import { useState } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogDescription } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { Upload, FileText, FileType, Video, Loader2 } from "lucide-react"; import { supabase } from "@/integrations/supabase/client"; import { toast } from "sonner"; import { useServerFn } from "@tanstack/react-start"; import { analyzeIncident } from "@/lib/incidents.functions"; export function UploadDialog({ onCreated }: { onCreated?: (id: string) => void }) { const [open, setOpen] = useState(false); const [busy, setBusy] = useState(false); const [title, setTitle] = useState(""); const [text, setText] = useState(""); const [file, setFile] = useState(null); const [tab, setTab] = useState<"text" | "file">("text"); const analyze = useServerFn(analyzeIncident); const reset = () => { setTitle(""); setText(""); setFile(null); setTab("text"); }; const submit = async () => { setBusy(true); try { let raw_text: string | null = null; let file_url: string | null = null; let file_name: string | null = null; let source_type: "text" | "file" | "pdf" | "video" = "text"; if (tab === "text") { if (!text.trim() && !title.trim()) throw new Error("Type something to analyze"); raw_text = text || title; } else { if (!file) throw new Error("Select a file"); file_name = file.name; const ext = file.name.split(".").pop()?.toLowerCase() ?? ""; source_type = ext === "pdf" ? "pdf" : ["mp4","mov","webm","avi","mkv"].includes(ext) ? "video" : "file"; const path = `public/${Date.now()}-${file.name}`; const { error: upErr } = await supabase.storage.from("incident-files").upload(path, file); if (upErr) throw upErr; file_url = path; if (["txt","csv","json","log","md","xml","yaml","yml"].includes(ext)) { raw_text = await file.text(); source_type = "file"; } else if (ext === "pdf") { raw_text = `[PDF file: ${file.name}, ${(file.size/1024).toFixed(1)} KB. Extract incident details from the document referenced by file_name.]`; } else if (source_type === "video") { raw_text = `[Video file: ${file.name}, ${(file.size/1024/1024).toFixed(2)} MB. Treat as recorded incident footage; analyze based on title + any supplied notes. Recommend transcription if not yet performed.]`; } } const finalTitle = title.trim() || (raw_text ? raw_text.slice(0, 80) : file_name) || "Untitled incident"; const { data: inc, error: insErr } = await supabase .from("incidents") .insert({ title: finalTitle, raw_text, file_url, file_name, source_type, status: "pending" }) .select() .single(); if (insErr) throw insErr; toast.success("Incident logged. Running multi-agent analysis…"); setOpen(false); reset(); onCreated?.(inc.id); try { await analyze({ data: { incidentId: inc.id } }); toast.success("Analysis complete"); } catch (e: any) { toast.error(`Analysis failed: ${await getErrorMessage(e, "Analysis request failed")}`); } } catch (e: any) { toast.error(await getErrorMessage(e, "Request failed")); } finally { setBusy(false); } }; return ( Submit incident for analysis Paste a report/transcript or upload sensor logs, PDF reports, or video evidence. DriveCore will route it through Event, Safety, Risk, and Documentation agents.
setTitle(e.target.value)} placeholder="e.g. Sudden braking event — I-280 NB" />
setTab(v as any)}> Paste text Upload file