mirror of
https://github.com/TheRealOwenRees/echecsfrance.git
synced 2026-07-23 12:36:57 +00:00
99 lines
2.8 KiB
TypeScript
99 lines
2.8 KiB
TypeScript
"use client";
|
|
|
|
import { useCallback, useMemo } from "react";
|
|
|
|
import { useAtomValue } from "jotai";
|
|
import L, { LatLngLiteral } from "leaflet";
|
|
import "leaflet-defaulticon-compatibility";
|
|
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
|
|
import "leaflet.smooth_marker_bouncing";
|
|
import "leaflet/dist/leaflet.css";
|
|
import { countBy, groupBy } from "lodash";
|
|
|
|
import {
|
|
filteredTournamentsByTimeControlAtom,
|
|
normsOnlyAtom,
|
|
} from "@/app/atoms";
|
|
import { TimeControlColours } from "@/app/constants";
|
|
import { Map, MapMarker } from "@/components/Map";
|
|
import { generatePieSVG } from "@/lib/pie";
|
|
import { TimeControl } from "@/types";
|
|
|
|
import Legend from "./Legend";
|
|
import TimeControlFilters from "./TimeControlFilters";
|
|
import { TournamentMarker } from "./TournamentMarker";
|
|
|
|
const TournamentMap = () => {
|
|
const tournaments = useAtomValue(filteredTournamentsByTimeControlAtom);
|
|
const normsOnly = useAtomValue(normsOnlyAtom);
|
|
|
|
const filteredTournaments = useMemo(
|
|
() => tournaments.filter((t) => (normsOnly ? t.norm : true)),
|
|
[normsOnly, tournaments],
|
|
);
|
|
|
|
const groupedTournaments = groupBy(filteredTournaments, (t) => t.groupId);
|
|
|
|
const createClusterCustomIcon = useCallback((cluster: any) => {
|
|
const childCount = cluster.getChildCount();
|
|
const children = cluster.getAllChildMarkers();
|
|
|
|
// We added the time control as the class name when creating the marker
|
|
const timeControlCounts = countBy(
|
|
children,
|
|
(child: any) => child.options.icon.options.className,
|
|
);
|
|
|
|
const html = `
|
|
<div>
|
|
${generatePieSVG(
|
|
"absolute w-[30px]",
|
|
15,
|
|
[
|
|
TimeControl.Classic,
|
|
TimeControl.Rapid,
|
|
TimeControl.Blitz,
|
|
TimeControl.Other,
|
|
].map((tc) => ({
|
|
value: timeControlCounts[tc] ?? 0,
|
|
colour: TimeControlColours[tc],
|
|
})),
|
|
)}
|
|
<span class="text-white font-semibold relative z-[300]">${childCount}</span>
|
|
</div>
|
|
`;
|
|
|
|
return new L.DivIcon({
|
|
html,
|
|
className: "marker-cluster bg-gray-600/20",
|
|
iconSize: new L.Point(40, 40),
|
|
});
|
|
}, []);
|
|
|
|
const markers: MapMarker[] = useMemo(
|
|
() =>
|
|
Object.values(groupedTournaments).map((tournamentGroup) => {
|
|
const { groupId } = tournamentGroup[0];
|
|
return {
|
|
markerId: groupId,
|
|
tableIds: tournamentGroup.map((t) => t.id),
|
|
component: (
|
|
<TournamentMarker key={groupId} tournamentGroup={tournamentGroup} />
|
|
),
|
|
};
|
|
}),
|
|
[groupedTournaments],
|
|
);
|
|
|
|
return (
|
|
<Map
|
|
markers={markers}
|
|
legend={<Legend />}
|
|
filters={<TimeControlFilters />}
|
|
iconCreateFunction={createClusterCustomIcon}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export default TournamentMap;
|