satupeta-main/app/(modules)/maps/components/leaflet-map/index.tsx
2026-02-23 12:21:05 +07:00

68 lines
1.9 KiB
TypeScript
Executable File

"use client";
import React, { useEffect, useState } from "react";
import { useAtom, useAtomValue } from "jotai";
import { activeBasemapAtom } from "../../state/active-basemap";
import { basemapConfig } from "../../config/basemap-config";
import { MapContainer } from "react-leaflet";
import L from "leaflet";
import { mapAtom } from "../../state/map";
import { mapSettingsAtom } from "../../state/map-settings";
import ZoomControl from "./zoom-control";
import { LayerManager } from "../layer-manager";
import MapSettings from "../map-settings";
const LeafletMap: React.FC = () => {
const activeBasemap = useAtomValue(activeBasemapAtom);
const [basemapLayer, setBasemapLayer] = useState<L.Layer | null>(null);
const [map, setMap] = useAtom(mapAtom);
const [mapSettings] = useAtom(mapSettingsAtom);
useEffect(() => {
if (!map) return;
const currentConfig = basemapConfig[activeBasemap];
if (!currentConfig?.leaflet) {
console.error(
`Missing Leaflet configuration for basemap: ${activeBasemap}`
);
return;
}
if (basemapLayer) {
map.removeLayer(basemapLayer);
}
const newLayer = L.tileLayer(currentConfig.leaflet.url, {
attribution: currentConfig.leaflet.attribution,
maxZoom: currentConfig.leaflet.maxZoom,
});
setBasemapLayer(newLayer);
map.addLayer(newLayer);
newLayer.bringToBack();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [map, activeBasemap]);
return (
<>
<MapContainer
center={[mapSettings.center[0], mapSettings.center[1]]}
zoom={8}
zoomControl={false}
ref={setMap}
attributionControl={false}
style={{ height: "100%", width: "100%" }}
/>
<LayerManager map={map} />
<div className="absolute top-48 cursor-pointer right-4 z-[403] flex flex-col gap-8">
<MapSettings />
<ZoomControl />
</div>
</>
);
};
export default LeafletMap;