import { AlertTriangle, ChevronRight, Info, Loader2, Search, X, Zap } from 'lucide-react'; import { useEffect, useRef, useState } from 'react'; interface DomainSignal { title: string; summary: string; severity: 'critical' | 'high' | 'medium' | 'low' | 'info'; timestamp: number; } interface DomainResult { domain: string; domainLabel: string; relevanceScore: number; signals: DomainSignal[]; insight: string; } interface Correlation { title: string; domains: string[]; description: string; confidence: number; } interface FusedResult { query: string; answeredAt: number; domainsQueried: string[]; domainResults: DomainResult[]; fusedAnswer: string; correlations: Correlation[]; recommendedActions: string[]; overallRisk: 'critical' | 'high' | 'medium' | 'low' | 'nominal'; confidence: number; liveDataSources?: string[]; } interface FusionBarProps { apiBase?: string; } const DOMAIN_COLORS: Record = { vessels: 'var(--gi-accent-blue)', aegis: '#ef4444', terra: '#22c55e', prism: '#8b5cf6', lyte: '#f59e0b', 'szl-holdings': '#8b7ac8', carlota: '#ec4899', }; const SEVERITY_COLORS: Record = { critical: '#ef4444', high: '#f59e0b', medium: '#3b82f6', low: '#6b7280', info: '#22c55e', }; const SUGGESTIONS = [ 'Brief me on compound risks this week', "What's the maritime impact on real estate?", 'Current cyber threat posture and legal implications', 'Portfolio risk snapshot across all domains', 'Summarize overnight signals', ]; function RiskBadge({ risk }: { risk: string }) { const color = SEVERITY_COLORS[risk] ?? '#6b7280'; return ( {risk} ); } function DomainBadge({ domain, live = false }: { domain: string; live?: boolean }) { const color = DOMAIN_COLORS[domain] ?? '#6b7280'; return ( {domain} {live && ( Live )} ); } export function FusionBar({ apiBase = '' }: FusionBarProps) { const [query, setQuery] = useState(''); const [loading, setLoading] = useState(false); const [result, setResult] = useState(null); const [error, setError] = useState(null); const [showSuggestions, setShowSuggestions] = useState(false); const inputRef = useRef(null); const panelRef = useRef(null); useEffect(() => { const handler = (e: MouseEvent) => { if (panelRef.current && !panelRef.current.contains(e.target as Node)) { setShowSuggestions(false); } }; document.addEventListener('mousedown', handler); return () => document.removeEventListener('mousedown', handler); }, []); async function submit(q: string) { const trimmed = q.trim(); if (!trimmed || loading) return; setLoading(true); setError(null); setResult(null); setShowSuggestions(false); try { const res = await fetch(`${apiBase}/api/cross-domain-query`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: trimmed }), }); const data = await res.json(); if (data.success && data.result) { setResult(data.result); } else { setError('Query failed — please try again.'); } } catch { setError('Unable to reach the fusion engine.'); } finally { setLoading(false); } } function handleSuggestion(s: string) { setQuery(s); setShowSuggestions(false); submit(s); } function clear() { setQuery(''); setResult(null); setError(null); inputRef.current?.focus(); } return (
{ setQuery(e.target.value); if (!result) setShowSuggestions(e.target.value.length === 0); }} onFocus={() => { if (!query && !result) setShowSuggestions(true); }} onKeyDown={(e) => { if (e.key === 'Enter') submit(query); if (e.key === 'Escape') { setShowSuggestions(false); clear(); } }} /> {loading && ( )} {(query || result) && !loading && ( )} {!loading && ( )}
{showSuggestions && !result && (
Suggested queries
{SUGGESTIONS.map((s) => ( ))}
)} {error && (
{error}
)} {result && (
Fusion Intelligence
{result.domainsQueried.length} domains · {Math.round(result.confidence * 100)}% confidence

{result.fusedAnswer.replace(/\*\*(.*?)\*\*/g, '$1')}

{result.domainsQueried.map((d) => ( ))}
{result.correlations.length > 0 && (

Cross-Domain Correlations

{result.correlations.map((c, i) => (
{c.title}
{c.description}
{c.domains.map((d) => ( ))} {Math.round(c.confidence * 100)}% conf.
))}
)} {result.recommendedActions.length > 0 && (

Recommended Actions

{result.recommendedActions.map((action, i) => (
{action}
))}
)} {result.domainResults.length > 0 && (

Domain Breakdown

{result.domainResults.slice(0, 6).map((dr) => (
{dr.domainLabel}
{Math.round(dr.relevanceScore * 100)}% relevant

{dr.insight}

{dr.signals.slice(0, 2).map((sig, j) => (
{sig.title}
))}
))}
)}
)}
); }