Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 3 additions & 50 deletions app/routes/business/calendar/api/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface CampaignCollaboration {
thumbnailUrl: string;
title: string;
status: "NONE" | "REVIEWING" | "MATCHED" | "REJECTED";
startDate: string; // "2026-02-01"
startDate: string;
endDate: string;
type: "APPLIED" | "SENT" | "RECEIVED";
}
Expand All @@ -26,57 +26,10 @@ export const getMyCollaborations = async (params?: {
startDate?: string;
endDate?: string;
}) => {
// axios -> axiosInstance로 수정

const response = await axiosInstance.get<CollaborationResponse>(
"/v1/campaigns/collaborations/me",
{ params }
);
return response.data.result;
};

/*export const MATCHING_DUMMY_DATA: CampaignCollaboration[] = [
{
campaignId: 1,
proposalId: "p1",
brandName: "라운드랩",
thumbnailUrl: "",
title: "자작나무 수분크림 체험단",
status: "MATCHED",
startDate: "2026-02-02",
endDate: "2026-02-07",
type: "SENT",
},
{
campaignId: 2,
proposalId: "p2",
brandName: "비플레인",
thumbnailUrl: "",
title: "'글로우업' 선크림 신제품 홍보",
status: "REVIEWING",
startDate: "2026-02-04",
endDate: "2025-02-05",
type: "RECEIVED",
},
{
campaignId: 3,
proposalId: "p3",
brandName: "그레이스유",
thumbnailUrl: "",
title: "봄 신상 코디 콘텐츠 제작",
status: "REVIEWING",
startDate: "2026-02-23",
endDate: "2026-02-24",
type: "RECEIVED",
},
{
campaignId: 4,
proposalId: "p4",
brandName: "이즈앤트리",
thumbnailUrl: "",
title: "비타민C 세럼 리뷰 캠페인",
status: "REJECTED",
startDate: "2026-02-01",
endDate: "2025-02-04",
type: "SENT",
},
];*/
};
52 changes: 29 additions & 23 deletions app/routes/business/calendar/calendar-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import MatchingCard from "../components/MatchingCard";
import MatchingTabSection from "../components/MatchingTabSection";
import dropdownIcon from "../../../assets/arrow-down.svg";
import EmptyState from "../components/EmptyState";
//import { MATCHING_DUMMY_DATA } from "../calendar/api/calendar";

export default function CalendarContent() {
const navigate = useNavigate();
Expand Down Expand Up @@ -41,13 +40,12 @@ export default function CalendarContent() {
fetchCampaigns();
}, [matchingSubTab]);

// 상태 변환 헬퍼 함수
const getStatusLabel = (status: CampaignCollaboration["status"]): "매칭" | "검토 중" | "거절" => {
switch (status) {
case "MATCHED":
return "매칭";
case "REVIEWING":
case "NONE":
case "NONE":
return "검토 중";
case "REJECTED":
return "거절";
Expand All @@ -73,37 +71,44 @@ export default function CalendarContent() {

const todayStr = new Date().toISOString().split('T')[0];
const currentMonthStr = todayStr.substring(0, 7);

const calendarEvents = campaigns.filter(item => item.status === "MATCHED");

const filteredList = campaigns.filter((item) => {
if (item.status !== "MATCHED") return false;

if (activeTab === "today") {
return item.startDate <= todayStr && item.endDate >= todayStr;
} else {
const startMonth = item.startDate.substring(0, 7);
const endMonth = item.endDate.substring(0, 7);
return startMonth <= currentMonthStr && endMonth >= currentMonthStr;
}
return item.startDate.includes(currentMonthStr) || item.endDate.includes(currentMonthStr);
});

const handleCardClick = (item: CampaignCollaboration) => {
const proposalId = item.proposalId || item.campaignId;
const proposalId = item.proposalId || item.campaignId;

if (item.status === "REJECTED") {
navigate(`/rejection?proposalId=${proposalId}`);
return;
}

// 1. 거절 상태일 때
if (item.status === "REJECTED") {
navigate(`/rejection?proposalId=${proposalId}`);
return;
}
if (item.type === "APPLIED") {
navigate(`/business/proposal?type=applied&applicationId=${proposalId}`);
return;
}

// 2. 지원하기 타입일 때
if (item.type === "APPLIED") {
navigate(`/business/proposal?type=applied&applicationId=${proposalId}`);
return;
}
if (item.type === "RECEIVED") {
navigate(`/business/proposal?type=received&proposalId=${proposalId}`);
return;
}

// 3. 그 외 기본
navigate(`/business/proposal?proposalId=${proposalId}`);
};
navigate(`/business/proposal?type=sent&proposalId=${proposalId}`);
};

return (
<div className="flex flex-col w-full min-h-screen bg-bluegray-1">
{/* 탭 네비게이션 */}
<div className="flex w-full bg-bg-w border-b border-text-gray5">
<button
onClick={() => setMainTab("collaboration")}
Expand All @@ -129,7 +134,7 @@ export default function CalendarContent() {

<main className="flex flex-col flex-1">
{mainTab === "collaboration" ? (
/* [A] 협업 현황 */
/* 협업 현황 */
<div className="flex flex-col gap-6 px-4 py-6">
{/* 주간 캘린더 연동 */}
<section className="flex flex-col gap-3">
Expand All @@ -142,7 +147,6 @@ export default function CalendarContent() {
<MonthlyCalendar events={calendarEvents} />
</section>

{/* 하단 리스트 섹션 */}
<section className="flex flex-col gap-4">
<div className="flex items-center gap-2">
<button
Expand All @@ -167,10 +171,11 @@ export default function CalendarContent() {
<CampaignCard
key={cp.campaignId || cp.proposalId}
campaignId={cp.campaignId}
proposalId={cp.proposalId ?? undefined}
type={cp.type}
brand={cp.brandName}
title={cp.title}
logo={cp.thumbnailUrl}

startDate={cp.startDate.split('-').slice(1).join('.')}
endDate={cp.endDate.split('-').slice(1).join('.')}
/>
Expand All @@ -184,7 +189,7 @@ export default function CalendarContent() {
</section>
</div>
) : (
/* [B] 매칭 현황 */
/* 매칭 현황 */
<div className="flex flex-col flex-1">
<MatchingTabSection
subTab={matchingSubTab}
Expand Down Expand Up @@ -216,6 +221,7 @@ export default function CalendarContent() {
status={getStatusLabel(item.status)}
date={item.startDate.split('-').slice(1).join('.') + "." + item.startDate.split('-')[0].slice(2)}
actionLabel={item.status === "REJECTED" ? "거절 사유 보기" : "제안 보기"}
logo={item.thumbnailUrl}
onClick={() => handleCardClick(item)}
/>
))
Expand Down
2 changes: 0 additions & 2 deletions app/routes/business/campaign/$campaignId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ export default function CampaignContent() {
loadData();
}, [campaignId]);

// 데이터 로딩 전
if (!data) return <div className="p-10 text-center">로딩 중...</div>;

// 태그들을 예쁘게 합쳐주는 함수 (예: ["릴스", "숏폼"] -> "릴스, 숏폼")
const formatTags = (tags: { name: string }[]) => tags.map(t => t.name).join(", ");

return (
Expand Down
24 changes: 11 additions & 13 deletions app/routes/business/components/CampaignBrandCard.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import brandLogo from "../../../assets/brand-logo.png";
import chatIcon from "../../../assets/chat-icon.svg";
import arrowRightIcon from "../../../assets/icon/arrow-right.svg";

interface CampaignBrandCardProps {
showChatSection?: boolean;
statusText?: string; // '보낸 제안' 또는 '검토 중'
statusText?: string;
brandName?: string;
brandTags?: string[];

brandTags?: string[];
brandImageUrl?: string;
matchingRate?: number;
}

export default function CampaignBrandCard({
showChatSection = true,
statusText = "보낸 제안",
showChatSection,
statusText,
brandName,
brandTags
brandTags,
brandImageUrl,
matchingRate // Props
}: CampaignBrandCardProps) {
return (
<section className="bg-bg-w p-5 flex flex-col gap-4 -mx-4 -mt-6">
Expand All @@ -23,11 +25,7 @@ export default function CampaignBrandCard({
<div className="flex gap-4">
{/* 브랜드 로고 박스 */}
<div className="w-[64px] h-[64px] flex items-center justify-center overflow-hidden border border-text-gray5 rounded-lg">
<img
src={brandLogo}
alt="beplain"
className="w-full h-full object-contain"
/>
<img src={brandImageUrl} alt={brandName} className="w-full h-full object-cover" />
</div>

<div className="flex flex-col gap-1">
Expand All @@ -48,7 +46,7 @@ export default function CampaignBrandCard({
<div className="flex flex-col items-end gap-1">
<div className="flex items-baseline gap-1">
<span className="text-title5 text-core-1">매칭률</span>
<span className="text-title6 text-core-1">99%</span>
<span className="text-title6 text-core-1">{matchingRate || 0}%</span>
</div>
<span className="text-callout1 text-core-1 mt-3">{statusText}</span>
</div>
Expand Down
39 changes: 24 additions & 15 deletions app/routes/business/components/CampaignCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ interface CampaignCardProps {
logo?: string;
showButton?: boolean;
campaignId?: string | number;
proposalId?: string | number;
type?: "SENT" | "RECEIVED" | "APPLIED";
}

export default function CampaignCard({
Expand All @@ -21,12 +23,27 @@ export default function CampaignCard({
endDate,
logo,
showButton = true,
campaignId = 1,
campaignId,
proposalId,
type = "SENT",
}: CampaignCardProps) {

const navigate = useNavigate();

// 로고 컴포넌트
const handleDetailClick = () => {
// 사용자가 제공한 라우팅 규칙에 따른 분기 로직
const id = proposalId || campaignId;

if (type === "APPLIED") {
navigate(`/business/proposal?type=applied&applicationId=${id}`);
} else if (type === "RECEIVED") {
navigate(`/business/proposal?type=received&proposalId=${id}`);
} else {
// 기본값 또는 SENT
navigate(`/business/proposal?type=sent&proposalId=${id}`);
}
};

const Logo = (
<div className="w-[72px] h-[72px] flex items-center justify-center border border-gray-100 rounded-lg overflow-hidden">
<img
Expand All @@ -39,10 +56,8 @@ export default function CampaignCard({

return (
<Card image={Logo}>
{/* 1. 컨테이너: 세로 배치, 간격 10px, 하단 정렬 */}
<div className="flex flex-col justify-end items-end gap-[10px] w-full self-stretch">

{/* 2. 상단 정보 섹션 */}
<div className="flex flex-col w-full gap-1">
{/* 브랜드명 */}
<div className="flex items-center gap-1">
Expand All @@ -52,7 +67,7 @@ export default function CampaignCard({
<img src={ArrowRight} alt="이동" className="w-4 h-4 object-contain" />
</div>

{/* 제목 및 날짜: 양 끝 정렬 */}
{/* 제목 및 날짜 */}
<div className="flex justify-between items-start w-full">
<p className="text-[13px] text-text-gray2 truncate flex-1 leading-tight mr-2">
{title}
Expand All @@ -64,20 +79,14 @@ export default function CampaignCard({
</div>
</div>

{/* 3. 캠페인 보기 버튼: 디자인 규격에 맞춰 높이와 너비 조정 */}
{/* 캠페인 보기 버튼 */}
{showButton && (
<button
onClick={() => navigate(`/business/campaign/${campaignId}`)}
onClick={handleDetailClick}
className="flex items-center justify-center bg-[#EBEEFB] rounded-[6px] transition-colors hover:bg-[#DEE2F5] w-full h-[32px] gap-[4px]"
>
<img
src={SearchIcon}
alt="돋보기"
className="w-3.5 h-3.5 object-contain"
/>
<span className="text-[13px] font-medium text-text-black">
캠페인 보기
</span>
<img src={SearchIcon} alt="돋보기" className="w-3.5 h-3.5 object-contain" />
<span className="text-[13px] font-medium text-text-black">캠페인 보기</span>
</button>
)}
</div>
Expand Down
10 changes: 4 additions & 6 deletions app/routes/business/components/FilterBottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ export default function FilterBottomSheet({
if (!isOpen) return null;

return (
/* 최상위 컨테이너 */
<div className="fixed inset-0 z-50 flex flex-col items-center justify-end">

{/* 배경 오버레이 */}

<div
className="absolute inset-0 bg-black/40"
onClick={onClose}
Expand All @@ -33,14 +31,14 @@ export default function FilterBottomSheet({
<div
className="relative bg-[var(--color-bg-w)] rounded-t-[24px] overflow-hidden animate-slide-up w-full max-w-[430px] h-[530px] flex flex-col"
>
{/* 1. 헤더 영역 */}
{/* 헤더 영역 */}
<div className="px-4 pt-8 pb-4">
<div className="inline-block border-b-2 border-[var(--color-core-1)] pb-1">
<span className="text-title7 text-[var(--color-text-black)]">정렬 필터</span>
</div>
</div>

{/* 2. 필터 옵션 영역 */}
{/* 필터 옵션 영역 */}
<div className="w-full bg-[var(--color-bluegray-1)] py-4">
<div className="flex items-center justify-start gap-8 px-4">
{FILTERS.map((filter) => (
Expand All @@ -59,7 +57,7 @@ export default function FilterBottomSheet({
</div>
</div>

{/* 3. 하단 적용하기 버튼 */}
{/* 하단 적용하기 버튼 */}
<div className="mt-auto px-4 pb-10">
<button
onClick={() => {
Expand Down
Loading
Loading