You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.3 KiB

import maplibregl from "maplibre-gl";
import Map, { MapProvider } from "react-map-gl";
import { useEffect, useRef } from "react";
import { Sidebar } from "../modules/Sidebar/Sidebar";
import { Layers } from "./Layers";
import { MapPopup } from "./Popup";
import { Basemap } from "./Basemap";
import { SignOut } from "../SignOut";
import debounce from "lodash.debounce";
import { Table } from "../modules/Table/Table";
import { usePopup } from "../stores/usePopup";
import { useClickedPointConfig } from "../stores/useClickedPointConfig";
import { Legend } from "../modules/Sidebar/Legend";
import { AddressSearch } from "../modules/Sidebar/AddressSearch";
export const MapComponent = () => {
const mapRef = useRef(null);
const mapContainerRef = useRef(null);
const { popup, setPopup } = usePopup();
const { setClickedPointConfig } = useClickedPointConfig();
const handleClick = (event) => {
if (!event.features) {
setPopup(null);
setClickedPointConfig(null);
return;
}
const feature = event.features[0];
if (!feature) {
setPopup(null);
setClickedPointConfig(null);
return;
}
const { lng: pointLng } = event.lngLat;
if (feature.geometry.type === "Point") {
const coordinates = feature.geometry.coordinates.slice();
while (Math.abs(pointLng - coordinates[0]) > 180) {
coordinates[0] += pointLng > coordinates[0] ? 360 : -360;
}
setPopup({ features: event.features, coordinates });
}
};
const handleMouseEnter = (event) => {
const feature = event.features[0];
if (!feature) return;
mapRef.current.getCanvas().style.cursor = "pointer";
};
const handleMouseLeave = (event) => {
const feature = event.features[0];
if (!feature) {
return;
}
mapRef.current.getCanvas().style.cursor = "";
};
useEffect(() => {
const resizeObserver = new ResizeObserver(
debounce(() => {
mapRef?.current?.resize();
}, 16)
);
if (mapContainerRef.current) {
resizeObserver.observe(mapContainerRef.current);
}
return () => {
resizeObserver.disconnect();
};
}, [mapContainerRef.current]);
return (
<MapProvider>
<div ref={mapContainerRef} className="w-full flex-1">
<Map
mapLib={maplibregl}
// mapStyle={`https://api.maptiler.com/maps/voyager/style.json?key=${MAP_TILER_KEY}`}
// style={{ width: "100%", height: "100%" }}
initialViewState={{
latitude: 55.7558,
longitude: 37.6173,
zoom: 9,
}}
dragRotate={false}
ref={mapRef}
interactiveLayerIds={["match-points", "unmatch-points"]}
onClick={handleClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
id="map"
>
{popup && (
<MapPopup
lat={popup.coordinates[1]}
lng={popup.coordinates[0]}
features={popup.features}
onClose={() => {
setPopup(null);
setClickedPointConfig(null);
}}
/>
)}
<Basemap />
<Layers />
<Sidebar />
<AddressSearch />
<Legend />
<SignOut />
</Map>
</div>
<Table />
</MapProvider>
);
};