import Link from 'next/link'; import { fmtDate, fmtDateTime } from '@/lib/format'; import type { EventRow } from '@/lib/types'; import { Confidence, EntityLinks, EventTypeBadge, eventColor } from './event-badge'; function dayKey(iso: string): string { return iso.slice(0, 10); } function dayHeading(key: string, today: string): string { if (key === today) return `Today · ${fmtDate(key)}`; const y = new Date(`${today}T00:00:00Z`); y.setUTCDate(y.getUTCDate() - 1); if (key === y.toISOString().slice(0, 10)) return `Yesterday · ${fmtDate(key)}`; return fmtDate(key); } function timeOnly(iso: string): string { const d = new Date(iso); if (Number.isNaN(d.getTime())) return '—'; return `${d.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', timeZone: 'UTC' })} UTC`; } /** One event row: time · type · title/summary/entities · source + confidence. Desktop = 4-column terminal grid; mobile = stacked. */ export function EventItem({ e, dense = false }: { e: EventRow; dense?: boolean }) { const href = `/events/${encodeURIComponent(e.id)}`; return (
  • {e.title} {e.summary && !dense &&

    {e.summary}

    }
    {e.source_url ? ( {e.source_name ?? e.source_id ?? 'Source'} ) : ( e.source_name ?? e.source_id ?? 'Source unavailable' )}
  • ); } /** Events grouped visually by UTC day. */ export function EventTimeline({ events, dense = false }: { events: EventRow[]; dense?: boolean }) { const today = new Date().toISOString().slice(0, 10); const groups: { day: string; items: EventRow[] }[] = []; for (const e of events) { const k = dayKey(e.event_time); const last = groups[groups.length - 1]; if (last && last.day === k) last.items.push(e); else groups.push({ day: k, items: [e] }); } return (
    {groups.map((g) => (

    {dayHeading(g.day, today)}

    {g.items.length} event{g.items.length > 1 ? 's' : ''}
      {g.items.map((e) => ( ))}
    ))}
    ); }