import { FloatingTooltip, Column, useTheme, ColumnProps } from '@umami/react-zen'; import { useState, useMemo } from 'react'; import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps'; import classNames from 'classnames'; import { colord } from 'colord'; import { ISO_COUNTRIES, MAP_FILE } from '@/lib/constants'; import { useDateRange, useWebsiteMetricsQuery, useCountryNames, useLocale, useMessages, } from '@/components/hooks'; import { formatLongNumber } from '@/lib/format'; import { percentFilter } from '@/lib/filters'; import styles from './WorldMap.module.css'; import { getThemeColors } from '@/lib/colors'; export interface WorldMapProps extends ColumnProps { websiteId?: string; data?: any[]; } export function WorldMap({ websiteId, data, className, ...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 visitorsLabel = formatMessage(labels.visitors).toLocaleLowerCase(locale); const unknownLabel = formatMessage(labels.unknown); const { dateRange: { startDate, endDate }, } = useDateRange(websiteId); const { data: mapData } = useWebsiteMetricsQuery(websiteId, { type: 'country', startAt: +startDate, endAt: +endDate, }); const metrics = useMemo( () => (data || mapData ? percentFilter((data || mapData) as any[]) : []), [data, mapData], ); const getFillColor = (code: string) => { if (code === 'AQ') return; const country = metrics?.find(({ x }) => x === code); if (!country) { return colors.map.fillColor; } return colord(colors.map.baseColor) [theme === 'light' ? 'lighten' : 'darken'](0.4 * (1.0 - country.z / 100)) .toHex(); }; const getOpacity = (code: string) => { return code === 'AQ' ? 0 : 1; }; const handleHover = (code: string) => { if (code === 'AQ') return; const country = metrics?.find(({ x }) => x === code); setTooltipPopup( `${countryNames[code] || unknownLabel}: ${formatLongNumber( country?.y || 0, )} ${visitorsLabel}` as any, ); }; return ( {({ geographies }) => { return geographies.map(geo => { const code = ISO_COUNTRIES[geo.id]; return ( handleHover(code)} onMouseOut={() => setTooltipPopup(null)} /> ); }); }} {tooltip && {tooltip}} ); }