"use client"; import dynamic from "next/dynamic"; import { useParams, useRouter } from "next/navigation"; import { useState } from "react"; import { useIncident } from "@/lib/useIncidents"; import { useCallsByIncident } from "@/lib/useCalls"; import { useSystems } from "@/lib/useSystems"; import { useAuth } from "@/components/AuthProvider"; import { CallRow } from "@/components/CallRow"; import { c2api } from "@/lib/c2api"; import type { IncidentRecord } from "@/lib/types"; const MapView = dynamic(() => import("@/components/MapView"), { ssr: false }); const TYPE_COLORS: Record = { fire: "bg-red-900 text-red-300", police: "bg-blue-900 text-blue-300", ems: "bg-yellow-900 text-yellow-300", accident: "bg-orange-900 text-orange-300", other: "bg-gray-800 text-gray-300", }; function TypeBadge({ type }: { type: string | null }) { const cls = TYPE_COLORS[type ?? "other"] ?? TYPE_COLORS.other; return ( {type ?? "other"} ); } function StatusBadge({ status }: { status: IncidentRecord["status"] }) { return ( {status} ); } type Tab = "summary" | "units" | "details"; export default function IncidentDetailPage() { const params = useParams(); const id = params.id as string; const router = useRouter(); const { incident, loading } = useIncident(id); const { calls, loading: callsLoading } = useCallsByIncident(id); const { systems } = useSystems(); const { isAdmin } = useAuth(); const [tab, setTab] = useState("summary"); const [summarizing, setSummarizing] = useState(false); const [resolving, setResolving] = useState(false); const systemMap = Object.fromEntries(systems.map((s) => [s.system_id, s])); async function handleResolve() { setResolving(true); try { await c2api.updateIncident(id, { status: "resolved" }); } catch (e) { console.error(e); } finally { setResolving(false); } } async function handleSummarize() { setSummarizing(true); try { await c2api.summarizeIncident(id); } catch (e) { console.error(e); } finally { setSummarizing(false); } } if (loading) return

Loading…

; if (!incident) return

Incident not found.

; const displayTags = incident.tags.filter((t) => t !== "auto-generated"); return (
{/* Back */} {/* Header */}

{incident.title ?? "Incident"}

{isAdmin && (
{incident.status === "active" && ( )}
)}
{/* Tags */} {displayTags.length > 0 && (
{displayTags.map((t) => ( {t} ))}
)} {/* Map */} {incident.location_coords && (
)} {/* Two-panel body */}
{/* Left: tabs — Summary / Units / Details */}
{/* Tab bar */}
{(["summary", "units", "details"] as Tab[]).map((t) => ( ))}
{/* Tab content */}
{tab === "summary" && ( incident.summary ? (

{incident.summary}

) : (

No summary yet.{" "} {isAdmin && ( )}

) )} {tab === "units" && (

Units

{incident.units?.length > 0 ? (
{incident.units.map((u) => ( {u} ))}
) : (

None extracted.

)}

Vehicles

{incident.vehicles?.length > 0 ? (
{incident.vehicles.map((v) => ( {v} ))}
) : (

None extracted.

)}
)} {tab === "details" && (
{incident.location && (

Location

{incident.location}

)}

Started

{new Date(incident.started_at).toLocaleString()}

Last activity

{new Date(incident.updated_at).toLocaleString()}

{incident.talkgroup_ids?.length > 0 && (

Talkgroups

{incident.talkgroup_ids.join(", ")}

)} {incident.severity && (

Severity

{incident.severity}

)}

Total calls

{incident.call_ids.length}

)}
{/* Right: calls */}

Calls ({calls.length})

{callsLoading ? (

Loading…

) : calls.length === 0 ? (

No calls linked yet.

) : (
{calls.map((c) => ( ))}
Time Talkgroup System Node Duration Audio
)}
); }