kgroad-frontend2/src/widgets/MapSection/HomeMap/HomeMap.tsx
2024-02-24 11:38:42 +00:00

170 lines
4.1 KiB
TypeScript

"use client";
import "./HomeMap.scss";
import "leaflet/dist/leaflet.css";
import {
MapContainer,
Marker,
Polyline,
Popup,
TileLayer,
useMap,
} from "react-leaflet";
import geo_green_icon from "./icons/geo-green.svg";
import geo_orange_icon from "./icons/geo-orange.svg";
import geo_pink_icon from "./icons/geo-pink.svg";
import geo_purple_icon from "./icons/geo-purple.svg";
import geo_red_icon from "./icons/geo-red.svg";
import geo_yellow_icon from "./icons/geo-yellow.svg";
import geo_white_icon from "./icons/geo-white.svg";
import {
DivIcon,
Icon,
LatLngExpression,
LatLngTuple,
} from "leaflet";
import { StaticImageData } from "next/image";
import Link from "next/link";
import { Fragment, useEffect, useState } from "react";
import L from "leaflet";
import { ILocation } from "@/shared/types/location-type";
import { useMapStore } from "../mapSectionStore";
interface IData {
id: number;
location: ILocation[];
category: number;
}
interface ILatLng {
lat: number;
lng: number;
}
interface IHomeMapProps {
reports: IData[];
}
const HomeMap: React.FC<IHomeMapProps> = ({
reports,
}: IHomeMapProps) => {
const { display_location, latLng } = useMapStore();
const [position, setPosition] = useState<ILatLng>({
lat: 42.8746,
lng: 74.606,
});
const createCustomIcon = (icon: StaticImageData) => {
const customIcon = new Icon({
iconUrl: icon.src,
iconSize: [64, 64],
});
return customIcon;
};
const icons: Record<string, DivIcon> = {
1: createCustomIcon(geo_red_icon),
2: createCustomIcon(geo_pink_icon),
3: createCustomIcon(geo_purple_icon),
4: createCustomIcon(geo_orange_icon),
5: createCustomIcon(geo_yellow_icon),
6: createCustomIcon(geo_green_icon),
};
const searchResultIcon = new Icon({
iconUrl: geo_white_icon.src,
iconSize: [100, 100],
});
const categoryToPolyline: Record<number, { color: string }> = {
1: { color: "rgba(230, 68, 82, 0.8)" },
2: { color: "rgba(198, 152, 224, 0.8)" },
3: { color: "rgba(135, 40, 157, 0.8)" },
4: { color: "rgba(247, 181, 84, 0.8)" },
5: { color: "rgba(254, 211, 99, 0.8)" },
6: { color: "rgba(158, 221, 128, 0.8)" },
};
const LocationMark = () => {
const map = useMap();
map.setView(L.latLng(latLng), map.getZoom(), { animate: true });
useEffect(() => {
setPosition(latLng);
}, [latLng]);
const defPosition = {
lat: 42.8746,
lng: 74.606,
};
if (
latLng.lat === defPosition.lat &&
latLng.lng === defPosition.lng
)
return null;
return (
<Marker position={latLng} icon={searchResultIcon}>
<Popup>{display_location}</Popup>
</Marker>
);
};
return (
<MapContainer
center={position}
zoom={14}
scrollWheelZoom={false}
className="home-map"
>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{reports.map((report) =>
report.location.length === 2 ? (
<Polyline
key={report.id}
pathOptions={categoryToPolyline[report.category]}
positions={[
[
parseFloat(report.location[0].latitude),
parseFloat(report.location[0].longitude),
],
[
parseFloat(report.location[1].latitude),
parseFloat(report.location[1].longitude),
],
]}
/>
) : null
)}
{reports.map((report) =>
report.location.map((marker) => (
<Marker
key={marker.id}
icon={icons[report.category]}
position={
[+marker.latitude, +marker.longitude] as LatLngTuple
}
>
<Popup>
<Link href={`/report/${report?.id}`}>
{marker.address}
</Link>
</Popup>
</Marker>
))
)}
<LocationMark />
</MapContainer>
);
};
export default HomeMap;