/* fraud-ui.jsx β€” Reusable UI components for Acme Bank Fraud Scoring */ const ACME = { primary: '#0D7C4A', primaryDark: '#065F3A', primaryBg: '#ECFDF5', bg: '#F3F4F6', card: '#FFFFFF', border: '#E5E7EB', text: '#111827', muted: '#6B7280', subtle: '#9CA3AF', success: '#059669', warning: '#D97706', danger: '#DC2626', neutral: '#6B7280', font: "'Plus Jakarta Sans', sans-serif", }; const SEVERITY_STYLES = { critical: { bg: '#FEE2E2', color: '#991B1B', dot: '#EF4444' }, high: { bg: '#FEF3C7', color: '#92400E', dot: '#F59E0B' }, medium: { bg: '#DBEAFE', color: '#1E40AF', dot: '#3B82F6' }, low: { bg: '#D1FAE5', color: '#065F46', dot: '#10B981' }, }; const RISK_STYLES = { critical: { bg: '#FEE2E2', color: '#991B1B' }, high: { bg: '#FEF3C7', color: '#92400E' }, medium: { bg: '#DBEAFE', color: '#1E40AF' }, low: { bg: '#D1FAE5', color: '#065F46' }, }; const STATUS_STYLES = { open: { bg: '#FEE2E2', color: '#991B1B', label: 'Open' }, investigating: { bg: '#FEF3C7', color: '#92400E', label: 'Investigating' }, resolved: { bg: '#D1FAE5', color: '#065F46', label: 'Resolved' }, cleared: { bg: '#D1FAE5', color: '#065F46', label: 'Cleared' }, flagged: { bg: '#FEE2E2', color: '#991B1B', label: 'Flagged' }, }; const REGION_CONFIG = { NA: { label: 'North America', flag: 'πŸ‡ΊπŸ‡Έ', color: '#3B82F6', bg: '#EFF6FF', navBg: '#EFF6FF', stripe: '#3B82F6' }, EU: { label: 'Europe', flag: 'πŸ‡ͺπŸ‡Ί', color: '#8B5CF6', bg: '#F5F3FF', navBg: '#F5F3FF', stripe: '#8B5CF6' }, APAC: { label: 'Asia-Pacific', flag: '🌏', color: '#F97316', bg: '#FFF7ED', navBg: '#FFF7ED', stripe: '#F97316' }, }; /* ─── Region Stripe β€” accent bar at top of page ─── */ const RegionStripe = ({ region }) => { const cfg = REGION_CONFIG[region]; if (!cfg) return null; return (
); }; /* ─── Top Nav ─── */ const NAV_TABS = ['Dashboard', 'Alerts', 'Transactions', 'Rules', 'Settings']; const FraudNav = ({ activeTab, onTabClick, version, mobile, demoRegion }) => { const regionCfg = REGION_CONFIG[demoRegion]; const accentColor = regionCfg ? regionCfg.color : ACME.primary; return (
onTabClick && onTabClick('Dashboard')}>
{!mobile && acmebank}
{(mobile ? NAV_TABS.slice(0, 3) : NAV_TABS).map((t) => { const active = t === activeTab; return (
onTabClick && onTabClick(t)} style={{ padding: mobile ? '0 8px' : '0 14px', height: 56, display: 'flex', alignItems: 'center', fontSize: mobile ? 13 : 14, fontWeight: active ? 600 : 500, color: active ? accentColor : ACME.muted, borderBottom: active ? '2px solid ' + accentColor : '2px solid transparent', cursor: 'pointer', fontFamily: ACME.font, flexShrink: 0, whiteSpace: 'nowrap' }}>{t}
); })}
{regionCfg && !mobile && (
{regionCfg.label}
)} {version && !mobile && (
v{version}
)}
{!mobile && ( <>
PS
Priya Sharma
Fraud Operations
)}
); }; /* ─── KPI Card ─── */ const KpiCard = ({ label, value, sub, subColor, icon, accent, mobile }) => (
{label}
{value}
{sub && !mobile &&
{sub}
}
{icon && !mobile && (
{icon}
)}
); /* ─── Badge ─── */ const Badge = ({ label, styles }) => (
{styles.dot &&
} {label}
); /* ─── Risk Score Bar ─── */ const RiskScoreBar = ({ score }) => { const pct = Math.round(score * 100); const color = score >= 0.85 ? '#EF4444' : score >= 0.65 ? '#F59E0B' : score >= 0.4 ? '#3B82F6' : '#10B981'; return (
{pct}%
); }; /* ─── Section Header ─── */ const SectionHeader = ({ title, subtitle, action }) => (
{title}
{subtitle &&
{subtitle}
}
{action && (
{action}
)}
); /* ─── Time Formatter ─── */ const formatTime = (ts) => { const d = new Date(ts); return d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); }; const formatTimeAgo = (ts) => { const seconds = Math.floor((Date.now() - ts) / 1000); if (seconds < 60) return `${seconds}s ago`; if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`; return `${Math.floor(seconds / 3600)}h ago`; }; // Responsive hook β€” detects mobile viewports (≀768px) function useIsMobile(breakpoint = 768) { const [isMobile, setIsMobile] = React.useState( () => window.innerWidth <= breakpoint ); React.useEffect(() => { const mql = window.matchMedia(`(max-width: ${breakpoint}px)`); const handler = (e) => setIsMobile(e.matches); mql.addEventListener('change', handler); return () => mql.removeEventListener('change', handler); }, [breakpoint]); return isMobile; } window.ACME = ACME; window.REGION_CONFIG = REGION_CONFIG; window.RegionStripe = RegionStripe; window.useIsMobile = useIsMobile; window.SEVERITY_STYLES = SEVERITY_STYLES; window.RISK_STYLES = RISK_STYLES; window.STATUS_STYLES = STATUS_STYLES; window.FraudNav = FraudNav; window.KpiCard = KpiCard; window.Badge = Badge; window.RiskScoreBar = RiskScoreBar; window.SectionHeader = SectionHeader; window.formatTime = formatTime; window.formatTimeAgo = formatTimeAgo;