fix: compact convergence block, cache icon tooltip, Résumé IA dark theme

- Bloc FOND./MARCHÉ/Signaux seuls : 3 colonnes larges → 1 ligne compacte
- cache 2h : retiré de l'affichage inline → icône Database tooltip (hover)
- Résumé IA : text-indigo-600 → text-slate-400/hover:slate-200 (harmonisé)
- Modal Résumé IA : bg-white → dark (bg-slate-900, textes slate-200/300)
- Dot "Réel" → abbr "Tx.R" + tooltip explicatif (Taux Réel = CT − CPI YoY)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
caty21
2026-06-27 19:05:23 +02:00
co-authored by Claude Sonnet 4.6
parent c7ec82d82a
commit 623b1fa2a0
2 changed files with 27 additions and 47 deletions
+20 -40
View File
@@ -1067,7 +1067,7 @@ export default function CurrencyCard({
{ key: "mac", abbr: "Fonda.", dir }, { key: "mac", abbr: "Fonda.", dir },
{ key: "cot", abbr: "COT", dir: cotSignalDir }, { key: "cot", abbr: "COT", dir: cotSignalDir },
{ key: "sent", abbr: "Sent", dir: sentSignalDir }, { key: "sent", abbr: "Sent", dir: sentSignalDir },
{ key: "real", abbr: "Réel", dir: realRateDir }, { key: "real", abbr: "Tx.R", dir: realRateDir },
]; ];
// Auto-select first available slider block when data changes // Auto-select first available slider block when data changes
@@ -1124,8 +1124,8 @@ export default function CurrencyCard({
</span> </span>
{esi !== null && <SurpriseIndexBadge value={esi} />} {esi !== null && <SurpriseIndexBadge value={esi} />}
{fromCache && cacheAge && ( {fromCache && cacheAge && (
<span className="flex items-center gap-0.5 text-[9px] text-amber-500" title="Données depuis le cache local"> <span className="text-amber-500/60 cursor-help" title={`Données depuis le cache local (${cacheAge})`}>
<Database size={9} /> cache {cacheAge} <Database size={9} />
</span> </span>
)} )}
</div> </div>
@@ -1133,7 +1133,7 @@ export default function CurrencyCard({
{!loading && ( {!loading && (
<div className="flex items-center gap-3 mt-2 pt-2 border-t border-slate-800"> <div className="flex items-center gap-3 mt-2 pt-2 border-t border-slate-800">
{signalSummary.map(s => ( {signalSummary.map(s => (
<div key={s.key} className="flex flex-col items-center gap-0.5" title={`${s.abbr} : ${s.dir}`}> <div key={s.key} className="flex flex-col items-center gap-0.5" title={s.key === "real" ? `Taux Réel = Taux directeur CPI YoY.\n> +1.5% → restrictif (bullish)\n< 0% → accommodant (bearish)` : `${s.abbr} : ${s.dir}`}>
<div className={`w-2 h-2 rounded-full ${ <div className={`w-2 h-2 rounded-full ${
s.dir === "bullish" ? "bg-emerald-500" s.dir === "bullish" ? "bg-emerald-500"
: s.dir === "bearish" ? "bg-red-500" : s.dir === "bearish" ? "bg-red-500"
@@ -1328,44 +1328,24 @@ export default function CurrencyCard({
{activeTab === "overview" && ( {activeTab === "overview" && (
<> <>
{/* ── Divergence macro / marché ───────────────────────────── */} {/* ── Divergence macro / marché — compact 1 ligne ─────────── */}
{(dir !== "neutral" || mispricDir !== "neutral") && ( {(dir !== "neutral" || mispricDir !== "neutral") && (
<div className={`rounded-xl border px-3 py-2 flex items-center gap-3 ${ <div className={`rounded-lg border px-2.5 py-1.5 flex items-center gap-1.5 text-[10px] ${
bothOpposed bothOpposed ? "bg-amber-500/8 border-amber-500/25"
? "bg-amber-500/8 border-amber-500/25" : bothAligned ? sigBg(divergenceSignal)
: bothAligned : "bg-slate-800/40 border-slate-700/30"
? `${sigBg(divergenceSignal)}`
: "bg-slate-800/40 border-slate-700/30"
}`}> }`}>
{/* Macro */} <span className="text-slate-500 shrink-0">Fond.</span>
<div className="flex flex-col items-center gap-0.5"> <span className={`font-black ${sigColor(dir)}`}>{dir === "bullish" ? "↑" : dir === "bearish" ? "↓" : "—"}</span>
<span className="text-[7px] text-slate-600 uppercase tracking-wider">Fond.</span> <span className={`text-[9px] tabular-nums ${sigColor(dir)}`}>({macroScore > 0 ? "+" : ""}{macroScore})</span>
<span className={`text-[18px] font-black leading-none ${sigColor(dir)}`}> <span className="text-slate-700 mx-0.5">·</span>
{dir === "bullish" ? "↑" : dir === "bearish" ? "↓" : "—"} <span className={`font-bold flex-1 text-center ${bothOpposed ? "text-amber-400" : sigColor(divergenceSignal)}`}>
</span> {bothOpposed ? "⚠ Divergence" : bothAligned ? (divergenceSignal === "bullish" ? "✓ Conv. ↑" : "✓ Conv. ↓") : dir !== "neutral" ? "Macro seule" : "Signaux seuls"}
<span className={`text-[9px] font-bold tabular-nums ${sigColor(dir)}`}> </span>
{macroScore > 0 ? "+" : ""}{macroScore} <span className="text-slate-700 mx-0.5">·</span>
</span> <span className="text-slate-500 shrink-0">Marché</span>
</div> <span className={`font-black ${sigColor(mispricDir)}`}>{mispricDir === "bullish" ? "↑" : mispricDir === "bearish" ? "↓" : "—"}</span>
{/* Verdict central */} <span className="text-[8px] text-slate-600 shrink-0">OIS/COT</span>
<div className="flex-1 text-center">
<div className={`text-[10px] font-bold ${bothOpposed ? "text-amber-400" : sigColor(divergenceSignal)}`}>
{bothOpposed ? "⚠ Divergence" : bothAligned ? (divergenceSignal === "bullish" ? "✓ Convergence ↑" : "✓ Convergence ↓") : dir !== "neutral" ? "Macro seule" : "Signaux seuls"}
</div>
{bothOpposed && (
<div className="text-[8px] text-slate-600 mt-0.5">
Fond. {dir === "bullish" ? "haussier" : "baissier"} · Marché {mispricDir === "bullish" ? "haussier" : "baissier"}
</div>
)}
</div>
{/* Marché / Signaux */}
<div className="flex flex-col items-center gap-0.5">
<span className="text-[7px] text-slate-600 uppercase tracking-wider">Marché</span>
<span className={`text-[18px] font-black leading-none ${sigColor(mispricDir)}`}>
{mispricDir === "bullish" ? "↑" : mispricDir === "bearish" ? "↓" : "—"}
</span>
<span className={`text-[9px] text-slate-600`}>OIS/COT/Sent</span>
</div>
</div> </div>
)} )}
+7 -7
View File
@@ -45,7 +45,7 @@ export default function NarrativeButton({ currency, phase, macroScore }: Props)
<button <button
onClick={run} onClick={run}
disabled={loading} disabled={loading}
className="flex items-center gap-1 text-[10px] text-indigo-600 hover:text-indigo-800 disabled:opacity-50" className="flex items-center gap-1 text-[10px] text-slate-400 hover:text-slate-200 disabled:opacity-50 transition-colors px-2 py-1"
> >
<Sparkles size={11} /> <Sparkles size={11} />
{loading ? "Analyse…" : "Résumé IA"} {loading ? "Analyse…" : "Résumé IA"}
@@ -60,20 +60,20 @@ export default function NarrativeButton({ currency, phase, macroScore }: Props)
{open && analysis && ( {open && analysis && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30 p-4" onClick={() => setOpen(false)}> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30 p-4" onClick={() => setOpen(false)}>
<div <div
className="bg-white rounded-xl shadow-xl max-w-sm w-full p-5" className="bg-slate-900 border border-slate-700 rounded-xl shadow-xl max-w-sm w-full p-5"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
<div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Sparkles size={15} className="text-indigo-500" /> <Sparkles size={15} className="text-slate-400" />
<span className="font-medium text-sm">Analyse {currency} Groq AI</span> <span className="font-medium text-sm text-slate-200">Analyse {currency} Groq AI</span>
</div> </div>
<button onClick={() => setOpen(false)} className="text-gray-400 hover:text-gray-700"> <button onClick={() => setOpen(false)} className="text-slate-600 hover:text-slate-300">
<X size={15} /> <X size={15} />
</button> </button>
</div> </div>
<p className="text-sm text-gray-700 leading-relaxed whitespace-pre-wrap">{analysis}</p> <p className="text-sm text-slate-300 leading-relaxed whitespace-pre-wrap">{analysis}</p>
<div className="mt-3 text-[10px] text-gray-400 text-right"> <div className="mt-3 text-[10px] text-slate-600 text-right">
Powered by Groq · Llama 3.1 8B Powered by Groq · Llama 3.1 8B
</div> </div>
</div> </div>