diff --git a/src/components/StatsPanel.tsx b/src/components/StatsPanel.tsx index b76d9e6..b7a9ea1 100644 --- a/src/components/StatsPanel.tsx +++ b/src/components/StatsPanel.tsx @@ -1,3 +1,4 @@ +import { useRef } from 'react'; import type { PeriodStats } from '../services/DataService'; interface StatsPanelProps { @@ -9,11 +10,15 @@ interface StatsPanelProps { const MEDALS = ['🥇', '🥈', '🥉']; -function StatCard({ label, value, sub }: { label: string; value: string; sub?: string }) { +function StatCard({ label, value, sub, delta }: { label: string; value: string; sub?: string; delta?: 'up' | 'down' | null }) { return (

{label}

-

{value}

+

+ {value} + {delta === 'up' && ↑} + {delta === 'down' && ↓} +

{sub &&

{sub}

}
); @@ -21,6 +26,26 @@ function StatCard({ label, value, sub }: { label: string; value: string; sub?: s export function StatsPanel({ stats, loading, periodDays, source }: StatsPanelProps) { const periodLabel = periodDays === 1 ? '24 dernières heures' : `${periodDays} derniers jours`; + const prevStats = useRef(null); + + // Calcule le delta d'une valeur par rapport au refresh précédent + function delta(current: number, prevMap: Map, key: string) { + const prev = prevMap.get(key); + if (prev === undefined) return null; + if (current > prev) return ↑; + if (current < prev) return ↓; + return null; + } + + // Construit une map volume précédent par ville + const prevCityVolume = new Map( + (prevStats.current?.topCities ?? []).map((c) => [c.name, c.volume]) + ); + const prevVolume = prevStats.current?.totalVolume ?? null; + const prevTxCount = prevStats.current?.transactionCount ?? null; + + // Mémorise les stats après le rendu + if (stats && !loading) prevStats.current = stats; const geoPct = stats && stats.transactionCount > 0 ? Math.round((stats.geoCount / stats.transactionCount) * 100) : null; @@ -55,11 +80,13 @@ export function StatsPanel({ stats, loading, periodDays, source }: StatsPanelPro prevVolume ? 'up' : stats.totalVolume < prevVolume ? 'down' : null) : null} /> prevTxCount ? 'up' : stats.transactionCount < prevTxCount ? 'down' : null) : null} /> {/* Couverture géo — uniquement en mode live */} {source === 'live' && geoPct !== null && ( @@ -96,8 +123,9 @@ export function StatsPanel({ stats, loading, periodDays, source }: StatsPanelPro

{city.name}

{city.count} tx

- + {city.volume.toLocaleString('fr-FR', { maximumFractionDigits: 0 })} Äž1 + {delta(city.volume, prevCityVolume, city.name)} ))}