import { useEffect, useState } from 'react'; import { api } from '../../api.js'; import { BY_CODE, countryName, num, people } from './laender.js'; // Info-Kasten unten links auf der Karte: Land oder Stadt mit Fakten und Wikipedia-Text const languageName = new Intl.DisplayNames(['de'], { type: 'language' }); const currencyName = new Intl.DisplayNames(['de'], { type: 'currency' }); const safe = (fn, v) => { try { return fn(v); } catch { return v; } }; function localTime(timezone) { try { return new Intl.DateTimeFormat('de-DE', { timeZone: timezone, hour: '2-digit', minute: '2-digit' }).format(new Date()); } catch { return null; } } const infoCache = new Map(); function useInfo(params) { const query = new URLSearchParams(params).toString(); const [info, setInfo] = useState(() => infoCache.get(query) || null); useEffect(() => { if (infoCache.has(query)) { setInfo(infoCache.get(query)); return; } let alive = true; api('GET', `/api/reisen/info?${query}`) .then((d) => { if (!d.offline) infoCache.set(query, d); if (alive) setInfo(d); }) .catch(() => alive && setInfo({ offline: true })); return () => { alive = false; }; }, [query]); return info; } export default function InfoCard({ selected, city, cities, otherCities, manual, busy, onSelect, onClose, onMark, onRemoveCity }) { if (selected.type === 'city' && city) { // Wer war (sichtbar) noch in dieser Stadt? const same = [...cities, ...otherCities].filter((c) => c.geonameId === city.geonameId && c.id !== city.id); return ; } if (selected.type === 'country') { return ( c.country === selected.key)} otherCities={otherCities.filter((c) => c.country === selected.key)} manual={manual.includes(selected.key)} onSelect={onSelect} onClose={onClose} onMark={onMark} busy={busy} /> ); } return null; } function Extract({ info }) { if (!info) return

Lade Infos …

; if (info.offline) return

Infotext gerade nicht erreichbar.

; if (!info.extract) return null; return ( <>

{info.extract}

{info.url && Mehr bei Wikipedia ↗} ); } function CountryInfo({ code, cities, otherCities, manual, onSelect, onClose, onMark, busy }) { const c = BY_CODE.get(code); const name = countryName(code); const info = useInfo({ kind: 'land', name: c?.name || name, code }); const visited = manual || cities.length > 0; const facts = [ (info?.capital || c?.capital?.length) && ['Hauptstadt', info?.capital || c.capital.join(', ')], info?.population && ['Einwohner', `${people(info.population)}${info.populationYear ? ` (${info.populationYear})` : ''}`], c?.area && ['Fläche', `${num(Math.round(c.area))} km²`], c?.subregion && ['Region', c.subregion], c?.languages?.length && ['Sprachen', c.languages.map((l) => safe((x) => languageName.of(x), l)).join(', ')], c?.currencies?.length && ['Währung', c.currencies.map((x) => safe((y) => currencyName.of(y), x)).join(', ')], ].filter(Boolean); return ( ); } function OtherChip({ city, onSelect, label = city.name }) { return ( ); } function CityInfo({ city, same, onSelect, onClose, onRemove, busy }) { const c = BY_CODE.get(city.country); const info = useInfo({ kind: 'stadt', name: city.name, code: String(city.geonameId), lat: city.lat, lon: city.lon }); const time = city.timezone && localTime(city.timezone); const facts = [ city.admin1 && ['Region', city.admin1], city.population && ['Einwohner', people(city.population)], city.elevation != null && ['Höhe', `${num(Math.round(city.elevation))} m`], time && ['Ortszeit', `${time} Uhr`], ].filter(Boolean); return ( ); }