import type { CalendarEvent } from './shared'; import { CalendarDays, MapPin, Repeat } from 'lucide-react'; import { useCalendarEvents, useSelectedCollection } from './useDavData'; import { useTranslation } from 'officerdev'; // Right panel of /calendar. Deliberately a grouped agenda list, not a month grid: the sidecar returns // events as they are stored, with RRULE unexpanded, so a grid would have to invent occurrences the server // never claimed existed. A list can show a repeating event honestly, as one entry with a "repeats" badge. const dayKey = (ev: CalendarEvent) => (ev.start ? ev.start.slice(0, 10) : ''); const formatDay = (iso: string) => { if (!iso) return 'No date'; const date = new Date(`${iso}T12:00:00`); if (Number.isNaN(date.getTime())) return iso; return date.toLocaleDateString(undefined, { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }); }; const formatTime = (ev: CalendarEvent) => { if (ev.allDay || !ev.start) return 'All day'; const start = new Date(ev.start); if (Number.isNaN(start.getTime())) return ''; const opts: Intl.DateTimeFormatOptions = { hour: '2-digit', minute: '2-digit' }; const end = ev.end ? new Date(ev.end) : null; if (!end || Number.isNaN(end.getTime())) return start.toLocaleTimeString(undefined, opts); return `${start.toLocaleTimeString(undefined, opts)} – ${end.toLocaleTimeString(undefined, opts)}`; }; export const CalendarView = () => { const { t } = useTranslation(); const { selected, isLoading: loadingCollections } = useSelectedCollection('calendar'); const { events, isLoading, error } = useCalendarEvents(selected?.path ?? null); if (loadingCollections) return ; if (!selected) return ; if (error) return ; if (isLoading) return ; if (events.length === 0) return ; const sorted = [...events].sort((a, b) => (a.start ?? '').localeCompare(b.start ?? '')); const days: Array<{ key: string; events: CalendarEvent[] }> = []; for (const ev of sorted) { const key = dayKey(ev); const last = days[days.length - 1]; if (last && last.key === key) last.events.push(ev); else days.push({ key, events: [ev] }); } return (
{days.map((day) => (

{formatDay(day.key)}

{day.events.map((ev) => (
{ev.summary || '(no title)'} {ev.rrule && ( repeats )}
{formatTime(ev)}
{ev.location && (
{ev.location}
)} {ev.description && (

{ev.description}

)}
))}
))}
); }; const Placeholder = ({ text }: { text: string }) => (
{text}
);