forked from Transparency/kgroad-frontend2
170 lines
4.1 KiB
TypeScript
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='© <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;
|