diff --git a/app/routes/business/calendar/api/calendar.ts b/app/routes/business/calendar/api/calendar.ts new file mode 100644 index 0000000..9f4ab67 --- /dev/null +++ b/app/routes/business/calendar/api/calendar.ts @@ -0,0 +1,35 @@ +import { axiosInstance } from "../../../../api/axios"; + +export interface CampaignCollaboration { + campaignId: number; + proposalId: string | null; + brandName: string; + thumbnailUrl: string; + title: string; + status: "NONE" | "REVIEWING" | "MATCHED" | "REJECTED"; + startDate: string; // "2026-02-01" + endDate: string; + type: "APPLIED" | "SENT" | "RECEIVED"; +} + +interface CollaborationResponse { + isSuccess: boolean; + code: string; + message: string; + result: CampaignCollaboration[]; +} + +// 협업 내역 조회 API +export const getMyCollaborations = async (params?: { + type?: "APPLIED" | "SENT" | "RECEIVED"; + status?: "NONE" | "REVIEWING" | "MATCHED" | "REJECTED"; + startDate?: string; + endDate?: string; +}) => { + // axios -> axiosInstance로 수정 + const response = await axiosInstance.get( + "/api/v1/campaigns/collaborations/me", + { params } + ); + return response.data.result; +}; \ No newline at end of file diff --git a/app/routes/business/calendar/calendar-content.tsx b/app/routes/business/calendar/calendar-content.tsx index 854dc53..e8b9930 100644 --- a/app/routes/business/calendar/calendar-content.tsx +++ b/app/routes/business/calendar/calendar-content.tsx @@ -1,5 +1,6 @@ -import { useState } from "react"; - +import { useState, useEffect } from "react"; +import { getMyCollaborations } from "./api/calendar"; +import type { CampaignCollaboration } from "./api/calendar"; import FilterBottomSheet from "../components/FilterBottomSheet"; import WeeklyCalendar from "../components/WeeklyCalendar"; import MonthlyCalendar from "../components/MonthlyCalendar"; @@ -10,6 +11,7 @@ import MatchingTabSection from "../components/MatchingTabSection"; import dropdownIcon from "../../../assets/arrow-down.svg"; import EmptyState from "../components/EmptyState"; + export default function CalendarContent() { const [mainTab, setMainTab] = useState<"collaboration" | "matching">("collaboration"); const [activeTab, setActiveTab] = useState<"thisMonth" | "today">("thisMonth"); @@ -19,6 +21,39 @@ export default function CalendarContent() { const hasData = true; + // API 데이터 상태 + const [campaigns, setCampaigns] = useState([]); + const [isLoading, setIsLoading] = useState(true); + // 데이터 로드 + useEffect(() => { + const fetchCampaigns = async () => { + try { + setIsLoading(true); + // 협업 현황 조회를 위해 전체 데이터를 가져옵니다. + const data = await getMyCollaborations(); + setCampaigns(data); + } catch (error) { + console.error("캠페인 로드 실패:", error); + } finally { + setIsLoading(false); + } + }; + + fetchCampaigns(); + }, []); + + // [필터링 로직] + const todayStr = new Date().toISOString().split('T')[0]; + const currentMonthStr = todayStr.substring(0, 7); // "2026-02" + + const filteredList = campaigns.filter((item) => { + if (activeTab === "today") { + return item.startDate <= todayStr && item.endDate >= todayStr; + } + // 이번달 기준 (시작일이나 종료일이 이번 달에 포함된 경우) + return item.startDate.includes(currentMonthStr) || item.endDate.includes(currentMonthStr); + }); + return (
{/* 탭 네비게이션 */} @@ -49,15 +84,18 @@ export default function CalendarContent() { {mainTab === "collaboration" ? ( /* [A] 협업 현황 */
+ {/* 주간 캘린더 연동 */}

이번주 일정

- +

이번달 일정

- +
+ + {/* 하단 리스트 섹션 */}
- - + {isLoading ? ( +

로딩 중...

+ ) : filteredList.length > 0 ? ( + filteredList.map((cp) => ( + 02.01) + startDate={cp.startDate.split('-').slice(1).join('.')} + endDate={cp.endDate.split('-').slice(1).join('.')} + /> + )) + ) : ( +
+ +
+ )}
diff --git a/app/routes/business/components/CampaignCard.tsx b/app/routes/business/components/CampaignCard.tsx index 4f02457..48de4b8 100644 --- a/app/routes/business/components/CampaignCard.tsx +++ b/app/routes/business/components/CampaignCard.tsx @@ -24,7 +24,6 @@ export default function CampaignCard({ campaignId = 1, }: CampaignCardProps) { const navigate = useNavigate(); - const BUTTON_WIDTH = '280px'; // 로고 컴포넌트 const Logo = ( @@ -39,39 +38,41 @@ export default function CampaignCard({ return ( -
- {/* 브랜드 + 제목/날짜 */} -
+ {/* 1. 컨테이너: 세로 배치, 간격 10px, 하단 정렬 */} +
+ + {/* 2. 상단 정보 섹션 */} +
+ {/* 브랜드명 */}
- {brand} + + {brand} + 이동
+ {/* 제목 및 날짜: 양 끝 정렬 */}
-

+

{title}

-
- {startDate}.25 - {endDate}.25 +
+ {startDate} + {endDate}
- {/* 캠페인 보기 버튼 */} + {/* 3. 캠페인 보기 버튼: 디자인 규격에 맞춰 높이와 너비 조정 */} {showButton && ( - 2025년 07월 + {year}년 {String(month).padStart(2, "0")}월 -
@@ -33,57 +67,44 @@ export default function MonthlyCalendar() { {/* 날짜 그리드 */}
- {allSlots.map((day, index) => ( -
-
- {day && ( - - {day} - - )} -
-
- ))} -
+ {allSlots.map((day, index) => { + const dayEvents = getEventsForDay(day); + const isToday = day === new Date().getDate() && month === (new Date().getMonth() + 1) && year === new Date().getFullYear(); - {/* 일정 바 */} -
- {/* 비플레인 */} -
- 비플레인 -
+ return ( +
+ {/* 날짜 표시 */} +
+ {day && ( + + {day} + + )} +
- {/* 라운드랩 */} -
- 라운드랩 -
+ {/* 해당 날짜의 일정 바 (이벤트가 있을 때만 표시) */} +
+ {dayEvents.slice(0, 2).map((event, idx) => ( +
+ {event.brandName} +
+ ))} + {dayEvents.length > 2 && ( + +{dayEvents.length - 2} + )} +
+
+ ); + })}
-
); -} +} \ No newline at end of file diff --git a/app/routes/business/components/WeeklyCalendar.tsx b/app/routes/business/components/WeeklyCalendar.tsx index bed289a..1e20c1d 100644 --- a/app/routes/business/components/WeeklyCalendar.tsx +++ b/app/routes/business/components/WeeklyCalendar.tsx @@ -1,7 +1,51 @@ +import type { CampaignCollaboration } from "../calendar/api/calendar"; +import { useMemo } from "react"; + +interface WeeklyCalendarProps { + events: CampaignCollaboration[]; // 이 부분을 추가하여 props를 정의합니다. +} + const WEEK_DAYS = ["일", "월", "화", "수", "목", "금", "토"]; -export default function WeeklyCalendar() { - const dates = [6, 7, 8, 9, 10, 11, 12]; +export default function WeeklyCalendar({ events }: WeeklyCalendarProps) { + console.log("주간 일정 데이터:", events); + + // 1. 이번 주 날짜 배열 생성 (일~토) + const weekDates = useMemo(() => { + const now = new Date(); + const dayOfWeek = now.getDay(); // 오늘 요일 (0: 일, 1: 월...) + const startOfWeek = new Date(now); + startOfWeek.setDate(now.getDate() - dayOfWeek); // 이번 주 일요일 계산 + + return Array.from({ length: 7 }, (_, i) => { + const date = new Date(startOfWeek); + date.setDate(startOfWeek.getDate() + i); + return date; + }); + }, []); + + const todayStr = new Date().toISOString().split("T")[0]; + + // 2. 일정 바 위치 계산 함수 + const getEventStyle = (startDate: string, endDate: string, index: number) => { + const start = new Date(startDate); + const end = new Date(endDate); + const weekStart = weekDates[0]; + const weekEnd = weekDates[6]; + + // 이번 주 범위에 포함되는지 확인 + const displayStart = start < weekStart ? 0 : start.getDay(); + const displayEnd = end > weekEnd ? 6 : end.getDay(); + const duration = displayEnd - displayStart + 1; + + return { + left: `${(displayStart * 100) / 7}%`, + width: `${(duration * 100) / 7}%`, + top: `${index * 26}px`, // 겹치지 않게 위아래 간격 조정 + height: "22px", + borderRadius: "11px", + }; + }; return (
@@ -14,50 +58,36 @@ export default function WeeklyCalendar() { {/* 날짜 그리드 */}
- {dates.map((date) => ( -
-
- {date} + {weekDates.map((dateObj) => { + const dateStr = dateObj.toISOString().split("T")[0]; + const isToday = dateStr === todayStr; + return ( +
+
+ {dateObj.getDate()} +
-
- ))} + ); + })}
{/* 일정 바 컨테이너 */}
- {/* 비플레인 */} -
- 비플레인 -
- - {/* 라운드랩 */} -
- 라운드랩 -
+ {events.slice(0, 3).map((event, idx) => ( // 최대 3개까지만 노출 예시 +
+ {event.brandName} +
+ ))}
);