feat: remove fill when district pop up is close
This commit is contained in:
parent
5808758855
commit
f4b6d19eb2
|
@ -11,7 +11,7 @@ import TimelineLayer from "./timeline-layer"
|
||||||
|
|
||||||
import type { ICrimes, IIncidentLogs } from "@/app/_utils/types/crimes"
|
import type { ICrimes, IIncidentLogs } from "@/app/_utils/types/crimes"
|
||||||
import type { IDistrictFeature } from "@/app/_utils/types/map"
|
import type { IDistrictFeature } from "@/app/_utils/types/map"
|
||||||
import { createFillColorExpression, processCrimeDataByDistrict } from "@/app/_utils/map"
|
import { createFillColorExpression, getCrimeRateColor, processCrimeDataByDistrict } from "@/app/_utils/map"
|
||||||
import UnclusteredPointLayer from "./uncluster-layer"
|
import UnclusteredPointLayer from "./uncluster-layer"
|
||||||
|
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
|
@ -153,17 +153,20 @@ export default function Layers({
|
||||||
easing: (t) => t * (2 - t),
|
easing: (t) => t * (2 - t),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (map.getLayer("clusters")) {
|
if (map.getLayer("clusters")) {
|
||||||
map.getMap().setLayoutProperty("clusters", "visibility", "visible")
|
map.getMap().setLayoutProperty("clusters", "visibility", "visible")
|
||||||
}
|
}
|
||||||
if (map.getLayer("unclustered-point")) {
|
|
||||||
map.getMap().setLayoutProperty("unclustered-point", "visibility", "visible")
|
if (map.getLayer("unclustered-point")) {
|
||||||
}
|
map.getMap().setLayoutProperty("unclustered-point", "visibility", "visible")
|
||||||
|
}
|
||||||
|
|
||||||
if (map.getLayer("district-fill")) {
|
if (map.getLayer("district-fill")) {
|
||||||
const fillColorExpression = createFillColorExpression(null, crimeDataByDistrict)
|
const fillColorExpression = createFillColorExpression(null, crimeDataByDistrict)
|
||||||
map.getMap().setPaintProperty("district-fill", "fill-color", fillColorExpression as any)
|
map.getMap().setPaintProperty("district-fill", "fill-color", fillColorExpression as any)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}, [map, crimeDataByDistrict])
|
}, [map, crimeDataByDistrict])
|
||||||
|
|
||||||
|
@ -213,6 +216,19 @@ export default function Layers({
|
||||||
0,
|
0,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
map.getMap().setPaintProperty("district-extrusion", "fill-extrusion-color", [
|
||||||
|
"case",
|
||||||
|
["has", "kode_kec"],
|
||||||
|
[
|
||||||
|
"match",
|
||||||
|
["get", "kode_kec"],
|
||||||
|
focusedDistrictId || "",
|
||||||
|
"transparent",
|
||||||
|
"transparent",
|
||||||
|
],
|
||||||
|
"transparent",
|
||||||
|
])
|
||||||
|
|
||||||
if (progress < 1) {
|
if (progress < 1) {
|
||||||
animationRef.current = requestAnimationFrame(animate)
|
animationRef.current = requestAnimationFrame(animate)
|
||||||
} else {
|
} else {
|
||||||
|
@ -270,7 +286,7 @@ export default function Layers({
|
||||||
easing: (t) => t * (2 - t),
|
easing: (t) => t * (2 - t),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Hide clusters when focusing on a district
|
// Hide clusters when focusing on a district
|
||||||
if (map.getLayer("clusters")) {
|
if (map.getLayer("clusters")) {
|
||||||
map.getMap().setLayoutProperty("clusters", "visibility", "none")
|
map.getMap().setLayoutProperty("clusters", "visibility", "none")
|
||||||
}
|
}
|
||||||
|
@ -289,16 +305,16 @@ export default function Layers({
|
||||||
const customEvent = e as CustomEvent
|
const customEvent = e as CustomEvent
|
||||||
if (!map || !customEvent.detail) return
|
if (!map || !customEvent.detail) return
|
||||||
|
|
||||||
const { longitude, latitude, zoom, bearing, pitch, duration } = customEvent.detail
|
const { longitude, latitude, zoom, bearing, pitch, duration } = customEvent.detail
|
||||||
|
|
||||||
map.flyTo({
|
map.flyTo({
|
||||||
center: [longitude, latitude],
|
center: [longitude, latitude],
|
||||||
zoom: zoom || 15,
|
zoom: zoom || 15,
|
||||||
bearing: bearing || 0,
|
bearing: bearing || 0,
|
||||||
pitch: pitch || 45,
|
pitch: pitch || 45,
|
||||||
duration: duration || 2000,
|
duration: duration || 2000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
mapboxMap.getCanvas().addEventListener("mapbox_fly_to", handleFlyToEvent as EventListener)
|
mapboxMap.getCanvas().addEventListener("mapbox_fly_to", handleFlyToEvent as EventListener)
|
||||||
|
|
||||||
|
@ -316,93 +332,93 @@ export default function Layers({
|
||||||
const customEvent = e as CustomEvent
|
const customEvent = e as CustomEvent
|
||||||
console.log("Received incident_click event in layers:", customEvent.detail)
|
console.log("Received incident_click event in layers:", customEvent.detail)
|
||||||
|
|
||||||
if (!customEvent.detail) {
|
if (!customEvent.detail) {
|
||||||
console.error("Empty incident click event data")
|
console.error("Empty incident click event data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the marker interaction flag to prevent district selection
|
// Set the marker interaction flag to prevent district selection
|
||||||
isInteractingWithMarker.current = true
|
isInteractingWithMarker.current = true
|
||||||
|
|
||||||
const incidentId = customEvent.detail.id || customEvent.detail.incidentId || customEvent.detail.incident_id
|
const incidentId = customEvent.detail.id || customEvent.detail.incidentId || customEvent.detail.incident_id
|
||||||
|
|
||||||
if (!incidentId) {
|
if (!incidentId) {
|
||||||
console.error("No incident ID found in event data:", customEvent.detail)
|
console.error("No incident ID found in event data:", customEvent.detail)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Looking for incident with ID:", incidentId)
|
console.log("Looking for incident with ID:", incidentId)
|
||||||
|
|
||||||
let foundIncident: ICrimeIncident | undefined
|
let foundIncident: ICrimeIncident | undefined
|
||||||
|
|
||||||
if (
|
if (
|
||||||
customEvent.detail.latitude !== undefined &&
|
customEvent.detail.latitude !== undefined &&
|
||||||
customEvent.detail.longitude !== undefined &&
|
customEvent.detail.longitude !== undefined &&
|
||||||
customEvent.detail.category !== undefined
|
customEvent.detail.category !== undefined
|
||||||
) {
|
) {
|
||||||
foundIncident = {
|
foundIncident = {
|
||||||
id: incidentId,
|
id: incidentId,
|
||||||
district: customEvent.detail.district,
|
district: customEvent.detail.district,
|
||||||
category: customEvent.detail.category,
|
category: customEvent.detail.category,
|
||||||
type_category: customEvent.detail.type,
|
type_category: customEvent.detail.type,
|
||||||
description: customEvent.detail.description,
|
description: customEvent.detail.description,
|
||||||
status: customEvent.detail.status || "Unknown",
|
status: customEvent.detail.status || "Unknown",
|
||||||
timestamp: customEvent.detail.timestamp ? new Date(customEvent.detail.timestamp) : undefined,
|
timestamp: customEvent.detail.timestamp ? new Date(customEvent.detail.timestamp) : undefined,
|
||||||
latitude: customEvent.detail.latitude,
|
latitude: customEvent.detail.latitude,
|
||||||
longitude: customEvent.detail.longitude,
|
longitude: customEvent.detail.longitude,
|
||||||
address: customEvent.detail.address,
|
address: customEvent.detail.address,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const crime of crimes) {
|
for (const crime of crimes) {
|
||||||
for (const incident of crime.crime_incidents) {
|
for (const incident of crime.crime_incidents) {
|
||||||
if (incident.id === incidentId || incident.id?.toString() === incidentId?.toString()) {
|
if (incident.id === incidentId || incident.id?.toString() === incidentId?.toString()) {
|
||||||
console.log("Found matching incident:", incident)
|
console.log("Found matching incident:", incident)
|
||||||
foundIncident = {
|
foundIncident = {
|
||||||
id: incident.id,
|
id: incident.id,
|
||||||
district: crime.districts.name,
|
district: crime.districts.name,
|
||||||
description: incident.description,
|
description: incident.description,
|
||||||
status: incident.status || "unknown",
|
status: incident.status || "unknown",
|
||||||
timestamp: incident.timestamp,
|
timestamp: incident.timestamp,
|
||||||
category: incident.crime_categories.name,
|
category: incident.crime_categories.name,
|
||||||
type_category: incident.crime_categories.type,
|
type_category: incident.crime_categories.type,
|
||||||
address: incident.locations.address,
|
address: incident.locations.address,
|
||||||
latitude: incident.locations.latitude,
|
latitude: incident.locations.latitude,
|
||||||
longitude: incident.locations.longitude,
|
longitude: incident.locations.longitude,
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (foundIncident) break
|
if (foundIncident) break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundIncident) {
|
if (!foundIncident) {
|
||||||
console.error("Could not find incident with ID:", incidentId)
|
console.error("Could not find incident with ID:", incidentId)
|
||||||
isInteractingWithMarker.current = false
|
isInteractingWithMarker.current = false
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundIncident.latitude || !foundIncident.longitude) {
|
||||||
|
console.error("Found incident has invalid coordinates:", foundIncident)
|
||||||
|
isInteractingWithMarker.current = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Setting selected incident:", foundIncident)
|
||||||
|
|
||||||
|
// Clear district selection when showing an incident
|
||||||
|
setSelectedDistrict(null)
|
||||||
|
selectedDistrictRef.current = null
|
||||||
|
setFocusedDistrictId(null)
|
||||||
|
|
||||||
|
setSelectedIncident(foundIncident)
|
||||||
|
|
||||||
|
// Reset the marker interaction flag after a delay
|
||||||
|
setTimeout(() => {
|
||||||
|
isInteractingWithMarker.current = false
|
||||||
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundIncident.latitude || !foundIncident.longitude) {
|
|
||||||
console.error("Found incident has invalid coordinates:", foundIncident)
|
|
||||||
isInteractingWithMarker.current = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Setting selected incident:", foundIncident)
|
|
||||||
|
|
||||||
// Clear district selection when showing an incident
|
|
||||||
setSelectedDistrict(null)
|
|
||||||
selectedDistrictRef.current = null
|
|
||||||
setFocusedDistrictId(null)
|
|
||||||
|
|
||||||
setSelectedIncident(foundIncident)
|
|
||||||
|
|
||||||
// Reset the marker interaction flag after a delay
|
|
||||||
setTimeout(() => {
|
|
||||||
isInteractingWithMarker.current = false
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
mapboxMap.getCanvas().addEventListener("incident_click", handleIncidentClickEvent as EventListener)
|
mapboxMap.getCanvas().addEventListener("incident_click", handleIncidentClickEvent as EventListener)
|
||||||
document.addEventListener("incident_click", handleIncidentClickEvent as EventListener)
|
document.addEventListener("incident_click", handleIncidentClickEvent as EventListener)
|
||||||
|
|
||||||
|
@ -450,64 +466,64 @@ export default function Layers({
|
||||||
if (districtCrime) {
|
if (districtCrime) {
|
||||||
const selectedYearNum = year ? Number.parseInt(year) : new Date().getFullYear()
|
const selectedYearNum = year ? Number.parseInt(year) : new Date().getFullYear()
|
||||||
|
|
||||||
let demographics = districtCrime.districts.demographics?.find((d) => d.year === selectedYearNum)
|
let demographics = districtCrime.districts.demographics?.find((d) => d.year === selectedYearNum)
|
||||||
|
|
||||||
if (!demographics && districtCrime.districts.demographics?.length) {
|
if (!demographics && districtCrime.districts.demographics?.length) {
|
||||||
demographics = districtCrime.districts.demographics.sort((a, b) => b.year - a.year)[0]
|
demographics = districtCrime.districts.demographics.sort((a, b) => b.year - a.year)[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
let geographics = districtCrime.districts.geographics?.find((g) => g.year === selectedYearNum)
|
let geographics = districtCrime.districts.geographics?.find((g) => g.year === selectedYearNum)
|
||||||
|
|
||||||
if (!geographics && districtCrime.districts.geographics?.length) {
|
if (!geographics && districtCrime.districts.geographics?.length) {
|
||||||
const validGeographics = districtCrime.districts.geographics
|
const validGeographics = districtCrime.districts.geographics
|
||||||
.filter((g) => g.year !== null)
|
.filter((g) => g.year !== null)
|
||||||
.sort((a, b) => (b.year || 0) - (a.year || 0))
|
.sort((a, b) => (b.year || 0) - (a.year || 0))
|
||||||
|
|
||||||
geographics = validGeographics.length > 0 ? validGeographics[0] : districtCrime.districts.geographics[0]
|
geographics = validGeographics.length > 0 ? validGeographics[0] : districtCrime.districts.geographics[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!demographics || !geographics) {
|
if (!demographics || !geographics) {
|
||||||
console.error("Missing district data:", { demographics, geographics })
|
console.error("Missing district data:", { demographics, geographics })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const crime_incidents = districtCrime.crime_incidents
|
const crime_incidents = districtCrime.crime_incidents
|
||||||
.filter((incident) => filterCategory === "all" || incident.crime_categories.name === filterCategory)
|
.filter((incident) => filterCategory === "all" || incident.crime_categories.name === filterCategory)
|
||||||
.map((incident) => ({
|
.map((incident) => ({
|
||||||
id: incident.id,
|
id: incident.id,
|
||||||
timestamp: incident.timestamp,
|
timestamp: incident.timestamp,
|
||||||
description: incident.description,
|
description: incident.description,
|
||||||
status: incident.status || "",
|
status: incident.status || "",
|
||||||
category: incident.crime_categories.name,
|
category: incident.crime_categories.name,
|
||||||
type: incident.crime_categories.type || "",
|
type: incident.crime_categories.type || "",
|
||||||
address: incident.locations.address || "",
|
address: incident.locations.address || "",
|
||||||
latitude: incident.locations.latitude,
|
latitude: incident.locations.latitude,
|
||||||
longitude: incident.locations.longitude,
|
longitude: incident.locations.longitude,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const updatedDistrict: IDistrictFeature = {
|
const updatedDistrict: IDistrictFeature = {
|
||||||
...selectedDistrictRef.current,
|
...selectedDistrictRef.current,
|
||||||
number_of_crime: crimeDataByDistrict[districtId]?.number_of_crime || 0,
|
number_of_crime: crimeDataByDistrict[districtId]?.number_of_crime || 0,
|
||||||
level: crimeDataByDistrict[districtId]?.level || selectedDistrictRef.current.level,
|
level: crimeDataByDistrict[districtId]?.level || selectedDistrictRef.current.level,
|
||||||
demographics: {
|
demographics: {
|
||||||
number_of_unemployed: demographics.number_of_unemployed,
|
number_of_unemployed: demographics.number_of_unemployed,
|
||||||
population: demographics.population,
|
population: demographics.population,
|
||||||
population_density: demographics.population_density,
|
population_density: demographics.population_density,
|
||||||
year: demographics.year,
|
year: demographics.year,
|
||||||
},
|
},
|
||||||
geographics: {
|
geographics: {
|
||||||
address: geographics.address || "",
|
address: geographics.address || "",
|
||||||
land_area: geographics.land_area || 0,
|
land_area: geographics.land_area || 0,
|
||||||
year: geographics.year || 0,
|
year: geographics.year || 0,
|
||||||
latitude: geographics.latitude,
|
latitude: geographics.latitude,
|
||||||
longitude: geographics.longitude,
|
longitude: geographics.longitude,
|
||||||
},
|
},
|
||||||
crime_incidents,
|
crime_incidents,
|
||||||
selectedYear: year,
|
selectedYear: year,
|
||||||
selectedMonth: month,
|
selectedMonth: month,
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedDistrictRef.current = updatedDistrict
|
selectedDistrictRef.current = updatedDistrict
|
||||||
|
|
||||||
setSelectedDistrict((prevDistrict) => {
|
setSelectedDistrict((prevDistrict) => {
|
||||||
if (
|
if (
|
||||||
|
|
Loading…
Reference in New Issue