import { useState, useEffect } from 'react'; import { StatsPanel } from './components/StatsPanel'; import { PeriodSelector } from './components/PeriodSelector'; import { HeatMap } from './components/HeatMap'; import { fetchData } from './services/DataService'; import type { PeriodStats } from './services/DataService'; import type { Transaction } from './data/mockData'; export default function App() { const [periodDays, setPeriodDays] = useState(7); const [transactions, setTransactions] = useState([]); const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [lastUpdate, setLastUpdate] = useState(null); const [source, setSource] = useState<'live' | 'mock'>('mock'); useEffect(() => { let cancelled = false; const load = (showLoading: boolean) => { if (showLoading) setLoading(true); else setRefreshing(true); fetchData(periodDays) .then(({ transactions, stats, source }) => { if (!cancelled) { setTransactions(transactions); setStats(stats); setSource(source); setLastUpdate(new Date()); } }) .catch((err) => console.warn('Ğ1Flux refresh error:', err)) .finally(() => { if (!cancelled) { setLoading(false); setRefreshing(false); } }); }; load(true); const interval = setInterval(() => load(false), 30_000); return () => { cancelled = true; clearInterval(interval); }; }, [periodDays]); return (
{/* Side panel */} {/* Map area */}
{/* Period selector — floating over map */}
{/* Transaction count + source badge */} {!loading && (
{transactions.length} transactions affichées
{source === 'live' ? <>{refreshing ? : '●'} live Ğ1v2{lastUpdate && {lastUpdate.toLocaleTimeString('fr-FR')}} : '○ mock'}
)} {/* Loading overlay */} {loading && (

Chargement des flux…

)}
); }