2022-12-29 00:43:22 +01:00
|
|
|
import { useState, useMemo } from 'react';
|
2021-03-27 06:32:13 +01:00
|
|
|
import { useRouter } from 'next/router';
|
2020-09-20 10:33:39 +02:00
|
|
|
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
|
2020-08-01 12:34:56 +02:00
|
|
|
import classNames from 'classnames';
|
2022-01-14 09:39:27 +01:00
|
|
|
import { colord } from 'colord';
|
2023-04-21 17:00:42 +02:00
|
|
|
import HoverTooltip from 'components/common/HoverTooltip';
|
2021-03-27 06:32:13 +01:00
|
|
|
import { ISO_COUNTRIES, THEME_COLORS, MAP_FILE } from 'lib/constants';
|
2023-04-21 17:00:42 +02:00
|
|
|
import useTheme from 'hooks/useTheme';
|
2020-10-01 01:27:27 +02:00
|
|
|
import useCountryNames from 'hooks/useCountryNames';
|
|
|
|
import useLocale from 'hooks/useLocale';
|
2023-04-14 07:28:29 +02:00
|
|
|
import { formatLongNumber } from 'lib/format';
|
|
|
|
import { percentFilter } from 'lib/filters';
|
2023-04-21 17:00:42 +02:00
|
|
|
import styles from './WorldMap.module.css';
|
2020-08-01 12:34:56 +02:00
|
|
|
|
2023-04-21 17:00:42 +02:00
|
|
|
export function WorldMap({ data, className }) {
|
2021-03-27 06:32:13 +01:00
|
|
|
const { basePath } = useRouter();
|
2020-08-01 12:34:56 +02:00
|
|
|
const [tooltip, setTooltip] = useState();
|
2020-09-20 10:33:39 +02:00
|
|
|
const [theme] = useTheme();
|
|
|
|
const colors = useMemo(
|
|
|
|
() => ({
|
|
|
|
baseColor: THEME_COLORS[theme].primary,
|
|
|
|
fillColor: THEME_COLORS[theme].gray100,
|
|
|
|
strokeColor: THEME_COLORS[theme].primary,
|
|
|
|
hoverColor: THEME_COLORS[theme].primary,
|
|
|
|
}),
|
|
|
|
[theme],
|
|
|
|
);
|
2021-06-30 03:41:34 +02:00
|
|
|
const { locale } = useLocale();
|
2020-10-01 01:27:27 +02:00
|
|
|
const countryNames = useCountryNames(locale);
|
2023-04-14 08:05:54 +02:00
|
|
|
const metrics = useMemo(() => (data ? percentFilter(data) : []), [data]);
|
2020-08-01 12:34:56 +02:00
|
|
|
|
|
|
|
function getFillColor(code) {
|
2020-09-20 10:33:39 +02:00
|
|
|
if (code === 'AQ') return;
|
2023-04-14 07:28:29 +02:00
|
|
|
const country = metrics?.find(({ x }) => x === code);
|
2020-08-01 12:34:56 +02:00
|
|
|
|
2020-09-20 10:33:39 +02:00
|
|
|
if (!country) {
|
|
|
|
return colors.fillColor;
|
|
|
|
}
|
|
|
|
|
2022-01-14 09:39:27 +01:00
|
|
|
return colord(colors.baseColor)
|
|
|
|
[theme === 'light' ? 'lighten' : 'darken'](0.4 * (1.0 - country.z / 100))
|
|
|
|
.toHex();
|
2020-08-01 12:34:56 +02:00
|
|
|
}
|
|
|
|
|
2020-09-20 10:33:39 +02:00
|
|
|
function getOpacity(code) {
|
|
|
|
return code === 'AQ' ? 0 : 1;
|
2020-08-01 12:34:56 +02:00
|
|
|
}
|
|
|
|
|
2020-10-01 01:27:27 +02:00
|
|
|
function handleHover(code) {
|
2020-09-20 10:33:39 +02:00
|
|
|
if (code === 'AQ') return;
|
2023-04-14 07:28:29 +02:00
|
|
|
const country = metrics?.find(({ x }) => x === code);
|
2023-03-14 19:35:24 +01:00
|
|
|
setTooltip(`${countryNames[code]}: ${formatLongNumber(country?.y || 0)} visitors`);
|
2020-08-01 12:34:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2020-09-20 10:33:39 +02:00
|
|
|
<div
|
|
|
|
className={classNames(styles.container, className)}
|
|
|
|
data-tip=""
|
|
|
|
data-for="world-map-tooltip"
|
|
|
|
>
|
|
|
|
<ComposableMap projection="geoMercator">
|
2020-08-01 12:34:56 +02:00
|
|
|
<ZoomableGroup zoom={0.8} minZoom={0.7} center={[0, 40]}>
|
2021-03-27 06:32:13 +01:00
|
|
|
<Geographies geography={`${basePath}${MAP_FILE}`}>
|
2020-08-01 12:34:56 +02:00
|
|
|
{({ geographies }) => {
|
|
|
|
return geographies.map(geo => {
|
2021-03-27 03:47:28 +01:00
|
|
|
const code = ISO_COUNTRIES[geo.id];
|
2020-08-01 12:34:56 +02:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Geography
|
|
|
|
key={geo.rsmKey}
|
|
|
|
geography={geo}
|
|
|
|
fill={getFillColor(code)}
|
2020-09-20 10:33:39 +02:00
|
|
|
stroke={colors.strokeColor}
|
|
|
|
opacity={getOpacity(code)}
|
2020-08-01 12:34:56 +02:00
|
|
|
style={{
|
|
|
|
default: { outline: 'none' },
|
2020-09-20 10:33:39 +02:00
|
|
|
hover: { outline: 'none', fill: colors.hoverColor },
|
2020-08-01 12:34:56 +02:00
|
|
|
pressed: { outline: 'none' },
|
|
|
|
}}
|
2020-10-01 01:27:27 +02:00
|
|
|
onMouseOver={() => handleHover(code)}
|
2020-08-01 12:34:56 +02:00
|
|
|
onMouseOut={() => setTooltip(null)}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
</Geographies>
|
|
|
|
</ZoomableGroup>
|
|
|
|
</ComposableMap>
|
2023-03-14 19:35:24 +01:00
|
|
|
{tooltip && <HoverTooltip tooltip={tooltip} />}
|
2020-08-01 12:34:56 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2021-02-16 14:18:27 +01:00
|
|
|
|
|
|
|
export default WorldMap;
|