diff --git a/app/routes/business/calendar/api/calendar.ts b/app/routes/business/calendar/api/calendar.ts index 4df2c99..44b48e4 100644 --- a/app/routes/business/calendar/api/calendar.ts +++ b/app/routes/business/calendar/api/calendar.ts @@ -13,6 +13,7 @@ export interface CampaignCollaboration { endDate: string; keyword?: string; type: "APPLIED" | "SENT" | "RECEIVED"; + category?: string; } interface CollaborationResponse { diff --git a/app/routes/business/calendar/calendar-content.tsx b/app/routes/business/calendar/calendar-content.tsx index ee411bb..22950b9 100644 --- a/app/routes/business/calendar/calendar-content.tsx +++ b/app/routes/business/calendar/calendar-content.tsx @@ -205,6 +205,8 @@ export default function CalendarContent() { key={`${cp.campaignId}-${cp.proposalId}-${cp.status}`} campaignId={cp.campaignId} proposalId={cp.proposalId ?? undefined} + brandId={cp.brandId} + category={cp.category || "beauty"} type={cp.type} brand={cp.brandName} title={cp.title} diff --git a/app/routes/business/components/CampaignBrandCard.tsx b/app/routes/business/components/CampaignBrandCard.tsx index 74046a2..d709672 100644 --- a/app/routes/business/components/CampaignBrandCard.tsx +++ b/app/routes/business/components/CampaignBrandCard.tsx @@ -1,3 +1,4 @@ +import { useNavigate } from "react-router-dom"; import chatIcon from "../../../assets/chat-icon.svg"; import arrowRightIcon from "../../../assets/icon/arrow-right.svg"; @@ -8,6 +9,8 @@ interface CampaignBrandCardProps { brandTags?: string[]; brandImageUrl?: string; matchingRate?: number; + brandId?: number | string; + category?: string; } export default function CampaignBrandCard({ @@ -16,8 +19,19 @@ export default function CampaignBrandCard({ brandName, brandTags, brandImageUrl, - matchingRate // Props + matchingRate, + brandId, + category }: CampaignBrandCardProps) { + const navigate = useNavigate(); + const handleBrandClick = (e: React.MouseEvent) => { + e.stopPropagation(); + if (brandId && category) { + navigate(`/brand?brandId=${brandId}&domain=${category}`); + } else { + console.warn("brandId 또는 category 정보가 부족합니다."); + } + }; return (
{/* 상단 브랜드 정보 */} @@ -28,14 +42,21 @@ export default function CampaignBrandCard({ {brandName} -
+
-

+

{brandName || "브랜드명"}

- arrow +
-

+

{brandTags && brandTags.length > 0 ? brandTags.map(tag => `#${tag}`).join(" ") : "#태그정보없음"} @@ -43,7 +64,7 @@ export default function CampaignBrandCard({

-
+
매칭률 {matchingRate || 0}% diff --git a/app/routes/business/components/CampaignCard.tsx b/app/routes/business/components/CampaignCard.tsx index 27824f9..604392e 100644 --- a/app/routes/business/components/CampaignCard.tsx +++ b/app/routes/business/components/CampaignCard.tsx @@ -6,6 +6,8 @@ import Card from "../../../components/common/Card"; interface CampaignCardProps { brand: string; + brandId?: string | number; + category?: string; title: string; startDate: string; endDate: string; @@ -18,6 +20,8 @@ interface CampaignCardProps { export default function CampaignCard({ brand, + brandId, + category = "beauty", title, startDate, endDate, @@ -30,6 +34,14 @@ export default function CampaignCard({ const navigate = useNavigate(); + const handleBrandClick = (e: React.MouseEvent) => { + e.stopPropagation(); + if (brandId) { + // 2. 알려주신 경로 규칙 적용 (Query Parameter 방식) + navigate(`/brand?brandId=${brandId}&domain=${category}`); + } + }; + const handleDetailClick = () => { // 사용자가 제공한 라우팅 규칙에 따른 분기 로직 const id = proposalId || campaignId; @@ -62,7 +74,10 @@ export default function CampaignCard({
{/* 브랜드명 */} -
+
{brand} diff --git a/app/routes/business/proposal/received-proposal-content.tsx b/app/routes/business/proposal/received-proposal-content.tsx index b637df6..ad02f40 100644 --- a/app/routes/business/proposal/received-proposal-content.tsx +++ b/app/routes/business/proposal/received-proposal-content.tsx @@ -81,7 +81,7 @@ export default function ReceivedProposalContent() { }; const closeModal = () => { setModalType("none"); - setRejectReason(""); + setRejectReason(""); }; const handleRejectClick = () => setModalType("reject"); @@ -113,6 +113,13 @@ export default function ReceivedProposalContent() { const formatDate = (dateStr: string) => (dateStr || "").replace(/-/g, ". "); + const STATUS_TEXT_MAP: Record = { + REVIEWING: "검토 중", + MATCHED: "매칭 완료", + REJECTED: "거절됨", + CANCELED: "취소됨", + }; + if (isLoading) return ; if (!proposal) return
데이터를 찾을 수 없습니다.
; @@ -126,11 +133,13 @@ export default function ReceivedProposalContent() {

{proposal.title}

diff --git a/app/routes/business/proposal/sent-proposal-content.tsx b/app/routes/business/proposal/sent-proposal-content.tsx index 33309e1..e81e08a 100644 --- a/app/routes/business/proposal/sent-proposal-content.tsx +++ b/app/routes/business/proposal/sent-proposal-content.tsx @@ -1,6 +1,6 @@ import { useState, useEffect } from "react"; import { useSearchParams, useNavigate } from "react-router-dom"; -import { getProposalDetail, type ProposalDetail} from "./api/proposal"; +import { getProposalDetail, type ProposalDetail } from "./api/proposal"; import { getBrandSummary, type BrandSummary } from "./api/brand"; import { getProfileCard, type ProfileCard } from "./api/user"; import { cancelCampaignProposal } from "./api/proposal"; @@ -28,11 +28,18 @@ export default function ProposalContent() { const proposalId = searchParams.get("proposalId"); + const STATUS_TEXT_MAP: Record = { + REVIEWING: "검토 중", + MATCHED: "매칭 완료", + REJECTED: "거절됨", + CANCELED: "취소됨", + }; + useEffect(() => { if (!proposalId) { - setIsLoading(false); - return; - } + setIsLoading(false); + return; + } const fetchData = async () => { console.log("실제 넘길 ID:", proposalId); @@ -46,7 +53,7 @@ export default function ProposalContent() { setBrand(brandResult); } - const profileResult = await getProfileCard(); + const profileResult = await getProfileCard(); setProfileCard(profileResult); @@ -66,21 +73,21 @@ export default function ProposalContent() { const handleCancel = async () => { if (!proposalId) return; - + if (!window.confirm("제안을 취소하시겠습니까?")) return; try { const response = await cancelCampaignProposal(proposalId); - + if (response.isSuccess) { alert("캠페인 제안을 취소했습니다."); - navigate(-1); + navigate(-1); } } catch (error: unknown) { console.error("제안 취소 실패:", error); - + let errorMessage = "취소 중 오류가 발생했습니다."; - + if (error instanceof Error) { errorMessage = error.message; } else if (typeof error === "string") { @@ -100,11 +107,13 @@ export default function ProposalContent() {
@@ -113,7 +122,10 @@ export default function ProposalContent() {

제안 프로필

-
+
navigate("/mypage/profileCard")} + className="w-full p-4 bg-bluegray-2 rounded-2xl flex justify-between items-center border border-core-70 cursor-pointer active:scale-[0.98] transition-all" + >
profile @@ -204,16 +216,16 @@ export default function ProposalContent() {
- {/* 상태가 REVIEWING일 때만 취소 버튼 */} - {data.status === "REVIEWING" && ( - - )} -
+ {/* 상태가 REVIEWING일 때만 취소 버튼 */} + {data.status === "REVIEWING" && ( + + )} +
);