import { useRef, useState } from 'react'; import type { PeriodStats } from '../services/DataService'; import type { FlowStats } from '../data/arcData'; import { Sparkline } from './Sparkline'; import { ServiceStatusDots } from './ServiceStatusDots'; import { useServiceStatus } from '../hooks/useServiceStatus'; import { CATEGORY_LABELS, CATEGORY_COLORS, type TxCategory } from '../data/commentParser'; import type { Transaction } from '../data/mockData'; interface StatsPanelProps { stats: PeriodStats | null; loading: boolean; periodDays: number; source: 'live' | 'mock'; className?: string; currentUD: number; animationLabel?: string; viewMode?: 'heatmap' | 'flow'; flowStats?: FlowStats | null; focusCity?: string | null; onClose?: () => void; onEndpointChange?: () => void; allTimestamps?: number[]; transactions?: Transaction[]; } const MEDALS = ['🥇', '🥈', '🥉']; function StatCard({ label, value, sub, delta }: { label: string; value: string; sub?: string; delta?: 'up' | 'down' | null }) { return (

{label}

{value} {delta === 'up' && } {delta === 'down' && }

{sub &&

{sub}

}
); } function formatDU(g1: number, ud: number): string { const du = g1 / ud; if (du < 10) return `≈ ${du.toFixed(2)} DU`; if (du < 100) return `≈ ${du.toFixed(1)} DU`; return `≈ ${Math.round(du).toLocaleString('fr-FR')} DU`; } function CityRow({ city, volume, count, countryCode, accent }: { city: string; volume: number; count: number; countryCode: string; accent?: string; }) { return (
{countryCode && ( {countryCode} )} {city} {volume.toLocaleString('fr-FR', { maximumFractionDigits: 0 })} Ğ1 · {count}
); } export function StatsPanel({ stats, loading, periodDays, source, currentUD, animationLabel, viewMode = 'heatmap', flowStats, focusCity, onClose, onEndpointChange, className, allTimestamps = [], transactions = [] }: StatsPanelProps) { const { subsquid, cesium, recheck } = useServiceStatus(); const [openCategory, setOpenCategory] = useState(null); 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; return ( ); }