feat: instrument analysis
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user