From 510cd285eceb71a04c17e69a5dd5120d3c7ed8b7 Mon Sep 17 00:00:00 2001 From: Siul Date: Fri, 10 Jul 2026 15:42:36 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20=EA=B7=B8=EB=A6=AC?= =?UTF-8?q?=EB=93=9C=20=EC=9A=94=EC=9D=BC=20=ED=97=A4=EB=8D=94=EC=97=90=20?= =?UTF-8?q?=EC=8B=A4=EC=A0=9C=20=EB=82=A0=EC=A7=9C(M/D)=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=20=EC=B6=94=EA=B0=80=20(#123)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit formatDayWithDate로 초대/결과 화면 요일 라벨에 날짜를 붙이고, 잘못된 dayCode를 방어하며 ICS 100KB 제한을 isIcs에만 적용한다. --- src/app/schedule/[id]/ScheduleRoomClient.tsx | 48 ++++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/app/schedule/[id]/ScheduleRoomClient.tsx b/src/app/schedule/[id]/ScheduleRoomClient.tsx index 16408a7..2102d20 100644 --- a/src/app/schedule/[id]/ScheduleRoomClient.tsx +++ b/src/app/schedule/[id]/ScheduleRoomClient.tsx @@ -64,6 +64,30 @@ const DAY_LABELS: Record = { SUN: "일요일", }; +const DAY_CODE_TO_JS_DAY: Record = { + SUN: 0, + MON: 1, + TUE: 2, + WED: 3, + THU: 4, + FRI: 5, + SAT: 6, +}; + +/** 요일 코드에 가장 가까운 날짜를 붙여 표시 (예: "월요일 7/14") */ +function formatDayWithDate(dayCode: DayCode): string { + const jsDay = DAY_CODE_TO_JS_DAY[dayCode]; + const label = DAY_LABELS[dayCode] ?? dayCode; + if (jsDay === undefined) { + return label; + } + const now = new Date(); + const diff = (jsDay - now.getDay() + 7) % 7; + const target = new Date(now); + target.setDate(now.getDate() + diff); + return `${label} ${target.getMonth() + 1}/${target.getDate()}`; +} + export function ScheduleRoomClient({ scheduleId, hostToken, @@ -378,7 +402,7 @@ export function ScheduleRoomClient({ slots.push({ key: `${day}-${hour}`, slot: { day, startHour: hour, endHour: hour + 1 }, - label: `${DAY_LABELS[day]} ${formatHour(hour)}-${formatHour(hour + 1)}`, + label: `${formatDayWithDate(day)} ${formatHour(hour)}-${formatHour(hour + 1)}`, }); } } @@ -488,7 +512,7 @@ export function ScheduleRoomClient({ ); return; } - if (!isImage && file.size > 100 * 1024) { + if (isIcs && file.size > 100 * 1024) { setImportMessage("ICS 파일 크기는 100KB 이하여야 합니다."); return; } @@ -741,7 +765,7 @@ export function ScheduleRoomClient({ key={day} className="flex h-8 items-center justify-center pb-2 text-center text-sm font-bold text-brand-purple" > - {DAY_LABELS[day]} + {formatDayWithDate(day)} ))} @@ -1258,7 +1282,7 @@ function HostResultPanel({ }, [schedule.candidateStartHour, schedule.candidateEndHour]); const heatmapDays = useMemo(() => { - return schedule.candidateDays.map((d) => DAY_LABELS[d] || d); + return schedule.candidateDays.map((d) => formatDayWithDate(d)); }, [schedule.candidateDays]); const heatmapColors = useMemo(() => { @@ -1588,23 +1612,17 @@ function HostResultPanel({ ); } -const DAY_CODE_TO_JS_DAY: Record = { - SUN: 0, - MON: 1, - TUE: 2, - WED: 3, - THU: 4, - FRI: 5, - SAT: 6, -}; - // 확정 슬롯은 요일 기반({day,startHour,endHour})이므로, // 다가오는 해당 요일의 실제 날짜로 환산해 캘린더 일정 start/end를 만든다. function nextOccurrence(slot: TimeSlot): { start: Date; end: Date } { const now = new Date(); const start = new Date(now); start.setHours(slot.startHour, 0, 0, 0); - let diff = (DAY_CODE_TO_JS_DAY[slot.day] - now.getDay() + 7) % 7; + const jsDay = DAY_CODE_TO_JS_DAY[slot.day]; + if (jsDay === undefined) { + throw new Error(`Invalid day code: ${slot.day}`); + } + let diff = (jsDay - now.getDay() + 7) % 7; if (diff === 0 && start.getTime() <= now.getTime()) { diff = 7; // 오늘 해당 요일이지만 시작 시간이 이미 지났으면 다음 주 }