"use client"; import { Card, CardContent, CardHeader, CardTitle, } from "@/app/_components/ui/card"; import { Skeleton } from "@/app/_components/ui/skeleton"; import MapView from "./map"; import { Button } from "@/app/_components/ui/button"; import { AlertCircle } from "lucide-react"; import { getMonthName } from "@/app/_utils/common"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useFullscreen } from "@/app/_hooks/use-fullscreen"; import { Overlay } from "./overlay"; import MapLegend from "./legends/map-legend"; import UnitsLegend from "./legends/units-legend"; import TimelineLegend from "./legends/timeline-legend"; import { useGetAvailableYears, useGetCrimeCategories, useGetCrimes, useGetCrimeTypes, useGetRecentIncidents, } from "@/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_queries/queries"; import MapSelectors from "./controls/map-selector"; import { cn } from "@/app/_lib/utils"; import { $Enums, crime_categories, crime_incidents, crimes, demographics, districts, geographics, locations, } from "@prisma/client"; import { CrimeTimelapse } from "./controls/bottom/crime-timelapse"; import { ITooltipsControl } from "./controls/top/tooltips"; import CrimeSidebar from "./controls/left/sidebar/map-sidebar"; import Tooltips from "./controls/top/tooltips"; import Layers from "./layers/layers"; import { useGetUnitsQuery } from "@/app/(pages)/(admin)/dashboard/crime-management/units/_queries/queries"; import { IDistrictFeature } from "@/app/_utils/types/map"; import EWSAlertLayer from "./layers/ews-alert-layer"; import { IIncidentLog } from "@/app/_utils/types/ews"; import { addMockIncident, getAllIncidents, resolveIncident, } from "@/app/_utils/mock/ews-data"; import { useMap } from "react-map-gl/mapbox"; import PanicButtonDemo from "./controls/panic-button-demo"; export default function CrimeMap() { const [sidebarCollapsed, setSidebarCollapsed] = useState(true); const [activeControl, setActiveControl] = useState( "clusters", ); const [selectedDistrict, setSelectedDistrict] = useState< IDistrictFeature | null >(null); const [selectedSourceType, setSelectedSourceType] = useState("cbu"); const [selectedYear, setSelectedYear] = useState(2024); const [selectedMonth, setSelectedMonth] = useState("all"); const [selectedCategory, setSelectedCategory] = useState( "all", ); const [ewsIncidents, setEwsIncidents] = useState([]); const [useAllYears, setUseAllYears] = useState(false); const [useAllMonths, setUseAllMonths] = useState(false); const [showAllIncidents, setShowAllIncidents] = useState(false); const [showLegend, setShowLegend] = useState(true); const [showUnitsLayer, setShowUnitsLayer] = useState(false); const [showClusters, setShowClusters] = useState(false); const [showHeatmap, setShowHeatmap] = useState(false); const [showTimelineLayer, setShowTimelineLayer] = useState(false); const [showEWS, setShowEWS] = useState(true); const [showPanicDemo, setShowPanicDemo] = useState(true); const [displayPanicDemo, setDisplayPanicDemo] = useState( showEWS && showPanicDemo, ); const [isTimelapsePlaying, setisTimelapsePlaying] = useState(false); const [yearProgress, setYearProgress] = useState(0); const [isSearchActive, setIsSearchActive] = useState(false); const mapContainerRef = useRef(null); const { current: mapInstance } = useMap(); const mapboxMap = mapInstance?.getMap() || null; const { isFullscreen } = useFullscreen(mapContainerRef); const { data: availableSourceTypes, isLoading: isTypeLoading } = useGetCrimeTypes(); const { data: availableYears, isLoading: isYearsLoading, error: yearsError, } = useGetAvailableYears(); const { data: categoriesData, isLoading: isCategoryLoading } = useGetCrimeCategories(); const categories = useMemo( () => categoriesData ? categoriesData.map((category) => category.name) : [], [categoriesData], ); const { data: crimes, isLoading: isCrimesLoading, error: crimesError, } = useGetCrimes(); const { data: fetchedUnits, isLoading } = useGetUnitsQuery(); const { data: recentIncidents } = useGetRecentIncidents(); useEffect(() => { if ( activeControl === "heatmap" || activeControl === "timeline" || activeControl === "incidents" ) { setSelectedYear("all"); setUseAllYears(true); setUseAllMonths(true); } else { setSelectedYear(2024); setUseAllYears(false); setUseAllMonths(false); } }, [activeControl]); const crimesBySourceType = useMemo(() => { if (!crimes) return []; return crimes.filter((crime) => crime.source_type === selectedSourceType ); }, [crimes, selectedSourceType]); const filteredByYearAndMonth = useMemo(() => { if (!crimesBySourceType) return []; if (useAllYears) { if (useAllMonths) { return crimesBySourceType; } else { return crimesBySourceType.filter((crime) => { return selectedMonth === "all" ? true : crime.month === selectedMonth; }); } } return crimesBySourceType.filter((crime) => { const yearMatch = crime.year === selectedYear; if (selectedMonth === "all" || useAllMonths) { return yearMatch; } else { return yearMatch && crime.month === selectedMonth; } }); }, [ crimesBySourceType, selectedYear, selectedMonth, useAllYears, useAllMonths, ]); const filteredCrimes = useMemo(() => { if (!filteredByYearAndMonth) return []; if (selectedCategory === "all") return filteredByYearAndMonth; return filteredByYearAndMonth.map((crime) => { const filteredIncidents = crime.crime_incidents.filter( (incident) => incident.crime_categories.name === selectedCategory, ); return { ...crime, crime_incidents: filteredIncidents, number_of_crime: filteredIncidents.length, }; }); }, [filteredByYearAndMonth, selectedCategory]); useEffect(() => { if (selectedSourceType === "cbu") { if ( activeControl !== "clusters" && activeControl !== "reports" && activeControl !== "layers" && activeControl !== "search" && activeControl !== "alerts" ) { setActiveControl("clusters"); setShowClusters(true); } } }, [selectedSourceType, activeControl]); useEffect(() => { setEwsIncidents(getAllIncidents()); }, []); const handleTriggerAlert = useCallback( (priority: "high" | "medium" | "low") => { const newIncident = addMockIncident({ priority }); setEwsIncidents(getAllIncidents()); }, [], ); const handleResolveIncident = useCallback((id: string) => { resolveIncident(id); setEwsIncidents(getAllIncidents()); }, []); const handleResolveAllAlerts = useCallback(() => { ewsIncidents.forEach((incident) => { if (incident.status === "active") { resolveIncident(incident.id); } }); setEwsIncidents(getAllIncidents()); }, [ewsIncidents]); const handleSourceTypeChange = useCallback((sourceType: string) => { setSelectedSourceType(sourceType); if (sourceType === "cbu") { setActiveControl("clusters"); setShowClusters(true); } else { setActiveControl("clusters"); setShowClusters(false); } }, []); const handleTimelineChange = useCallback( (year: number, month: number, progress: number) => { setSelectedYear(year); setSelectedMonth(month); setYearProgress(progress); }, [], ); const handleTimelinePlayingChange = useCallback((playing: boolean) => { setisTimelapsePlaying(playing); if (playing) { setSelectedDistrict(null); } }, []); const resetFilters = useCallback(() => { setSelectedYear(2024); setSelectedMonth("all"); setSelectedCategory("all"); }, []); const getMapTitle = () => { if (useAllYears) { return `All Years Data ${ selectedCategory !== "all" ? `- ${selectedCategory}` : "" }`; } let title = `${selectedYear}`; if (selectedMonth !== "all" && !useAllMonths) { title += ` - ${getMonthName(Number(selectedMonth))}`; } if (selectedCategory !== "all") { title += ` - ${selectedCategory}`; } return title; }; const handleControlChange = (controlId: ITooltipsControl) => { if ( selectedSourceType === "cbu" && !["clusters", "reports", "layers", "search", "alerts"].includes( controlId as string, ) ) { return; } setActiveControl(controlId); if (controlId === "clusters") { setShowClusters(true); } else { setShowClusters(false); } if (controlId === "incidents") { setShowAllIncidents(true); } else { setShowAllIncidents(false); } if (controlId === "search") { setIsSearchActive((prev) => !prev); } if (controlId === "units") { setShowUnitsLayer(true); } else { setShowUnitsLayer(false); } if (controlId === "timeline") { setShowTimelineLayer(true); } else { setShowTimelineLayer(false); } if ( controlId === "heatmap" || controlId === "timeline" || controlId === "incidents" ) { setUseAllYears(true); setUseAllMonths(true); } else { setUseAllYears(false); setUseAllMonths(false); } setShowEWS(true); }; // const showTimelineLayer = activeControl === "timeline"; return ( Crime Map {getMapTitle()} {isCrimesLoading ? (
) : crimesError ? (

Failed to load crime data. Please try again later.

) : (
{isFullscreen && ( <>
{mapboxMap && ( )} {displayPanicDemo && (
inc.status === "active" )} />
)}
{showClusters && ( )} {!showClusters && ( )}
{showUnitsLayer && (
)} {showTimelineLayer && (
)} )}
)}
); }