feat: causal lab

This commit is contained in:
OpenSquared
2026-06-28 14:18:43 +02:00
parent 20f1897211
commit 863ba67610
4 changed files with 247 additions and 97 deletions

View File

@@ -53,8 +53,8 @@ interface Template {
}
interface MarketEvent {
id: number; name: string; category: string; sub_type: string
start_date: string; level: string; impact_score: number
market_impact: string; affected_assets: string
start_date: string; end_date: string | null; level: string; created_at: string | null
impact_score: number; market_impact: string; affected_assets: string
actual_value: number | null; expected_value: number | null; surprise_pct: number | null
analysis_id: number | null; template_id: number | null; activation_score: number | null
}
@@ -1318,7 +1318,7 @@ function TabEditor() {
// ── Tab: Analyser ─────────────────────────────────────────────────────────────
function TabAnalyze() {
function TabAnalyze({ initialEventId }: { initialEventId?: number | null }) {
const [events, setEvents] = useState<MarketEvent[]>([])
const [templates, setTemplates] = useState<Template[]>([])
const [selEvent, setSelEvent] = useState<MarketEvent | null>(null)
@@ -1340,6 +1340,12 @@ function TabAnalyze() {
]).then(([evs, tmps]) => { setEvents(evs); setTemplates(tmps) })
}, [catF, q])
useEffect(() => {
if (!initialEventId || !events.length || selEvent) return
const found = events.find(e => e.id === initialEventId)
if (found) setSelEvent(found)
}, [events, initialEventId])
const currentTemplate = templates.find(t => t.id === selTmpl)
const manualNodes = currentTemplate?.graph_json?.input_mapping
? Object.entries(currentTemplate.graph_json.input_mapping).filter(([, c]) =>
@@ -1389,7 +1395,12 @@ function TabAnalyze() {
<select value={catF} onChange={e => setCatF(e.target.value)}
className="bg-dark-700 border border-slate-700 rounded px-2 py-1.5 text-xs text-slate-300">
<option value="">Tous</option>
{Object.entries(CAT_LABELS).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
<option value="event_calendar">Calendrier éco</option>
<option value="fundamental">Fondamental</option>
<option value="geopolitical">Géopolitique</option>
<option value="report">Report</option>
<option value="sentiment">Sentiment</option>
<option value="technical">Technique</option>
</select>
</div>
@@ -1686,7 +1697,8 @@ const TABS = [
export default function CausalLab() {
const [searchParams] = useSearchParams()
const initialTemplateId = searchParams.get('template') ? parseInt(searchParams.get('template')!) : null
const [tab, setTab] = useState('library')
const initialEventId = searchParams.get('event') ? parseInt(searchParams.get('event')!) : null
const [tab, setTab] = useState(initialEventId ? 'analyze' : 'library')
return (
<div className="p-6 min-h-screen">
@@ -1714,7 +1726,7 @@ export default function CausalLab() {
<div className="bg-dark-800 rounded-xl p-5 border border-slate-700/30">
{tab === 'library' && <TabLibrary initialTemplateId={initialTemplateId} />}
{tab === 'editor' && <TabEditor />}
{tab === 'analyze' && <TabAnalyze />}
{tab === 'analyze' && <TabAnalyze initialEventId={initialEventId} />}
{tab === 'calib' && <TabCalibration />}
</div>
</div>