diff --git a/sigap-website/app/_components/map/crime-map.tsx b/sigap-website/app/_components/map/crime-map.tsx index c0046ae..2e932f4 100644 --- a/sigap-website/app/_components/map/crime-map.tsx +++ b/sigap-website/app/_components/map/crime-map.tsx @@ -105,25 +105,6 @@ export default function CrimeMap() { }) }, [filteredByYearAndMonth, selectedCategory]) - // Extract all incidents from all districts for marker display - // const allIncidents = useMemo(() => { - // if (!filteredCrimes) return [] - - // return filteredCrimes.flatMap((crime) => - // crime.crime_incidents.map((incident) => ({ - // id: incident.id, - // timestamp: incident.timestamp, - // description: incident.description, - // status: incident.status, - // category: incident.crime_categories.name, - // type: incident.crime_categories.type, - // address: incident.locations.address, - // latitude: incident.locations.latitude, - // longitude: incident.locations.longitude, - // })) - // ) - // }, [filteredCrimes]) - // Handle incident marker click const handleIncidentClick = (incident: CrimeIncident) => { console.log("Incident clicked directly:", incident); @@ -184,10 +165,12 @@ export default function CrimeMap() { // Handle district click const handleDistrictClick = (feature: DistrictFeature) => { + console.log("District clicked in CrimeMap:", feature.name); + // When a district is clicked, clear any selected incident setSelectedIncident(null); - // Set the selected district + // Set the selected district (for the sidebar or other components) setSelectedDistrict(feature); } @@ -250,7 +233,16 @@ export default function CrimeMap() { !sidebarCollapsed && isFullscreen && "ml-[400px]" )}> - {/* District Layer with crime data */} + {/* District Layer with crime data - don't pass onClick if we want internal popup */} + + + {/* Pass onClick if you want to handle districts externally */} + {/* + */} {/* Popup for selected incident */} {selectedIncident && selectedIncident.latitude && selectedIncident.longitude && ( diff --git a/sigap-website/app/_components/map/layers/district-layer.tsx b/sigap-website/app/_components/map/layers/district-layer.tsx index ddb8e37..96da11f 100644 --- a/sigap-website/app/_components/map/layers/district-layer.tsx +++ b/sigap-website/app/_components/map/layers/district-layer.tsx @@ -12,7 +12,6 @@ import { ICrimes } from "@/app/_utils/types/crimes" export interface DistrictFeature { id: string name: string - properties: Record longitude: number latitude: number number_of_crime: number @@ -45,56 +44,14 @@ export interface DistrictFeature { selectedMonth?: string } -// Updated interface to match the structure in crimes.ts -// export interface ICrimeData { -// id: string -// district_id: string -// districts: { -// name: string -// geographics: { -// address: string | null -// land_area: number | null -// year: number | null -// latitude: number -// longitude: number -// }[] -// demographics: { -// number_of_unemployed: number -// population: number -// population_density: number -// year: number -// }[] -// } -// number_of_crime: number -// level: $Enums.crime_rates -// score: number -// month: number -// year: number -// crime_incidents: Array<{ -// id: string -// timestamp: Date -// description: string -// status: string -// crime_categories: { -// name: string -// type: string | null -// } -// locations: { -// address: string | null -// latitude: number -// longitude: number -// } -// }> -// } - // District layer props export interface DistrictLayerProps { visible?: boolean onClick?: (feature: DistrictFeature) => void - year?: string - month?: string - filterCategory?: string | "all" - crimes?: ICrimes[] + year: string + month: string + filterCategory: string | "all" + crimes: ICrimes[] tilesetId?: string } @@ -179,8 +136,34 @@ export default function DistrictLayer({ }) const firstDistrictCrime = districtCrimes.length > 0 ? districtCrimes[0] : null - const demographics = firstDistrictCrime?.districts.demographics?.[0] - const geographics = firstDistrictCrime?.districts.geographics?.[0] + + const selectedYearNum = year ? parseInt(year) : new Date().getFullYear(); + + let demographics = firstDistrictCrime?.districts.demographics?.find( + d => d.year === selectedYearNum + ); + + if (!demographics && firstDistrictCrime?.districts.demographics?.length) { + demographics = firstDistrictCrime.districts.demographics + .sort((a, b) => b.year - a.year)[0]; + console.log(`Tidak ada data demografis untuk tahun ${selectedYearNum}, menggunakan data tahun ${demographics.year}`); + } + + let geographics = firstDistrictCrime?.districts.geographics?.find( + g => g.year === selectedYearNum + ); + + if (!geographics && firstDistrictCrime?.districts.geographics?.length) { + const validGeographics = firstDistrictCrime.districts.geographics + .filter(g => g.year !== null) + .sort((a, b) => (b.year || 0) - (a.year || 0)); + + geographics = validGeographics.length > 0 ? + validGeographics[0] : + firstDistrictCrime.districts.geographics[0]; + + console.log(`Tidak ada data geografis untuk tahun ${selectedYearNum}, menggunakan data ${geographics.year ? `tahun ${geographics.year}` : 'tanpa tahun'}`); + } const clickLng = e.lngLat ? e.lngLat.lng : null const clickLat = e.lngLat ? e.lngLat.lat : null @@ -198,7 +181,7 @@ export default function DistrictLayer({ const district: DistrictFeature = { id: districtId, name: feature.properties.nama || feature.properties.kecamatan || "Unknown District", - properties: feature.properties, + // properties: feature.properties, longitude: geographics.longitude || clickLng || 0, latitude: geographics.latitude || clickLat || 0, number_of_crime: crimeData.number_of_crime || 0, @@ -227,6 +210,7 @@ export default function DistrictLayer({ } selectedDistrictRef.current = district; + console.log("District clicked, selectedDistrictRef set to:", selectedDistrictRef.current); if (onClick) { onClick(district); @@ -300,6 +284,7 @@ export default function DistrictLayer({ }, [map]); const handleCloseDistrictPopup = useCallback(() => { + console.log("Closing district popup"); selectedDistrictRef.current = null; setSelectedDistrict(null); }, []); @@ -685,8 +670,30 @@ export default function DistrictLayer({ const districtCrime = crimes.find(crime => crime.district_id === districtId); if (districtCrime) { - const demographics = districtCrime.districts.demographics?.[0]; - const geographics = districtCrime.districts.geographics?.[0]; + const selectedYearNum = year ? parseInt(year) : new Date().getFullYear(); + + let demographics = districtCrime.districts.demographics?.find( + d => d.year === selectedYearNum + ); + + if (!demographics && districtCrime.districts.demographics?.length) { + demographics = districtCrime.districts.demographics + .sort((a, b) => b.year - a.year)[0]; + } + + let geographics = districtCrime.districts.geographics?.find( + g => g.year === selectedYearNum + ); + + if (!geographics && districtCrime.districts.geographics?.length) { + const validGeographics = districtCrime.districts.geographics + .filter(g => g.year !== null) + .sort((a, b) => (b.year || 0) - (a.year || 0)); + + geographics = validGeographics.length > 0 ? + validGeographics[0] : + districtCrime.districts.geographics[0]; + } if (!demographics || !geographics) { console.error("Missing district data:", { demographics, geographics }); @@ -749,17 +756,17 @@ export default function DistrictLayer({ return ( <> - {selectedDistrictRef.current ? ( + {selectedDistrict && ( - ) : null} + )} ) } diff --git a/sigap-website/app/_components/map/pop-up/district-popup.tsx b/sigap-website/app/_components/map/pop-up/district-popup.tsx index acb2e7d..3ece597 100644 --- a/sigap-website/app/_components/map/pop-up/district-popup.tsx +++ b/sigap-website/app/_components/map/pop-up/district-popup.tsx @@ -1,6 +1,6 @@ "use client" -import { useState, useMemo } from "react" +import { useState, useMemo, useEffect } from "react" import { Popup } from "react-map-gl/mapbox" import { Badge } from "@/app/_components/ui/badge" import { Card } from "@/app/_components/ui/card" @@ -46,6 +46,16 @@ export default function DistrictPopup({ }: DistrictPopupProps) { const [activeTab, setActiveTab] = useState("overview") + // Add debug log when the component is rendered + useEffect(() => { + console.log("DistrictPopup mounted:", { + district: district.name, + coords: [longitude, latitude], + year, + month + }); + }, [district, longitude, latitude, year, month]); + // Extract all crime incidents from the district data and apply filtering if needed const allCrimeIncidents = useMemo(() => { // Check if there are crime incidents in the district object