From 60a824498a6c7f24950f1f86eac0c2a1d434dc40 Mon Sep 17 00:00:00 2001 From: Sajid Mehmood Date: Thu, 6 Aug 2026 22:30:44 -0400 Subject: [PATCH] Filter by country when clicking the world map Clicking a country on the world map now applies the same `country=eq.` filter that the countries table produces, so the whole dashboard scopes to that country. Clicking the already-selected country clears the filter, and the selected country is highlighted on the map. The realtime page opts out (allowFilter={false}) since realtime data does not support filters. Run-on: Niteshift Co-Authored-By: Claude Opus 5 --- .../[websiteId]/realtime/RealtimePage.tsx | 2 +- src/components/metrics/WorldMap.tsx | 29 ++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/realtime/RealtimePage.tsx b/src/app/(main)/websites/[websiteId]/realtime/RealtimePage.tsx index 6220c6957..d9933d0e6 100644 --- a/src/app/(main)/websites/[websiteId]/realtime/RealtimePage.tsx +++ b/src/app/(main)/websites/[websiteId]/realtime/RealtimePage.tsx @@ -50,7 +50,7 @@ export function RealtimePage({ websiteId }: { websiteId: string }) { - + diff --git a/src/components/metrics/WorldMap.tsx b/src/components/metrics/WorldMap.tsx index 3c8fadb80..a939e1cd1 100644 --- a/src/components/metrics/WorldMap.tsx +++ b/src/components/metrics/WorldMap.tsx @@ -6,6 +6,7 @@ import { useCountryNames, useLocale, useMessages, + useNavigation, useWebsiteMetricsQuery, } from '@/components/hooks'; import { getThemeColors } from '@/lib/colors'; @@ -16,17 +17,20 @@ import { formatLongNumber } from '@/lib/format'; export interface WorldMapProps extends ColumnProps { websiteId?: string; data?: any[]; + allowFilter?: boolean; } -export function WorldMap({ websiteId, data, ...props }: WorldMapProps) { +export function WorldMap({ websiteId, data, allowFilter = true, ...props }: WorldMapProps) { const [tooltip, setTooltipPopup] = useState(); const { theme } = useTheme(); const { colors } = getThemeColors(theme); const { locale } = useLocale(); const { formatMessage, labels } = useMessages(); const { countryNames } = useCountryNames(locale); + const { router, updateParams, query } = useNavigation(); const visitorsLabel = formatMessage(labels.visitors).toLocaleLowerCase(locale); const unknownLabel = formatMessage(labels.unknown); + const selectedCountry = allowFilter ? query.country?.replace(/^eq\./, '') : undefined; const { data: mapData } = useWebsiteMetricsQuery(websiteId, { type: 'country', @@ -39,6 +43,11 @@ export function WorldMap({ websiteId, data, ...props }: WorldMapProps) { const getFillColor = (code: string) => { if (code === 'AQ') return; + + if (code && code === selectedCountry) { + return colors.map.hoverColor; + } + const country = metrics?.find(({ x }) => x === code); if (!country) { @@ -54,6 +63,16 @@ export function WorldMap({ websiteId, data, ...props }: WorldMapProps) { return code === 'AQ' ? 0 : 1; }; + const isClickable = (code: string) => { + return allowFilter && !!code && code !== 'AQ'; + }; + + const handleClick = (code: string) => { + if (!isClickable(code)) return; + + router.replace(updateParams({ country: code === selectedCountry ? undefined : `eq.${code}` })); + }; + const handleHover = (code: string) => { if (code === 'AQ') return; const country = metrics?.find(({ x }) => x === code); @@ -77,6 +96,7 @@ export function WorldMap({ websiteId, data, ...props }: WorldMapProps) { {({ geographies }) => { return geographies.map(geo => { const code = ISO_COUNTRIES[geo.id]; + const cursor = isClickable(code) ? 'pointer' : 'default'; return ( handleHover(code)} onMouseOut={() => setTooltipPopup(null)} + onClick={() => handleClick(code)} /> ); });