// frontend/components/calendar/DayView.tsx — 일 뷰 (실제 날짜 기반: 그리드 + 집중 카드 + 어젠다) "use client"; import type { MouseEvent } from "react"; import { Icon } from "@/components/Icon"; import { HOURS, dayNum, monthNum, parseISO, timeOfPx, toMin, 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"; const PEOPLE_COLORS = ["var(--coral)", "var(--blue)", "var(--violet)"]; const WEEKDAYS_KO = ["일", "월", "화", "수", "목", "금", "토"]; function evSort(a: CalEvent, b: CalEvent): number { // 종일 먼저, 그다음 시작시각 순 if (!a.start && b.start) return -1; if (a.start && !b.start) return 1; if (!a.start && !b.start) return 0; return toMin(a.start) - toMin(b.start); } export function DayView({ events, focusBlocks, calMap, dayDate, todayDate, onOpen, onMeet, onSlotClick, onCommit, }: { events: CalEvent[]; focusBlocks: FocusBlockT[]; calMap: Record; dayDate: string; todayDate: string; onOpen: (ev: CalEvent, e: MouseEvent) => void; onMeet: (ev: CalEvent) => void; onSlotClick: (dateIso: string, time: string) => void; onCommit?: EvCommit; }) { const dayEvents = events.filter((e) => e.date === dayDate).sort(evSort); const dayFocus = focusBlocks .filter((b) => b.date === dayDate) .sort((a, b) => toMin(a.start) - toMin(b.start)); const wd = WEEKDAYS_KO[parseISO(dayDate).getDay()]; const isToday = dayDate === todayDate; const now = new Date(); const nowTop = topOf( `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`, ); return (
{HOURS.map((h) => (
{h}:00
))}
{ const rect = e.currentTarget.getBoundingClientRect(); onSlotClick(dayDate, timeOfPx(e.clientY - rect.top)); }} > {HOURS.map((h) => (
))} {isToday &&
} {dayFocus.map((b) => ( ))} {dayEvents .filter((e) => !e.start) .map((ev, ai) => ( ))} {dayEvents .filter((e) => e.start) .map((ev) => ( ))}
{dayFocus.length > 0 && (
오늘의 집중 모드 빈 시간에 맞춰 자동 배치했어요

오전 미팅 사이엔 가벼운 일을, 오후 빈 블록엔 딥 워크를 넣었어요.

{dayFocus.map((b) => (
{b.start}
{b.tag}
{b.title}
))}
)}
{monthNum(dayDate)}월 {dayNum(dayDate)}일 {wd}요일
일정 {dayEvents.length}개{isToday ? " · 오늘" : ""}
{dayEvents.length === 0 &&
이 날은 일정이 없어요.
} {dayEvents.map((ev) => (
onOpen(ev, e)} >
{ev.start ? ( <> {ev.start} {ev.end} ) : ( "종일" )}
{ev.title} {ev.soon && }
{" "} {calMap[ev.cal]?.name ?? "기타"} {ev.loc && ( <> · {ev.loc} )}
{ev.people.length > 0 && (
{ev.people.slice(0, 3).map((p, i) => (
{p[0]}
))} {ev.people.join(", ")}
)} {ev.note &&
{ev.note}
} {ev.actions.length > 0 && (
내가 맡기로 한 일
{ev.actions.map((a, i) => (
{a.text} {a.when}
))}
)} {ev.has_meeting && ( )}
))}
); }