// Analytics overview view — org-level KPIs, distributions, leaderboards. function Sparkline({ data, color = "var(--fg)", fill = false, height = 36, width = 120 }) { const min = Math.min(...data), max = Math.max(...data); const range = max - min || 1; const W = width, H = height; const pts = data.map((v, i) => { const x = (i / (data.length - 1)) * W; const y = H - 2 - ((v - min) / range) * (H - 6); return [x, y]; }); const d = pts.map((p, i) => (i === 0 ? "M" : "L") + p[0].toFixed(1) + " " + p[1].toFixed(1)).join(" "); const area = fill ? `${d} L ${W} ${H} L 0 ${H} Z` : null; return ( {area && } ); } function KPICard({ label, value, delta, sub, spark, sparkColor }) { const isUp = typeof delta === "number" ? delta > 0 : String(delta).startsWith("+"); const isDown = typeof delta === "number" ? delta < 0 : String(delta).startsWith("−") || String(delta).startsWith("-"); const cls = isUp ? "up" : isDown ? "down" : "flat"; const sign = typeof delta === "number" ? (delta > 0 ? "+" : "") : ""; return (
{label}
{value}
{spark && }
{isUp && } {isDown && } {sign}{delta} {sub && {sub}}
); } function TypologyChart() { const max = Math.max(...TYPOLOGY_DIST.map(t => t.count)); return (
{TYPOLOGY_DIST.map((t, i) => (
{t.name}
{t.count} · {t.pct}%
))}
); } function CorridorTable() { return ( {CORRIDOR_RISK.map((c, i) => ( ))}
Corridor Risk 90d volume
{c.from} {c.to} {c.vol}
); } function Leaderboard() { const max = Math.max(...QUEUE_BY_ASSIGNEE.map(a => a.open)); return ( {QUEUE_BY_ASSIGNEE.map(a => ( ))}
Analyst Workload Open SLA
{a.init} {a.who}
{a.open} 0 ? "var(--risk-high)" : "var(--fg-3)" }}> {a.sla > 0 ? `${a.sla} risk` : "—"}
); } function HourHeatmap() { // 7×24 heatmap of alert generation const heatmapData = []; for (let d = 0; d < 7; d++) { const row = []; for (let h = 0; h < 24; h++) { // Synthetic but plausible — peaks at business hours, especially Tue/Wed const business = (h >= 8 && h <= 18) ? 1 : 0.3; const weekend = (d === 5 || d === 6) ? 0.4 : 1; const peak = (d === 1 || d === 2 || d === 3) && (h >= 10 && h <= 14) ? 1.4 : 1; const noise = 0.5 + (Math.sin(d*7 + h*0.7) + 1) * 0.5; row.push(Math.round(business * weekend * peak * noise * 12)); } heatmapData.push(row); } const max = Math.max(...heatmapData.flat()); const days = ["M","T","W","T","F","S","S"]; return (
{Array.from({ length: 24 }).map((_, h) => (
{h % 4 === 0 ? h.toString().padStart(2, "0") : ""}
))}
{heatmapData.map((row, d) => (
{days[d]}
{row.map((v, h) => (
))}
))}
Less {[0, 0.25, 0.5, 0.75, 1].map((v, i) => (
))} More
); } function AnalyticsView({ data }) { const kpis = data?.kpis || window.KPIS || {}; const summary = data?.summary; const k = (key, fallback) => kpis[key] || fallback; return (

Operations overview

FIU workload and detection performance · last 30 days
{/* KPI grid */}
{/* Two-col charts */}

Alerts by typology

187 alerts · 8 categories

Corridor risk

top 6 by volume

Alert generation · 7d × 24h

UTC

Team workload

{/* Detection performance table */}

Detection rules · performance · 30d

Rule Typology Fires TP rate FP rate Trend Status
); } function RulRow({ id, name, type, fires, tp, fp, trend, status }) { const sCls = status === "healthy" ? "pill low" : status === "watch" ? "pill med" : "pill high"; return ( {id} {name} {type} {fires} {tp}% 50 ? "var(--risk-high)" : fp > 40 ? "var(--risk-med)" : "var(--fg-2)" }}>{fp}% {status} ); } Object.assign(window, { AnalyticsView, Sparkline });