Fix world map country selection handling and preserve map during re-fetch

This commit is contained in:
2026-04-05 22:44:50 +02:00
parent 15d53a8e96
commit 6e2abe9d97
2 changed files with 35 additions and 15 deletions

View File

@@ -113,6 +113,13 @@ export function MapPage(): React.JSX.Element {
const { countries, countryNames, bans, total, loading, error, refresh } =
useMapData(range, originFilter, source, selectedCountry ?? undefined);
// True after the first successful data load — keeps the map mounted
// during subsequent re-fetches so country selection gives instant feedback.
const [hasLoadedOnce, setHasLoadedOnce] = useState(false);
useEffect(() => {
if (!loading && !error) setHasLoadedOnce(true);
}, [loading, error]);
const {
thresholds: mapThresholds,
error: mapThresholdError,
@@ -195,7 +202,8 @@ export function MapPage(): React.JSX.Element {
</MessageBar>
)}
{loading && !error && (
{/* Initial load spinner — only shown before the first data arrives. */}
{loading && !error && !hasLoadedOnce && (
<div style={{ display: "flex", justifyContent: "center", padding: tokens.spacingVerticalXL }}>
<Spinner label="Loading map data…" />
</div>
@@ -203,8 +211,10 @@ export function MapPage(): React.JSX.Element {
{/* ---------------------------------------------------------------- */}
{/* World map */}
{/* Keep the map mounted after first load so clicking a country gives */}
{/* immediate visual feedback before the filtered data arrives. */}
{/* ---------------------------------------------------------------- */}
{!loading && !error && (
{!error && hasLoadedOnce && (
<WorldMap
countries={countries}
countryNames={countryNames}
@@ -242,19 +252,22 @@ export function MapPage(): React.JSX.Element {
{/* ---------------------------------------------------------------- */}
{/* Summary line */}
{/* ---------------------------------------------------------------- */}
{!loading && !error && (
<Text size={300} style={{ color: tokens.colorNeutralForeground3 }}>
{String(total)} total ban{total !== 1 ? "s" : ""} in the selected period
{" · "}
{String(Object.keys(countries).length)} countr{Object.keys(countries).length !== 1 ? "ies" : "y"} affected
</Text>
{!error && hasLoadedOnce && (
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS }}>
<Text size={300} style={{ color: tokens.colorNeutralForeground3 }}>
{String(total)} total ban{total !== 1 ? "s" : ""} in the selected period
{" · "}
{String(Object.keys(countries).length)} countr{Object.keys(countries).length !== 1 ? "ies" : "y"} affected
</Text>
{loading && <Spinner size="tiny" />}
</div>
)}
{/* ---------------------------------------------------------------- */}
{/* Companion bans table */}
{/* ---------------------------------------------------------------- */}
{!loading && !error && (
<div className={styles.tableWrapper}>
{!error && hasLoadedOnce && (
<div className={styles.tableWrapper} style={{ opacity: loading ? 0.5 : 1, transition: "opacity 150ms" }}>
<Table size="small" aria-label="Bans list">
<TableHeader>
<TableRow>