fix: barre de géoloc toujours visible, basée sur la période complète
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
En mode animation, globalGeoStats passe les chiffres de la période entière (depuis stats global) pour que la barre affiche le vrai taux Cesium+. Le label indique "(période)" pour rappeler que ce n'est pas par frame. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -72,6 +72,7 @@ export default function App() {
|
|||||||
source={source}
|
source={source}
|
||||||
currentUD={currentUD}
|
currentUD={currentUD}
|
||||||
animationLabel={animation.active ? (animation.currentFrame?.label ?? undefined) : undefined}
|
animationLabel={animation.active ? (animation.currentFrame?.label ?? undefined) : undefined}
|
||||||
|
globalGeoStats={animation.active && stats ? { geoCount: stats.geoCount, transactionCount: stats.transactionCount } : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Map area */}
|
{/* Map area */}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ interface StatsPanelProps {
|
|||||||
source: 'live' | 'mock';
|
source: 'live' | 'mock';
|
||||||
currentUD: number;
|
currentUD: number;
|
||||||
animationLabel?: string;
|
animationLabel?: string;
|
||||||
|
// Stats de géoloc de la période complète (indépendantes de la frame courante)
|
||||||
|
globalGeoStats?: { geoCount: number; transactionCount: number };
|
||||||
}
|
}
|
||||||
|
|
||||||
const MEDALS = ['🥇', '🥈', '🥉'];
|
const MEDALS = ['🥇', '🥈', '🥉'];
|
||||||
@@ -33,7 +35,7 @@ function formatDU(g1: number, ud: number): string {
|
|||||||
return `≈ ${Math.round(du).toLocaleString('fr-FR')} DU`;
|
return `≈ ${Math.round(du).toLocaleString('fr-FR')} DU`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StatsPanel({ stats, loading, periodDays, source, currentUD, animationLabel }: StatsPanelProps) {
|
export function StatsPanel({ stats, loading, periodDays, source, currentUD, animationLabel, globalGeoStats }: StatsPanelProps) {
|
||||||
const periodLabel = periodDays === 1 ? '24 dernières heures' : `${periodDays} derniers jours`;
|
const periodLabel = periodDays === 1 ? '24 dernières heures' : `${periodDays} derniers jours`;
|
||||||
const prevStats = useRef<PeriodStats | null>(null);
|
const prevStats = useRef<PeriodStats | null>(null);
|
||||||
|
|
||||||
@@ -55,9 +57,6 @@ export function StatsPanel({ stats, loading, periodDays, source, currentUD, anim
|
|||||||
|
|
||||||
// Mémorise les stats après le rendu
|
// Mémorise les stats après le rendu
|
||||||
if (stats && !loading) prevStats.current = stats;
|
if (stats && !loading) prevStats.current = stats;
|
||||||
const geoPct = stats && stats.transactionCount > 0
|
|
||||||
? Math.round((stats.geoCount / stats.transactionCount) * 100)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="w-72 shrink-0 flex flex-col gap-4 bg-[#0a0b0f]/95 backdrop-blur-sm border-r border-[#1e1f2a] p-5 overflow-y-auto">
|
<aside className="w-72 shrink-0 flex flex-col gap-4 bg-[#0a0b0f]/95 backdrop-blur-sm border-r border-[#1e1f2a] p-5 overflow-y-auto">
|
||||||
@@ -109,23 +108,31 @@ export function StatsPanel({ stats, loading, periodDays, source, currentUD, anim
|
|||||||
})()}
|
})()}
|
||||||
delta={prevTxCount !== null ? (stats.transactionCount > prevTxCount ? 'up' : stats.transactionCount < prevTxCount ? 'down' : null) : null}
|
delta={prevTxCount !== null ? (stats.transactionCount > prevTxCount ? 'up' : stats.transactionCount < prevTxCount ? 'down' : null) : null}
|
||||||
/>
|
/>
|
||||||
{/* Couverture géo — uniquement en mode live, masquée en animation
|
{/* Couverture géo — toujours basée sur la période complète (pas la frame) */}
|
||||||
(visibleTransactions ne contient que du géolocalisé → toujours 100%) */}
|
{source === 'live' && (() => {
|
||||||
{source === 'live' && geoPct !== null && !animationLabel && (
|
const geo = globalGeoStats ?? { geoCount: stats.geoCount, transactionCount: stats.transactionCount };
|
||||||
|
const pct = geo.transactionCount > 0
|
||||||
|
? Math.round((geo.geoCount / geo.transactionCount) * 100)
|
||||||
|
: null;
|
||||||
|
if (pct === null) return null;
|
||||||
|
return (
|
||||||
<div className="bg-[#0f1016] border border-[#2e2f3a] rounded-xl p-3">
|
<div className="bg-[#0f1016] border border-[#2e2f3a] rounded-xl p-3">
|
||||||
<div className="flex justify-between items-center mb-1.5">
|
<div className="flex justify-between items-center mb-1.5">
|
||||||
<p className="text-[#4b5563] text-xs uppercase tracking-widest">Géolocalisées</p>
|
<p className="text-[#4b5563] text-xs uppercase tracking-widest">
|
||||||
<p className="text-[#6b7280] text-xs">{stats.geoCount} / {stats.transactionCount}</p>
|
Géolocalisées{animationLabel ? <span className="normal-case ml-1 opacity-60">(période)</span> : ''}
|
||||||
|
</p>
|
||||||
|
<p className="text-[#6b7280] text-xs">{geo.geoCount} / {geo.transactionCount}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full bg-[#1e1f2a] rounded-full h-1.5">
|
<div className="w-full bg-[#1e1f2a] rounded-full h-1.5">
|
||||||
<div
|
<div
|
||||||
className="bg-[#d4a843] h-1.5 rounded-full transition-all duration-500"
|
className="bg-[#d4a843] h-1.5 rounded-full transition-all duration-500"
|
||||||
style={{ width: `${geoPct}%` }}
|
style={{ width: `${pct}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-[#4b5563] text-xs mt-1 text-right">{geoPct}% via Cesium+</p>
|
<p className="text-[#4b5563] text-xs mt-1 text-right">{pct}% via Cesium+</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
);
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user