import { useState, useEffect, useContext } from 'react'; import { QueryClientContext } from '@tanstack/react-query'; import { useRealTimeFraudStream } from '../../hooks/useRealTimeFraudStream'; import { apiClient, formatApiError, advanceInstitutionalSessionEpoch, } from '../../api/client'; import { Activity, Radio, ShieldCheck, LogIn, LogOut } from 'lucide-react'; interface HeaderProps { onMenuClick: () => void; } interface SessionUserProfile { username: string; bank_id: string; roles: string[]; clearance_level?: number; } export default function Header({ onMenuClick }: HeaderProps) { const docsUrl = (import.meta.env.VITE_API_URL ?? '').replace(/\/+$/, '') + '/docs'; const { status, streamSource, streamProvenance, latencyMs, totalStreamedTransactions } = useRealTimeFraudStream(); const queryClient = useContext(QueryClientContext); const [sessionUser, setSessionUser] = useState(() => { try { const raw = localStorage.getItem('cfi_session_user'); if (raw) { return JSON.parse(raw) as SessionUserProfile; } } catch { // ignore storage errors } return null; }); const [isLoginModalOpen, setIsLoginModalOpen] = useState(false); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [loginError, setLoginError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); useEffect(() => { const syncAuthFromStorage = async () => { try { const token = localStorage.getItem('cfi_token'); const rawUser = localStorage.getItem('cfi_session_user'); if (!token) { setSessionUser(null); return; } if (rawUser) { setSessionUser(JSON.parse(rawUser) as SessionUserProfile); } const { data } = await apiClient.get('/api/v1/auth/me'); if (data?.username) { localStorage.setItem('cfi_session_user', JSON.stringify(data)); if (data.bank_id) { localStorage.setItem('cfi_tenant_id', data.bank_id); } setSessionUser(data); } } catch (err: unknown) { const status = (err as { response?: { status?: number } })?.response?.status; if (status === 401) { await advanceInstitutionalSessionEpoch(queryClient, { preserveAuthCredentials: false }); setSessionUser(null); } } }; void syncAuthFromStorage(); const handleStorageChange = () => { void syncAuthFromStorage(); }; window.addEventListener('storage', handleStorageChange); window.addEventListener('cfi-auth-changed', handleStorageChange); return () => { window.removeEventListener('storage', handleStorageChange); window.removeEventListener('cfi-auth-changed', handleStorageChange); }; }, [queryClient]); const handleLoginSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!username.trim() || !password) return; setLoginError(null); setIsSubmitting(true); try { const { data } = await apiClient.post<{ access_token: string; refresh_token?: string; user: SessionUserProfile; }>('/api/v1/auth/login', { username: username.trim(), password, }); await advanceInstitutionalSessionEpoch(queryClient, { preserveAuthCredentials: false }); localStorage.setItem('cfi_token', data.access_token); if (data.refresh_token) { localStorage.setItem('cfi_refresh_token', data.refresh_token); } if (data.user?.bank_id) { localStorage.setItem('cfi_tenant_id', data.user.bank_id); } localStorage.setItem('cfi_session_user', JSON.stringify(data.user)); setSessionUser(data.user); setPassword(''); setIsLoginModalOpen(false); window.dispatchEvent(new Event('cfi-auth-changed')); await queryClient?.invalidateQueries(); } catch (err: unknown) { setLoginError(formatApiError(err, 'Institutional authentication failed.')); } finally { setIsSubmitting(false); } }; const handleSignOut = async () => { try { await apiClient.post('/api/v1/auth/logout'); } catch { // Proceed with local session cleanup even if backend logout fails } await advanceInstitutionalSessionEpoch(queryClient, { preserveAuthCredentials: false }); setSessionUser(null); window.dispatchEvent(new Event('cfi-auth-changed')); await queryClient?.invalidateQueries(); }; return ( <>
{/* Menu toggle button on mobile */}

Collaborative Fraud Intelligence Platform

{/* Real-time WebSocket status badge */}
{status === 'connected' ? ( streamSource === 'LIVE_CONNECTOR' ? ( Live Connector WS ({latencyMs}ms) ) : streamSource === 'SIMULATED' ? ( Simulated Feed ({latencyMs}ms) ) : ( Telemetry Standby ({latencyMs}ms) ) ) : status === 'mock_active' ? ( Simulated Stream (Offline) ) : status === 'connecting' ? ( Connecting... ) : ( WS Offline )} {/* Live streamed transactions ticker */} {totalStreamedTransactions.toLocaleString()} txns
{sessionUser ? (
{sessionUser.username} · {sessionUser.bank_id.toUpperCase()}
) : ( )}
{isLoginModalOpen && (

Institutional Session Authentication

Authenticate with your sovereign institutional credentials to bind tenant context.

{loginError && (
{loginError}
)}
setUsername(e.target.value)} placeholder="e.g., analyst_bank_a" className="w-full rounded-lg border border-slate-700 bg-slate-950 px-3 py-2 text-sm text-slate-100 font-mono focus:border-indigo-500 focus:outline-none" required />
setPassword(e.target.value)} placeholder="Enter institutional credential" className="w-full rounded-lg border border-slate-700 bg-slate-950 px-3 py-2 text-sm text-slate-100 font-mono focus:border-indigo-500 focus:outline-none" required />
)} ); }