// React data store + hooks that bridge the static UI fixtures with the Mossad API. const { createContext, useContext, useState, useEffect, useCallback } = React; const DataContext = createContext(null); function DataProvider({ children }) { const [auth, setAuth] = useState(() => ({ token: localStorage.getItem("mossad_token"), tenantId: localStorage.getItem("mossad_tenant"), })); const [data, setData] = useState({ alerts: window.ALERTS || [], kpis: window.KPIS || {}, cases: [], rules: [], riskProfiles: [], tenants: window.TENANTS || [], transactions: [], customers: [], sars: [], summary: null, loading: false, error: null, }); const isAuthenticated = !!(auth.token && auth.tenantId); const load = useCallback(async (silent = false) => { if (!isAuthenticated) return; if (!silent) setData(d => ({ ...d, loading: true, error: null })); try { const api = window.mossadApi; const [summary, alertsRaw, casesRaw, rulesRaw, riskRaw, txnsRaw, customersRaw, sarsRaw] = await Promise.all([ api.fetchDashboard().catch(() => null), api.fetchAlerts().catch(() => []), api.fetchCases().catch(() => []), api.fetchRules().catch(() => []), api.fetchRiskProfiles().catch(() => []), api.fetchTransactions(1000).catch(() => []), api.fetchCustomers(500).catch(() => []), api.fetchSARs ? api.fetchSARs().catch(() => []) : Promise.resolve([]), ]); const alerts = Array.isArray(alertsRaw) ? alertsRaw.map(api.mapAlert) : window.ALERTS || []; const cases = Array.isArray(casesRaw) ? casesRaw.map(api.mapCase) : []; const rules = Array.isArray(rulesRaw) ? rulesRaw : []; const riskProfiles = Array.isArray(riskRaw) ? riskRaw : []; const transactions = Array.isArray(txnsRaw) ? txnsRaw : []; const customers = Array.isArray(customersRaw) ? customersRaw : []; const sars = Array.isArray(sarsRaw) ? sarsRaw : []; const kpis = summary ? { alertsOpen: { value: summary.open_alerts, delta: summary.total_alerts_today, label: "Open alerts" }, highRisk: { value: summary.alerts_by_severity?.high || 0, delta: summary.alerts_by_severity?.critical || 0, label: "High-risk" }, slaBreached: { value: 0, delta: 0, label: "SLA-breached" }, avgClose: { value: "โ€”", delta: summary.avg_rule_execution_ms ? summary.avg_rule_execution_ms.toFixed(0) + "ms" : "โ€”", label: "Avg rule exec" }, sarsFiled: { value: summary.sars_filed_this_month, delta: summary.open_cases, label: "SARs filed ยท MTD" }, falsePositive:{ value: "โ€”", delta: "", label: "False positive rate" }, } : window.KPIS; setData({ alerts, cases, rules, sars, riskProfiles, tenants: window.TENANTS || [], transactions, customers, summary, kpis, loading: false, error: null, }); // Also keep globals up to date so legacy components keep working. window.ALERTS = alerts; window.KPIS = kpis; window.CASES_API = cases; window.RULES_API = rules; window.RISK_PROFILES_API = riskProfiles; window.TRANSACTIONS_API = transactions; window.CUSTOMERS_API = customers; window.SARS_API = sars; } catch (err) { setData(d => ({ ...d, loading: false, error: err.message })); } }, [isAuthenticated]); useEffect(() => { load(); const id = setInterval(() => load(true), 30000); return () => clearInterval(id); }, [load]); const login = async (email, password) => { const data = await window.mossadApi.login(email, password); const next = { token: localStorage.getItem("mossad_token"), tenantId: data.tenant_id }; setAuth(next); await load(true); }; const logout = () => { window.mossadApi.logout(); setAuth({ token: null, tenantId: null }); setData(d => ({ ...d, alerts: window.ALERTS || [], kpis: window.KPIS || {}, cases: [], sars: [] })); }; return ( load(false) }}> {children} ); } function useData() { return useContext(DataContext); } Object.assign(window, { DataProvider, useData });