// frontend/components/calendar/WeekView.tsx — 주 뷰 (실제 날짜 기반 시간 그리드) "use client"; import type { MouseEvent } from "react"; import { HOURS, dayNum, timeOfPx, topOf } from "@/lib/calendar/time"; import type { CalEvent, Calendar, FocusBlock as FocusBlockT } from "@/lib/calendar/types"; import { EvBlock, type EvCommit } from "./EvBlock"; import { FocusBlock } from "./FocusBlock"; function nowTopPx(): number { const d = new Date(); return topOf(`${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`); } export function WeekView({ events, focusBlocks, calMap, weekDates, weekdays, todayDate, onOpen, onSlotClick, onCommit, }: { events: CalEvent[]; focusBlocks: FocusBlockT[]; calMap: Record; weekDates: string[]; // ISO 7개(일~토) weekdays: string[]; todayDate: string; onOpen: (ev: CalEvent, e: MouseEvent) => void; onSlotClick: (dateIso: string, time: string) => void; onCommit?: EvCommit; }) { const nowTop = nowTopPx(); // 빈 시간 슬롯 클릭 → 생성. 이벤트/집중 블록은 stopPropagation 으로 제외됨. const slotClick = (iso: string) => (e: MouseEvent) => { const rect = e.currentTarget.getBoundingClientRect(); onSlotClick(iso, timeOfPx(e.clientY - rect.top)); }; return (
{weekDates.map((iso, i) => (
{weekdays[i]}
{dayNum(iso)}
))}
{HOURS.map((h) => (
{h}:00
))}
{weekDates.map((iso, i) => { const dayEvents = events.filter((e) => e.date === iso); const dayAllDay = dayEvents.filter((e) => !e.start); const dayTimed = dayEvents.filter((e) => e.start); const dayFocus = focusBlocks.filter((b) => b.date === iso); return (
{HOURS.map((h) => (
))} {iso === todayDate &&
} {dayFocus.map((b) => ( ))} {dayAllDay.map((ev, ai) => ( ))} {dayTimed.map((ev) => ( ))}
); })}
); }