import { useState, useMemo } from "react"; import { Copy, UploadCloud, FileText, Zap, Cpu, Sun, Layers, ArrowRight, Download, CheckCircle2 } from "lucide-react"; export const MODELS = [ { id: "bart_large_cnn", name: "BART", badgeLabel: "Top Pick", badgeColor: "text-orange-600 bg-orange-100 border-orange-200 dark:text-orange-400 dark:border-orange-500/30 dark:bg-orange-500/10", speed: 2, icon: Cpu, description: "Meta's BART model fine-tuned on CNN/DailyMail. It produces highly abstractive, narrative-style summaries, making it the best overall for rewriting raw incident descriptions into fluent reports." }, { id: "flan_t5_small", name: "Flan-T5", badgeLabel: "Fast", badgeColor: "text-blue-600 bg-blue-100 border-blue-200 dark:text-blue-400 dark:border-blue-500/30 dark:bg-blue-500/10", speed: 3, icon: Zap, description: "Google's instruction-tuned T5 model. It's incredibly fast and lightweight to run locally on CPU, though its summaries can occasionally be more concise and rigid than BART." }, { id: "pegasus_cnn", name: "PEGASUS", badgeLabel: "Precise", badgeColor: "text-emerald-600 bg-emerald-100 border-emerald-200 dark:text-emerald-400 dark:border-emerald-500/30 dark:bg-emerald-500/10", speed: 1, icon: Layers, description: "Google's PEGASUS model designed specifically for summarization. It is highly precise but computationally heavy, resulting in slower generation times." }, { id: "textrank", name: "TextRank", badgeLabel: "Offline", badgeColor: "text-purple-600 bg-purple-100 border-purple-200 dark:text-purple-400 dark:border-purple-500/30 dark:bg-purple-500/10", speed: 3, icon: Sun, description: "A classic non-neural extractive model based on PageRank. It works entirely offline without a GPU by identifying and extracting the most important exact sentences from the text." } ]; function downloadTextFile(filename, content) { const blob = new Blob([content], { type: "text/plain;charset=utf-8" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); link.remove(); URL.revokeObjectURL(url); } function extractTags(text) { if (!text) return []; try { const tags = []; // Vehicles const vehicleMatch = text.match(/\b(\d+|two|three|four|five|several|multiple)\s+(?:vehicles?|cars?|trucks?)\b/i); if (vehicleMatch) tags.push(vehicleMatch[1].toLowerCase() + " vehicles"); // Duration (minutes) const minMatch = text.match(/\b(\d+)\s*(?:min|minutes?)\b/i); if (minMatch) tags.push(minMatch[1] + " min"); // Distance (miles/km) const miMatch = text.match(/\b(\d+(?:\.\d+)?)\s*(?:miles?|mi|km)\b/i); if (miMatch) tags.push(miMatch[1] + " mi backup"); // Road codes like D71, E11 const codeMatches = text.match(/\b[A-Z]\d{1,3}\b/g); if (codeMatches) { codeMatches.forEach(c => { if (!tags.includes(c)) tags.push(c); }); } // Named roads (safe version) const roadMatch = text.match(/\b(?:Sheikh\s+Zayed|Hessa|Al\s+Khail|E[0-9]+|Highway\s+\d+|I-\d+|Route\s+\d+)[^,.]*(?:Road|Rd|Street|St|Hwy)?\b/gi); if (roadMatch) { const shortRoad = roadMatch[0].trim().split(' ').slice(0, 3).join(' '); if (!tags.some(t => t.toLowerCase() === shortRoad.toLowerCase())) tags.push(shortRoad); } return Array.from(new Set(tags)).slice(0, 4); } catch (_) { return []; } } export default function SummarizerWidget({ text, setText, modelChoice, setModelChoice, onSummarize, loading, summary }) { const wordCount = text.trim() ? text.trim().split(/\s+/).length : 0; const summaryWordCount = summary ? summary.split(/\s+/).filter(Boolean).length : 0; const [copied, setCopied] = useState(false); const extractedTags = useMemo(() => { return summary ? extractTags(summary + " " + text) : []; // eslint-disable-next-line react-hooks/exhaustive-deps }, [summary]); const handleCopy = () => { if (!summary) return; navigator.clipboard.writeText(summary); setCopied(true); setTimeout(() => setCopied(false), 2000); }; return (
{/* Input and Output Split Area */}
{/* LEFT PANE: INPUT */}

Original Incident

{wordCount} words