import type { StoredEvent } from './useEventStorage' export type SectionKey = 'today' | 'thisWeek' | 'nextWeek' | 'later' | 'past' export interface DateGroup { dateKey: string label: string events: StoredEvent[] showSubheader: boolean } export interface EventSection { key: SectionKey label: string dateGroups: DateGroup[] emphasized: boolean } const SECTION_ORDER: SectionKey[] = ['today', 'thisWeek', 'nextWeek', 'later', 'past'] const SECTION_LABELS: Record = { today: 'Today', thisWeek: 'This Week', nextWeek: 'Next Week', later: 'Later', past: 'Past', } function startOfDay(date: Date): Date { const d = new Date(date) d.setHours(0, 0, 0, 0) return d } function endOfDay(date: Date): Date { const d = new Date(date) d.setHours(23, 59, 59, 999) return d } function endOfWeek(date: Date): Date { const d = new Date(date) const dayOfWeek = d.getDay() // 0=Sun, 1=Mon, ..., 6=Sat // ISO week: Monday is first day. End of week = Sunday. // If today is Sunday (0), end of week is today. // Otherwise, days until Sunday = 7 - dayOfWeek const daysUntilSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek d.setDate(d.getDate() + daysUntilSunday) return endOfDay(d) } function endOfNextWeek(date: Date): Date { const thisWeekEnd = endOfWeek(date) const d = new Date(thisWeekEnd) d.setDate(d.getDate() + 7) return endOfDay(d) } function toDateKey(date: Date): string { const y = date.getFullYear() const m = String(date.getMonth() + 1).padStart(2, '0') const d = String(date.getDate()).padStart(2, '0') return `${y}-${m}-${d}` } function formatDateLabel(date: Date): string { return new Intl.DateTimeFormat(undefined, { weekday: 'short', day: 'numeric', month: 'short', }).format(date) } function classifyEvent(eventDate: Date, todayStart: Date, todayEnd: Date, weekEnd: Date, nextWeekEnd: Date): SectionKey { if (eventDate < todayStart) return 'past' if (eventDate <= todayEnd) return 'today' if (eventDate <= weekEnd) return 'thisWeek' if (eventDate <= nextWeekEnd) return 'nextWeek' return 'later' } export function useEventGrouping(events: StoredEvent[], now: Date = new Date()): EventSection[] { const todayStart = startOfDay(now) const todayEnd = endOfDay(now) const weekEnd = endOfWeek(now) const nextWeekEnd = endOfNextWeek(now) // Classify events into sections const buckets: Record = { today: [], thisWeek: [], nextWeek: [], later: [], past: [], } for (const event of events) { const eventDate = new Date(event.dateTime) const section = classifyEvent(eventDate, todayStart, todayEnd, weekEnd, nextWeekEnd) buckets[section].push(event) } // Build sections const sections: EventSection[] = [] for (const key of SECTION_ORDER) { const sectionEvents = buckets[key] if (sectionEvents.length === 0) continue // Sort events const ascending = key !== 'past' sectionEvents.sort((a, b) => { const diff = new Date(a.dateTime).getTime() - new Date(b.dateTime).getTime() return ascending ? diff : -diff }) // Group by date const dateGroupMap = new Map() for (const event of sectionEvents) { const dateKey = toDateKey(new Date(event.dateTime)) const group = dateGroupMap.get(dateKey) if (group) { group.push(event) } else { dateGroupMap.set(dateKey, [event]) } } // Convert to DateGroup array (order preserved from sorted events) const dateGroups: DateGroup[] = [] for (const [dateKey, groupEvents] of dateGroupMap) { dateGroups.push({ dateKey, label: formatDateLabel(new Date(groupEvents[0]!.dateTime)), events: groupEvents, showSubheader: key !== 'today', }) } sections.push({ key, label: SECTION_LABELS[key], dateGroups, emphasized: key === 'today', }) } return sections }