import { useState, useEffect, useCallback } from 'react' import { Zap, RefreshCw, ChevronDown, ChevronRight, AlertCircle, TrendingUp, TrendingDown, Minus, Settings, Play, Check, Sliders, } from 'lucide-react' import axios from 'axios' import clsx from 'clsx' const api = axios.create({ baseURL: '/api' }) // ── Types ───────────────────────────────────────────────────────────────────── interface Impact { id: number instrument_id: string impact_score: number direction: string rationale: string confidence: number ai_generated: number manually_adjusted: number adjusted_score?: number adjusted_direction?: string override_rationale?: string } interface EvaluatedSource { source_type: string source_id: number source_name: string source_date: string category_name: string max_score: number n_instruments: number evaluated_at: string impacts: Impact[] } interface UnevaluatedEvent { id: number name: string start_date: string category: string sub_type: string impact_score: number } interface TopInstrument { instrument_id: string avg_score: number n_events: number } interface MonitorData { evaluated: EvaluatedSource[] unevaluated: UnevaluatedEvent[] top_instruments: TopInstrument[] period_days: number min_score: number } interface DefaultImpact { instrument_id: string sensitivity: number typical_direction: string notes: string } interface Category { id: number name: string type: string sub_type: string description: string default_impacts: DefaultImpact[] } // ── Helpers ─────────────────────────────────────────────────────────────────── const DIR_CFG: Record = { bullish: { icon: , color: 'text-emerald-400', short: '↑' }, bearish: { icon: , color: 'text-red-400', short: '↓' }, neutral: { icon: , color: 'text-slate-400', short: '—' }, depends_on_outcome: { icon: , color: 'text-amber-400', short: '?' }, bullish_if_beat: { icon: , color: 'text-emerald-300', short: '↑?' }, bearish_if_hawkish: { icon: , color: 'text-red-300', short: '↓H' }, bullish_if_surprise: { icon: , color: 'text-violet-400', short: '↑!' }, } const TYPE_CFG: Record = { event_calendar: { color: 'text-amber-400 bg-amber-900/30 border-amber-700/30', label: 'Calendrier' }, geopolitical: { color: 'text-red-400 bg-red-900/30 border-red-700/30', label: 'Géopolitique' }, } function scoreBar(score: number, color = 'bg-blue-500') { return (
{(score * 100).toFixed(0)}
) } function scoreColor(score: number) { if (score >= 0.7) return 'bg-red-500' if (score >= 0.5) return 'bg-orange-500' if (score >= 0.3) return 'bg-amber-500' return 'bg-slate-500' } function dirColor(dir: string) { return DIR_CFG[dir]?.color ?? 'text-slate-400' } // ── AdjustModal ─────────────────────────────────────────────────────────────── function AdjustModal({ impact, onClose, onSave, }: { impact: Impact onClose: () => void onSave: (id: number, score: number, dir: string, rationale: string) => void }) { const [score, setScore] = useState(impact.adjusted_score ?? impact.impact_score) const [dir, setDir] = useState(impact.adjusted_direction ?? impact.direction) const [rationale, setRationale] = useState(impact.override_rationale ?? '') const DIRS = ['bullish','bearish','neutral','depends_on_outcome'] return (
Ajuster l'impact — {impact.instrument_id}
Score IA : {(impact.impact_score * 100).toFixed(0)}
setScore(parseFloat(e.target.value))} className="w-full accent-blue-500" />
{DIRS.map(d => ( ))}