From 89d5c46738c4ef4759a57e38bbf53eb99e304d70 Mon Sep 17 00:00:00 2001 From: Jio Date: Wed, 28 Jan 2026 22:24:40 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EA=B0=84=20=EB=9D=BC=EC=9A=B0=ED=8C=85=20=EB=B0=8F=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_business/calendar/calendar-content.tsx | 40 +++++++------- .../_business/components/CampaignCard.tsx | 16 ++++-- .../_business/components/MatchingCard.tsx | 53 +++++++++++-------- 3 files changed, 63 insertions(+), 46 deletions(-) diff --git a/src/routes/_main/_business/calendar/calendar-content.tsx b/src/routes/_main/_business/calendar/calendar-content.tsx index 305d100..d3f88f8 100644 --- a/src/routes/_main/_business/calendar/calendar-content.tsx +++ b/src/routes/_main/_business/calendar/calendar-content.tsx @@ -1,5 +1,4 @@ import { useState } from "react"; - import FilterBottomSheet from "../components/FilterBottomSheet"; import WeeklyCalendar from "../components/WeeklyCalendar"; import MonthlyCalendar from "../components/MonthlyCalendar"; @@ -25,8 +24,9 @@ export default function CalendarContent() {
+
+ {/* matchingSubTab을 type 프롭스로 그대로 전달 */} {matchingSubTab === "sent" ? ( <> - - - - + + + + ) : ( <> - - - - + + + + )}
- ) : (
- +
)} @@ -135,4 +135,4 @@ export default function CalendarContent() { ); -} +} \ No newline at end of file diff --git a/src/routes/_main/_business/components/CampaignCard.tsx b/src/routes/_main/_business/components/CampaignCard.tsx index 7576801..5a0d955 100644 --- a/src/routes/_main/_business/components/CampaignCard.tsx +++ b/src/routes/_main/_business/components/CampaignCard.tsx @@ -1,3 +1,4 @@ +import { useNavigate } from "@tanstack/react-router"; import BrandLogo from "../../../../assets/brand-logo.png"; import ArrowRight from "../../../../assets/arrow-right.svg"; import SearchIcon from "../../../../assets/search.svg"; @@ -20,6 +21,13 @@ export default function CampaignCard({ showButton = true, }: CampaignCardProps) { const BUTTON_WIDTH = "280px"; + + // 2. navigate 함수 선언 + const navigate = useNavigate(); + + const handleGoToCampaign = () => { + navigate({ to: "/campaign" }); + }; return (
@@ -62,20 +70,18 @@ export default function CampaignCard({
- {/* 캠페인 보기 버튼 */} + {/* 캠페인 보기 버튼 - onClick 이벤트 연결 */} {showButton && ( - {/* 채팅 버튼 */} - From a96ef0e75ac639322ab3a34e1e287c267c687bdf Mon Sep 17 00:00:00 2001 From: Jio Date: Fri, 30 Jan 2026 01:14:22 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=BA=A0=ED=8E=98=EC=9D=B8=20?= =?UTF-8?q?=EC=A0=9C=EC=95=88=20=EB=B0=8F=20=ED=98=84=ED=99=A9=20aPI=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 30 +++++ src/api/axois.ts | 21 ++++ src/hooks/queries/useCampaign.ts | 16 +++ .../_main/_business/campaign/api/campaign.ts | 22 ++++ .../_business/campaign/campaign-content.tsx | 106 ++++++++++++------ vite.config.ts | 8 ++ 7 files changed, 172 insertions(+), 32 deletions(-) create mode 100644 src/api/axois.ts create mode 100644 src/hooks/queries/useCampaign.ts create mode 100644 src/routes/_main/_business/campaign/api/campaign.ts diff --git a/package.json b/package.json index 4572bea..24b3d44 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@iconify/react": "^6.0.2", "@tanstack/react-query": "^5.90.16", "@tanstack/react-router": "^1.145.7", + "axios": "^1.13.4", "iconify": "^1.4.0", "react": "^19.2.0", "react-dom": "^19.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 857d27a..1513317 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@tanstack/react-router': specifier: ^1.145.7 version: 1.150.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + axios: + specifier: ^1.13.4 + version: 1.13.4 iconify: specifier: ^1.4.0 version: 1.4.0 @@ -1451,6 +1454,9 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axios@1.13.4: + resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==} + babel-dead-code-elimination@1.0.12: resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==} @@ -1822,6 +1828,15 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + for-each@0.3.5: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} @@ -2459,6 +2474,9 @@ packages: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} engines: {node: ^14.13.1 || >=16.0.0} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} @@ -4550,6 +4568,14 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 + axios@1.13.4: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + babel-dead-code-elimination@1.0.12: dependencies: '@babel/core': 7.28.6 @@ -5021,6 +5047,8 @@ snapshots: flatted@3.3.3: {} + follow-redirects@1.15.11: {} + for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -5629,6 +5657,8 @@ snapshots: pretty-bytes@6.1.1: {} + proxy-from-env@1.1.0: {} + psl@1.15.0: dependencies: punycode: 2.3.1 diff --git a/src/api/axois.ts b/src/api/axois.ts new file mode 100644 index 0000000..1bbe22a --- /dev/null +++ b/src/api/axois.ts @@ -0,0 +1,21 @@ +import axios from "axios"; + +export const axiosInstance = axios.create({ + // 1. baseURL을 "/"로 수정 + baseURL: "/", + headers: { + "Content-Type": "application/json", + }, +}); + +// 2. 인증 토큰 자동 삽입 +/* +axiosInstance.interceptors.request.use((config) => { + const token = localStorage.getItem("accessToken"); + + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; +}); +*/ \ No newline at end of file diff --git a/src/hooks/queries/useCampaign.ts b/src/hooks/queries/useCampaign.ts new file mode 100644 index 0000000..41210b6 --- /dev/null +++ b/src/hooks/queries/useCampaign.ts @@ -0,0 +1,16 @@ +import { useMutation } from "@tanstack/react-query"; +import { postCampaignRequest } from "../../routes/_main/_business/campaign/api/campaign"; + +export const useCreateCampaignMutation = () => { + return useMutation({ + mutationFn: postCampaignRequest, + onSuccess: (data) => { + alert("캠페인 제안이 완료되었습니다!"); + console.log("성공:", data); + }, + onError: (error) => { + alert("제안에 실패했습니다."); + console.error("에러:", error); + }, + }); +}; \ No newline at end of file diff --git a/src/routes/_main/_business/campaign/api/campaign.ts b/src/routes/_main/_business/campaign/api/campaign.ts new file mode 100644 index 0000000..550822a --- /dev/null +++ b/src/routes/_main/_business/campaign/api/campaign.ts @@ -0,0 +1,22 @@ +import { axiosInstance } from "../../../../../api/axois"; + +export interface CampaignRequest { + brandId: number; + campaignId: number | null; + campaignName: string; + description: string; + formats: { id: string }[]; + categories: { id: string; customValue?: string }[]; + tones: { id: string }[]; + involvements: { id: string }[]; + usageRanges: { id: string }[]; + rewardAmount: number; + productId: number; + startDate: string; + endDate: string; +} + +export const postCampaignRequest = async (data: CampaignRequest) => { + const response = await axiosInstance.post("/api/v1/campaigns/request", data); + return response.data; +}; \ No newline at end of file diff --git a/src/routes/_main/_business/campaign/campaign-content.tsx b/src/routes/_main/_business/campaign/campaign-content.tsx index f3afe47..ba90362 100644 --- a/src/routes/_main/_business/campaign/campaign-content.tsx +++ b/src/routes/_main/_business/campaign/campaign-content.tsx @@ -1,4 +1,5 @@ import { useState } from "react"; +import { useCreateCampaignMutation } from "../../../../hooks/queries/useCampaign"; import Header from "../../../../components/layout/Header"; import CampaignBrandCard from "../components/CampaignBrandCard"; @@ -12,31 +13,62 @@ import calendarIcon from "../../../../assets/icon-calender.svg"; export default function CampaignContent() { const [isContentOpen, setIsContentOpen] = useState(false); + + // 1. API 전송을 위한 상태 관리 + const [campaignData, setCampaignData] = useState({ + brandId: 1, + campaignId: null, // 신규 캠페인 + campaignName: "비플레인 클렌징 및 세럼 리뷰 콘텐츠", + description: "안녕하세요 크리에이터 비비 입니다! 비플레인의 가치가 제 채널에서 소개하는 뷰티 콘텐츠와 잘 맞닿아 있다고 생각되어 협찬을 제안드립니다.", + rewardAmount: 200000, + startDate: "2025-01-20", + endDate: "2025-01-30", + // 태그/형식 등은 초기값 혹은 API로 받아온 ID값 세팅 + formats: [{ id: "32000000-0000-0000-0000-000000000000" }], + categories: [{ id: "31310000-0000-0000-0000-000000000000", customValue: "성분 분석 리뷰" }], + tones: [ + { id: "31360000-0000-0000-0000-000000000000" }, + { id: "31330000-0000-0000-0000-000000000000" } + ], + involvements: [{ id: "32320000-0000-0000-0000-000000000000" }], + usageRanges: [{ id: "32350000-0000-0000-0000-000000000000" }], + productId: 5 + }); + + // 2. TanStack Query Mutation 사용 + const { mutate, isPending } = useCreateCampaignMutation(); + + const handleSubmit = () => { + // 실제 전송 로직 + mutate(campaignData); + }; return ( -
- {/* Header */} +
-
+
{/* 캠페인명 */} } + right={edit} > -
- 비플레인 클렌징 및 세럼 리뷰 콘텐츠 -
+ setCampaignData({...campaignData, campaignName: e.target.value})} + className="w-full p-4 bg-[var(--color-bg-w)] border border-[var(--color-text-gray5)] rounded-lg text-body1 focus:outline-none focus:border-blue-400" + />
{/* 캠페인 내용 */} setIsContentOpen(prev => !prev)}> +