fix: détection pays fiable via nom de ville Cesium+ + reorder bounding boxes
- Extrait le pays depuis le champ city Cesium+ en priorité (ex: "Heusy, 4800, Belgique" → BE) - Bounding boxes réordonnées : petits pays (LU, BE, CH, NL) avant FR pour éviter les faux positifs - Affiche l'heure du dernier refresh sur le badge live Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ export default function App() {
|
||||
const [stats, setStats] = useState<PeriodStats | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [lastUpdate, setLastUpdate] = useState<Date | null>(null);
|
||||
const [source, setSource] = useState<'live' | 'mock'>('mock');
|
||||
|
||||
useEffect(() => {
|
||||
@@ -26,6 +27,7 @@ export default function App() {
|
||||
setTransactions(transactions);
|
||||
setStats(stats);
|
||||
setSource(source);
|
||||
setLastUpdate(new Date());
|
||||
}
|
||||
})
|
||||
.catch((err) => console.warn('Ğ1Flux refresh error:', err))
|
||||
@@ -66,7 +68,7 @@ export default function App() {
|
||||
: 'bg-[#0a0b0f]/80 border-[#2e2f3a] text-[#4b5563]'
|
||||
}`}>
|
||||
{source === 'live'
|
||||
? <>{refreshing ? <span className="animate-spin inline-block">↻</span> : '●'} live Ğ1v2</>
|
||||
? <>{refreshing ? <span className="animate-spin inline-block">↻</span> : '●'} live Ğ1v2{lastUpdate && <span className="ml-1 opacity-60">{lastUpdate.toLocaleTimeString('fr-FR')}</span>}</>
|
||||
: '○ mock'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,16 +25,17 @@ export interface GeoProfile {
|
||||
|
||||
// Détection de pays par bounding box (pays présents dans la communauté Ğ1)
|
||||
const COUNTRY_BOXES: { code: string; latMin: number; latMax: number; lngMin: number; lngMax: number }[] = [
|
||||
{ code: 'FR', latMin: 41.3, latMax: 51.1, lngMin: -5.1, lngMax: 9.6 },
|
||||
// Petits pays d'abord : leurs bounding boxes chevauchent celle de la France
|
||||
{ code: 'LU', latMin: 49.4, latMax: 50.2, lngMin: 5.7, lngMax: 6.5 },
|
||||
{ code: 'BE', latMin: 49.5, latMax: 51.5, lngMin: 2.5, lngMax: 6.4 },
|
||||
{ code: 'CH', latMin: 45.8, latMax: 47.8, lngMin: 5.9, lngMax: 10.5 },
|
||||
{ code: 'LU', latMin: 49.4, latMax: 50.2, lngMin: 5.7, lngMax: 6.5 },
|
||||
{ code: 'NL', latMin: 50.7, latMax: 53.6, lngMin: 3.3, lngMax: 7.2 },
|
||||
{ code: 'DE', latMin: 47.3, latMax: 55.1, lngMin: 6.0, lngMax: 15.0 },
|
||||
{ code: 'FR', latMin: 41.3, latMax: 51.1, lngMin: -5.1, lngMax: 9.6 },
|
||||
{ code: 'ES', latMin: 35.9, latMax: 43.8, lngMin: -9.3, lngMax: 4.3 },
|
||||
{ code: 'PT', latMin: 36.8, latMax: 42.2, lngMin: -9.5, lngMax: -6.2 },
|
||||
{ code: 'IT', latMin: 36.6, latMax: 47.1, lngMin: 6.6, lngMax: 18.5 },
|
||||
{ code: 'GB', latMin: 49.9, latMax: 60.9, lngMin: -8.2, lngMax: 1.8 },
|
||||
{ code: 'NL', latMin: 50.7, latMax: 53.6, lngMin: 3.3, lngMax: 7.2 },
|
||||
{ code: 'MA', latMin: 27.6, latMax: 35.9, lngMin: -13.2, lngMax: -1.0 },
|
||||
{ code: 'TN', latMin: 30.2, latMax: 37.5, lngMin: 7.5, lngMax: 11.6 },
|
||||
{ code: 'SN', latMin: 12.3, latMax: 16.7, lngMin: -17.5, lngMax: -11.4 },
|
||||
@@ -55,6 +56,29 @@ export function cleanCityName(city: string): string {
|
||||
return city.split(',')[0].trim();
|
||||
}
|
||||
|
||||
// Noms de pays en français/anglais → code ISO (Cesium+ utilise le français)
|
||||
const COUNTRY_NAME_TO_CODE: Record<string, string> = {
|
||||
'france': 'FR', 'belgique': 'BE', 'belgium': 'BE',
|
||||
'suisse': 'CH', 'switzerland': 'CH', 'schweiz': 'CH',
|
||||
'luxembourg': 'LU', 'allemagne': 'DE', 'germany': 'DE',
|
||||
'espagne': 'ES', 'spain': 'ES', 'portugal': 'PT',
|
||||
'italie': 'IT', 'italy': 'IT', 'pays-bas': 'NL',
|
||||
'netherlands': 'NL', 'royaume-uni': 'GB', 'united kingdom': 'GB',
|
||||
'maroc': 'MA', 'morocco': 'MA', 'tunisie': 'TN', 'tunisia': 'TN',
|
||||
'sénégal': 'SN', 'senegal': 'SN', 'canada': 'CA', 'brésil': 'BR', 'brazil': 'BR',
|
||||
};
|
||||
|
||||
/** Extrait le pays depuis le champ city Cesium+ (ex: "Heusy, 4800, Belgique" → "BE") */
|
||||
function countryCodeFromCity(city: string): string {
|
||||
const parts = city.split(',');
|
||||
for (let i = parts.length - 1; i >= 0; i--) {
|
||||
const token = parts[i].trim().toLowerCase();
|
||||
const code = COUNTRY_NAME_TO_CODE[token];
|
||||
if (code) return code;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// geoPoint accepte n'importe quel type — Cesium+ utilise plusieurs formats ES geo_point
|
||||
const HitSchema = z.object({
|
||||
_id: z.string(),
|
||||
@@ -127,10 +151,11 @@ export async function resolveGeoByKeys(
|
||||
const src = hit._source;
|
||||
const geo = parseGeoPoint(src.geoPoint);
|
||||
if (!geo) continue;
|
||||
const city = src.city ?? 'Inconnue';
|
||||
result.set(hit._id, {
|
||||
name: src.title ?? '',
|
||||
city: src.city ?? 'Inconnue',
|
||||
countryCode: latLngToCountryCode(geo.lat, geo.lng),
|
||||
city,
|
||||
countryCode: countryCodeFromCity(city) || latLngToCountryCode(geo.lat, geo.lng),
|
||||
lat: geo.lat,
|
||||
lng: geo.lng,
|
||||
});
|
||||
@@ -186,10 +211,11 @@ export async function resolveGeoByNames(
|
||||
const src = hit._source;
|
||||
const geo = parseGeoPoint(src.geoPoint);
|
||||
if (geo && src.title) {
|
||||
const city = src.city ?? 'Inconnue';
|
||||
result.set(src.title.toLowerCase(), {
|
||||
name: src.title,
|
||||
city: src.city ?? 'Inconnue',
|
||||
countryCode: latLngToCountryCode(geo.lat, geo.lng),
|
||||
city,
|
||||
countryCode: countryCodeFromCity(city) || latLngToCountryCode(geo.lat, geo.lng),
|
||||
lat: geo.lat,
|
||||
lng: geo.lng,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user