'use client'; import { useEffect, useRef } from 'react'; import type { CalendarEventView } from '@/services/ScheduleService'; import { formatTime } from '@/lib/calendar/grid'; import { SOURCE_COLORS, SOURCE_LABELS, } from '@/components/calendar/sourceColors'; /** * 指定日のイベント詳細ダイアログ。 * セル内ではtruncateされるタイトルも、ここでは全文と説明を表示する。 * 開閉時にフォーカスをダイアログへ移し、閉じたら元の要素へ戻す。 */ export function EventDetailDialog({ date, events, onClose, }: { date: Date; events: CalendarEventView[]; onClose: () => void; }) { const dialogRef = useRef(null); useEffect(() => { const previouslyFocused = document.activeElement as HTMLElement | null; dialogRef.current?.focus(); return () => { previouslyFocused?.focus?.(); }; }, []); useEffect(() => { function onKey(e: KeyboardEvent) { if (e.key === 'Escape') onClose(); } window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [onClose]); const dateLabel = `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`; return (
e.stopPropagation()} role="dialog" aria-modal="true" aria-label={`${dateLabel}のイベント`} data-testid="calendar-detail-dialog" >

{dateLabel}

{events.length === 0 ? (

この日のイベントはありません。

) : ( events.map((e) => (

{e.title}

{SOURCE_LABELS[e.source] ?? e.source}

{formatTime(e.startAt)} {e.endAt ? ` 〜 ${formatTime(e.endAt)}` : ''}

{e.description && (

{e.description}

)}
)) )}
); }