/** * TimelineView — chronological event list grouped by decade with filter controls. */ "use client"; import Link from "next/link"; import { useEffect, useMemo, useState } from "react"; interface TimelineEntry { entity_class: string; entity_id: string; canonical_name: string; date_start: string | null; date_end: string | null; primary_location: string | null; narrative_summary: string | null; href: string; } export function TimelineView({ initialSearch }: { initialSearch?: string }) { const [q, setQ] = useState(initialSearch ?? ""); const [from, setFrom] = useState("1940"); const [to, setTo] = useState("2026"); const [data, setData] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); const params = new URLSearchParams({ class: "event", from, to, limit: "500", }); if (q.trim()) params.set("q", q.trim()); fetch(`/api/timeline?${params}`) .then((r) => r.json()) .then((j: { entries: TimelineEntry[] }) => { setData(j.entries ?? []); setLoading(false); }) .catch(() => setLoading(false)); }, [q, from, to]); const byDecade = useMemo(() => { const map = new Map(); for (const e of data) { const year = (e.date_start ?? "").slice(0, 4); if (!year) continue; const decade = `${year.slice(0, 3)}0s`; if (!map.has(decade)) map.set(decade, []); map.get(decade)!.push(e); } return Array.from(map.entries()).sort(([a], [b]) => a.localeCompare(b)); }, [data]); return (
setQ(e.target.value)} placeholder="ex. Roswell, Nimitz, Hoover..." className="w-full bg-transparent border border-[rgba(0,255,156,0.20)] focus:border-[#00ff9c] rounded px-2 py-1.5 font-mono text-sm text-[#c8d4e6] outline-none" />
setFrom(e.target.value)} placeholder="1940" className="w-20 bg-transparent border border-[rgba(0,255,156,0.20)] focus:border-[#00ff9c] rounded px-2 py-1.5 font-mono text-sm text-[#c8d4e6] outline-none" />
setTo(e.target.value)} placeholder="2026" className="w-20 bg-transparent border border-[rgba(0,255,156,0.20)] focus:border-[#00ff9c] rounded px-2 py-1.5 font-mono text-sm text-[#c8d4e6] outline-none" />
{loading ? "…" : `${data.length} eventos`}
{byDecade.map(([decade, items]) => (

{decade} · {items.length}

    {items.map((e) => (
  1. {e.date_start} {e.canonical_name} {e.primary_location && ( {e.primary_location} )}
    {e.narrative_summary && (

    {e.narrative_summary}

    )}
  2. ))}
))}
{!loading && data.length === 0 && (
nenhum evento encontrado nesse filtro
)}
); }