"use client" import { useEffect, useCallback, useRef } from "react" import type { IIncidentLogs } from "@/app/_utils/types/crimes" interface RecentIncidentsLayerProps { visible?: boolean map: any incidents?: IIncidentLogs[] } export default function RecentIncidentsLayer({ visible = false, map, incidents = [] }: RecentIncidentsLayerProps) { const isInteractingWithMarker = useRef(false) // Filter incidents from the last 24 hours const recentIncidents = incidents.filter((incident) => { if (!incident.timestamp) return false const incidentDate = new Date(incident.timestamp) const now = new Date() const timeDiff = now.getTime() - incidentDate.getTime() // 86400000 = 24 hours in milliseconds return timeDiff <= 86400000 }) const handleIncidentClick = useCallback( (e: any) => { if (!map) return const features = map.queryRenderedFeatures(e.point, { layers: ["recent-incidents"] }) if (!features || features.length === 0) return // Stop event propagation e.originalEvent.stopPropagation() e.preventDefault() isInteractingWithMarker.current = true const incident = features[0] if (!incident.properties) return e.originalEvent.stopPropagation() e.preventDefault() const incidentDetails = { id: incident.properties.id, description: incident.properties.description, status: incident.properties?.status || "Active", longitude: (incident.geometry as any).coordinates[0], latitude: (incident.geometry as any).coordinates[1], timestamp: new Date(incident.properties.timestamp || Date.now()), category: incident.properties.category, } // console.log("Recent incident clicked:", incidentDetails) // Ensure markers stay visible if (map.getLayer("recent-incidents")) { map.setLayoutProperty("recent-incidents", "visibility", "visible") } // First fly to the incident location map.flyTo({ center: [incidentDetails.longitude, incidentDetails.latitude], zoom: 15, bearing: 0, pitch: 45, duration: 2000, }) // Dispatch the incident_click event to show the popup const customEvent = new CustomEvent("incident_click", { detail: incidentDetails, bubbles: true, }) map.getCanvas().dispatchEvent(customEvent) document.dispatchEvent(customEvent) // Reset the flag after a delay setTimeout(() => { isInteractingWithMarker.current = false }, 5000) }, [map], ) useEffect(() => { if (!map || !visible) return // console.log(`Setting up recent incidents layer with ${recentIncidents.length} incidents from the last 24 hours`) // Convert incidents to GeoJSON const recentData = { type: "FeatureCollection" as const, features: recentIncidents.map((incident) => ({ type: "Feature" as const, geometry: { type: "Point" as const, coordinates: [incident.longitude, incident.latitude], }, properties: { id: incident.id, user_id: incident.user_id, address: incident.address, description: incident.description, timestamp: incident.timestamp ? incident.timestamp.toString() : new Date().toString(), category: incident.category, district: incident.district, severity: incident.severity, status: incident.verified, source: incident.source, }, })), } const setupLayerAndSource = () => { try { // Check if source exists and update it if (map.getSource("recent-incidents-source")) { ; (map.getSource("recent-incidents-source") as any).setData(recentData) } else { // If not, add source map.addSource("recent-incidents-source", { type: "geojson", data: recentData, }) } // Find first symbol layer for proper layering const layers = map.getStyle().layers let firstSymbolId: string | undefined for (const layer of layers) { if (layer.type === "symbol") { firstSymbolId = layer.id break } } // Check if layer exists already if (!map.getLayer("recent-incidents")) { map.addLayer( { id: "recent-incidents", type: "circle", source: "recent-incidents-source", paint: { "circle-color": "#FF5252", // Red color for recent incidents "circle-radius": [ "interpolate", ["linear"], ["zoom"], 7, 4, // Slightly larger at lower zooms for visibility 12, 8, 15, 12, // Larger maximum size ], "circle-stroke-width": 2, "circle-stroke-color": "#FFFFFF", "circle-opacity": 0.8, // Add a pulsing effect "circle-stroke-opacity": ["interpolate", ["linear"], ["zoom"], 7, 0.5, 15, 0.8], }, layout: { visibility: visible ? "visible" : "none", }, }, firstSymbolId, ) // Add a glow effect with a larger circle behind map.addLayer( { id: "recent-incidents-glow", type: "circle", source: "recent-incidents-source", paint: { "circle-color": "#FF5252", "circle-radius": ["interpolate", ["linear"], ["zoom"], 7, 6, 12, 12, 15, 18], "circle-opacity": 0.2, "circle-blur": 1, }, layout: { visibility: visible ? "visible" : "none", }, }, "recent-incidents", ) // Add mouse events map.on("mouseenter", "recent-incidents", () => { map.getCanvas().style.cursor = "pointer" }) map.on("mouseleave", "recent-incidents", () => { map.getCanvas().style.cursor = "" }) } else { // Update existing layer visibility map.setLayoutProperty("recent-incidents", "visibility", visible ? "visible" : "none") map.setLayoutProperty("recent-incidents-glow", "visibility", visible ? "visible" : "none") } // Ensure click handler is properly registered map.off("click", "recent-incidents", handleIncidentClick) map.on("click", "recent-incidents", handleIncidentClick) } catch (error) { console.error("Error setting up recent incidents layer:", error) } } // Check if style is loaded and set up layer accordingly if (map.isStyleLoaded()) { setupLayerAndSource() } else { map.once("style.load", setupLayerAndSource) // Fallback setTimeout(() => { if (map.isStyleLoaded()) { setupLayerAndSource() } else { console.warn("Map style still not loaded after timeout") } }, 1000) } return () => { if (map) { map.off("click", "recent-incidents", handleIncidentClick) } } }, [map, visible, recentIncidents, handleIncidentClick]) return null }