"use client" import { createFillColorExpression, processDistrictFeature } from "@/app/_utils/map" import { IDistrictLayerProps } from "@/app/_utils/types/map" import { useEffect } from "react" export default function DistrictFillLineLayer({ visible = true, map, onClick, year, month, filterCategory = "all", crimes = [], tilesetId, focusedDistrictId, setFocusedDistrictId, crimeDataByDistrict, }: IDistrictLayerProps) { useEffect(() => { if (!map || !visible) return const handleDistrictClick = (e: any) => { const incidentFeatures = map.queryRenderedFeatures(e.point, { layers: ["unclustered-point", "clusters"], }) if (incidentFeatures && incidentFeatures.length > 0) { return } if (!map || !e.features || e.features.length === 0) return const feature = e.features[0] const districtId = feature.properties.kode_kec // If clicking the same district, deselect it if (focusedDistrictId === districtId) { setFocusedDistrictId(null) // Reset pitch and bearing with animation map.easeTo({ pitch: 0, bearing: 0, duration: 1500, easing: (t) => t * (2 - t), // easeOutQuad }) // Show all clusters again when unfocusing if (map.getLayer("clusters")) { map.setLayoutProperty("clusters", "visibility", "visible") } if (map.getLayer("unclustered-point")) { map.setLayoutProperty("unclustered-point", "visibility", "visible") } return } const district = processDistrictFeature(feature, e, districtId, crimeDataByDistrict, crimes, year, month) if (!district) return setFocusedDistrictId(district.id) // Hide clusters when focusing on a district if (map.getLayer("clusters")) { map.setLayoutProperty("clusters", "visibility", "none") } if (map.getLayer("unclustered-point")) { map.setLayoutProperty("unclustered-point", "visibility", "none") } // Animate to a pitched view focused on the district map.flyTo({ center: [district.longitude, district.latitude], zoom: 12.5, pitch: 75, bearing: 0, duration: 1500, easing: (t) => t * (2 - t), // easeOutQuad }) if (onClick) { onClick(district) } } const onStyleLoad = () => { if (!map) return try { if (!map.getSource("districts")) { const layers = map.getStyle().layers let firstSymbolId: string | undefined for (const layer of layers) { if (layer.type === "symbol") { firstSymbolId = layer.id break } } map.addSource("districts", { type: "vector", url: `mapbox://${tilesetId}`, }) const fillColorExpression = createFillColorExpression(focusedDistrictId, crimeDataByDistrict) if (!map.getLayer("district-fill")) { map.addLayer( { id: "district-fill", type: "fill", source: "districts", "source-layer": "Districts", paint: { "fill-color": fillColorExpression as any, "fill-opacity": 0.6, }, }, firstSymbolId, ) } if (!map.getLayer("district-line")) { map.addLayer( { id: "district-line", type: "line", source: "districts", "source-layer": "Districts", paint: { "line-color": "#ffffff", "line-width": 1, "line-opacity": 0.5, }, }, firstSymbolId, ) } map.on("mouseenter", "district-fill", () => { map.getCanvas().style.cursor = "pointer" }) map.on("mouseleave", "district-fill", () => { map.getCanvas().style.cursor = "" }) map.off("click", "district-fill", handleDistrictClick) map.on("click", "district-fill", handleDistrictClick) } else { if (map.getLayer("district-fill")) { const fillColorExpression = createFillColorExpression(focusedDistrictId, crimeDataByDistrict) map.setPaintProperty("district-fill", "fill-color", fillColorExpression as any) } } } catch (error) { console.error("Error adding district layers:", error) } } if (map.isStyleLoaded()) { onStyleLoad() } else { map.once("style.load", onStyleLoad) } return () => { if (map) { map.off("click", "district-fill", handleDistrictClick) } } }, [ map, visible, tilesetId, crimes, filterCategory, year, month, focusedDistrictId, crimeDataByDistrict, onClick, setFocusedDistrictId, ]) return null }