feat: instrument analysis

This commit is contained in:
OpenSquared
2026-06-30 18:09:29 +02:00
parent c3cebc2d7e
commit 75489a54bd

View File

@@ -760,6 +760,20 @@ function CausalFrise({
const [activeChip, setActiveChip] = useState<{ const [activeChip, setActiveChip] = useState<{
tmpl: CausalTemplate; ev: SnapshotEvent; chipX: number; chipY: number tmpl: CausalTemplate; ev: SnapshotEvent; chipX: number; chipY: number
} | null>(null) } | null>(null)
const [popupScore, setPopupScore] = useState<number | null | 'loading'>('loading')
// Fetch activation_score live when popup opens for a specific event
useEffect(() => {
const evId = activeChip?.ev.id
if (!evId) { setPopupScore(null); return }
setPopupScore('loading')
api.get(`/causal-lab/analyses?market_event_id=${evId}&limit=1`)
.then(r => {
const score = r.data?.[0]?.activation_score
setPopupScore(score != null ? Math.round(score * 100) : null)
})
.catch(() => setPopupScore(null))
}, [activeChip?.ev.id])
useEffect(() => { useEffect(() => {
const el = containerRef.current; if (!el) return const el = containerRef.current; if (!el) return
@@ -969,25 +983,24 @@ function CausalFrise({
)} )}
</div> </div>
{/* Précision — causalScores (API fraîche) avec fallback sur activation_score du snapshot */} {/* Précision — fetch live depuis causal_event_analyses au moment du clic */}
{(() => { {popupScore === 'loading' ? (
const snapScore = ev.activation_score != null ? Math.round(ev.activation_score * 100) : null <div className="mb-2 text-[9px] text-slate-600 italic">Chargement score</div>
const s = ev.id != null ? (causalScores[ev.id] ?? snapScore) : snapScore ) : popupScore != null ? (() => {
if (s == null) return null const barCls = popupScore >= 70 ? 'bg-emerald-500' : popupScore >= 40 ? 'bg-amber-500' : 'bg-red-500'
const barCls = s >= 70 ? 'bg-emerald-500' : s >= 40 ? 'bg-amber-500' : 'bg-red-500' const txtCls = popupScore >= 70 ? 'text-emerald-400' : popupScore >= 40 ? 'text-amber-400' : 'text-red-400'
const txtCls = s >= 70 ? 'text-emerald-400' : s >= 40 ? 'text-amber-400' : 'text-red-400'
return ( return (
<div className="mb-2"> <div className="mb-2">
<div className="flex items-center justify-between text-[9px] text-slate-600 mb-0.5"> <div className="flex items-center justify-between text-[9px] text-slate-600 mb-0.5">
<span>Précision prédiction</span> <span>Précision prédiction</span>
<span className={txtCls}>{s}%</span> <span className={txtCls}>{popupScore}%</span>
</div> </div>
<div className="h-1 bg-slate-800 rounded-full overflow-hidden"> <div className="h-1 bg-slate-800 rounded-full overflow-hidden">
<div className={clsx('h-full rounded-full', barCls)} style={{ width: `${s}%` }} /> <div className={clsx('h-full rounded-full', barCls)} style={{ width: `${popupScore}%` }} />
</div> </div>
</div> </div>
) )
})()} })() : null}
<div className="flex gap-1.5"> <div className="flex gap-1.5">
<button <button