"use client"; import { useState } from "react"; import type { CallRecord } from "@/lib/types"; import { c2api } from "@/lib/c2api"; interface Props { call: CallRecord; systemName?: string; isAdmin?: boolean; } function duration(started: string, ended: string | null): string { if (!ended) return "active"; const ms = new Date(ended).getTime() - new Date(started).getTime(); const s = Math.floor(ms / 1000); return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m ${s % 60}s`; } const TAG_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", }; export function CallRow({ call, systemName, isAdmin }: Props) { const [expanded, setExpanded] = useState(false); const [showOriginal, setShowOriginal] = useState(false); const [editing, setEditing] = useState(false); const [editText, setEditText] = useState(""); const [saving, setSaving] = useState(false); const isActive = call.status === "active"; const hasDetails = call.transcript || call.transcript_corrected || (call.tags && call.tags.length > 0) || call.incident_id; const displayTranscript = (!showOriginal && call.transcript_corrected) ? call.transcript_corrected : call.transcript; const hasBoth = !!(call.transcript && call.transcript_corrected); const hasSegments = call.segments && call.segments.length > 1; function startEdit() { setEditText(call.transcript_corrected ?? call.transcript ?? ""); setEditing(true); } async function saveEdit(e: React.MouseEvent) { e.stopPropagation(); setSaving(true); try { await c2api.patchTranscript(call.call_id, editText); setEditing(false); } catch (err) { console.error(err); } finally { setSaving(false); } } return ( <> hasDetails && setExpanded((v) => !v)} > {new Date(call.started_at).toLocaleTimeString()} {call.talkgroup_name || call.talkgroup_id || "—"} {call.tags && call.tags.length > 0 && ( {call.tags[0]} )} {systemName ?? call.system_id ?? "—"} {call.node_id} {isActive ? ( ● live ) : ( {duration(call.started_at, call.ended_at)} )} {call.audio_url ? ( e.stopPropagation()} className="text-blue-400 hover:text-blue-300 text-xs" > audio ) : ( )} {hasDetails && (expanded ? "▲" : "▼")} {expanded && hasDetails && ( {/* Tags */} {call.tags && call.tags.length > 0 && (
{call.tags.map((tag) => ( {tag} ))}
)} {/* Incident link */} {call.incident_id && (

Incident:{" "} {call.incident_id.slice(0, 8)}…

)} {/* Transcript */} {editing ? (
e.stopPropagation()}>