// Tenants view — Mossad is single-tenant per session today, so there's exactly one tenant // card to show. Its name/branding come from the TENANTS fixture (tenant-data.jsx), but every // number below is computed live from the alerts/cases/SARs/customers already loaded for the // logged-in tenant — nothing here is a static number anymore. function statusPill(status) { if (status === "healthy") return { cls: "pill low", label: "Healthy" }; if (status === "watch") return { cls: "pill med", label: "Watch" }; if (status === "attention") return { cls: "pill high", label: "Attention" }; if (status === "onboarding") return { cls: "pill info", label: "Onboarding" }; return { cls: "pill", label: status }; } // Sparkline tuned for the tenant card — wider, with axis baseline. function TenantSpark({ data, color, height = 56 }) { if (!data.length) return null; const max = Math.max(...data, 1); const min = 0; const W = 320, H = height, P = 4; const pts = data.map((v, i) => { const x = P + (i / (data.length - 1)) * (W - P * 2); const y = H - P - ((v - min) / (max - min || 1)) * (H - P * 2); return [x, y]; }); const d = pts.map((p, i) => (i === 0 ? "M" : "L") + p[0].toFixed(1) + " " + p[1].toFixed(1)).join(" "); const area = `${d} L ${pts[pts.length - 1][0].toFixed(1)} ${H - P} L ${pts[0][0].toFixed(1)} ${H - P} Z`; return ( ); } // Real 30-day alert volume, bucketed by day from the alerts already loaded for this tenant. function alertVolumeByDay(alerts, days = 30) { const buckets = []; const keys = []; const start = new Date(); start.setHours(0, 0, 0, 0); start.setDate(start.getDate() - (days - 1)); for (let i = 0; i < days; i++) { const d = new Date(start); d.setDate(d.getDate() + i); keys.push(d.toISOString().slice(0, 10)); buckets.push(0); } const index = new Map(keys.map((k, i) => [k, i])); alerts.forEach(a => { const ts = a.opened || a._raw?.created_at; if (!ts) return; const day = new Date(ts).toISOString().slice(0, 10); const i = index.get(day); if (i != null) buckets[i] += 1; }); return buckets; } // Real current severity mix — a snapshot, not a fake 12-month trend. function severityMix(alerts) { const mix = { low: 0, med: 0, high: 0, severe: 0 }; alerts.forEach(a => { if (a.severity === "critical") mix.severe += 1; else if (a.severity === "high") mix.high += 1; else if (a.severity === "med" || a.severity === "medium") mix.med += 1; else mix.low += 1; }); return mix; } function SeverityMixBar({ mix }) { const order = [ { k: "low", label: "Low", color: "var(--risk-low)" }, { k: "med", label: "Medium", color: "var(--risk-med)" }, { k: "high", label: "High", color: "oklch(56% 0.20 35)" }, { k: "severe", label: "Critical", color: "var(--risk-high)" }, ]; const total = order.reduce((s, o) => s + mix[o.k], 0) || 1; return (
{order.map(o => (
))}
{order.map(o => ( {o.label} {mix[o.k]} ))}
); } // Health status derived from real numbers instead of an editorial fixture label. function deriveStatus(stats) { if (stats.severityMix.severe > 0 || stats.highRisk > 20) return "attention"; if (stats.highRisk > 0) return "watch"; return "healthy"; } function TenantCard({ tenant, stats }) { const isDark = document.documentElement.dataset.theme === "dark"; const accent = isDark ? tenant.colorDark : tenant.color; const sp = statusPill(deriveStatus(stats)); return (
{/* Header */}
{tenant.initial}
{tenant.name}
{tenant.sector} · since {tenant.since}
{sp.label}
{/* KPI grid — real */}
{[ { label: "Customers", value: stats.customersLabel }, { label: "Open alerts", value: stats.openAlerts }, { label: "High-risk", value: stats.highRisk, c: stats.highRisk > 10 ? "var(--risk-high)" : "var(--fg)" }, { label: "SARs · MTD", value: stats.sarsMtd }, ].map((k, i) => (
{k.label}
{k.value}
))}
{/* Alert volume sparkline — real, bucketed from live alerts */}
Alert volume · 30d
{/* Current severity mix — real snapshot, not a 12-month fixture */}
Alert severity mix · current
); } function TenantsView({ data }) { const tenant = TENANTS[0]; const alerts = data?.alerts || []; const customers = data?.customers || []; const sars = data?.sars || []; const stats = React.useMemo(() => { const now = new Date(); const openAlerts = alerts.filter(a => a.status === "open").length; const highRisk = alerts.filter(a => a.severity === "high" || a.severity === "critical").length; const sarsMtd = sars.filter(s => { const d = new Date(s.created_at); return d.getFullYear() === now.getFullYear() && d.getMonth() === now.getMonth(); }).length; return { customersLabel: customers.length.toLocaleString() + (customers.length === 500 ? "+" : ""), openAlerts, highRisk, sarsMtd, alertsByDay: alertVolumeByDay(alerts), severityMix: severityMix(alerts), }; }, [alerts, customers, sars]); return (

Tenants

1 fintech on Mossad · {stats.customersLabel} customers monitored
); } Object.assign(window, { TenantsView });