"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 { useRef, useState, useCallback, useMemo, useEffect } 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 { ITooltips } from "./controls/top/tooltips" import CrimeSidebar from "./controls/left/sidebar/map-sidebar" import Tooltips from "./controls/top/tooltips" import Layers from "./layers/layers" import DistrictLayer, { DistrictFeature } from "./layers/district-layer-old" import { useGetUnitsQuery } from "@/app/(pages)/(admin)/dashboard/crime-management/units/_queries/queries" export default function CrimeMap() { const [sidebarCollapsed, setSidebarCollapsed] = useState(true) const [selectedDistrict, setSelectedDistrict] = useState(null) const [showLegend, setShowLegend] = useState(true) const [activeControl, setActiveControl] = useState("clusters") const [selectedSourceType, setSelectedSourceType] = useState("cbu") const [selectedYear, setSelectedYear] = useState(2024) const [selectedMonth, setSelectedMonth] = useState("all") const [selectedCategory, setSelectedCategory] = useState("all") const [yearProgress, setYearProgress] = useState(0) const [isTimelapsePlaying, setisTimelapsePlaying] = useState(false) const [isSearchActive, setIsSearchActive] = useState(false) const [showUnitsLayer, setShowUnitsLayer] = useState(false) const [showClusters, setShowClusters] = useState(false) const [showHeatmap, setShowHeatmap] = useState(false) const [showUnclustered, setShowUnclustered] = useState(true) const [useAllYears, setUseAllYears] = useState(false) const [useAllMonths, setUseAllMonths] = useState(false) const [showEWS, setShowEWS] = useState(true) const mapContainerRef = useRef(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") { setUseAllYears(true); setUseAllMonths(true); } else { 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); setShowUnclustered(false); } } }, [selectedSourceType, activeControl]); const handleSourceTypeChange = useCallback((sourceType: string) => { setSelectedSourceType(sourceType); if (sourceType === "cbu") { setActiveControl("clusters"); setShowClusters(true); setShowUnclustered(false); } else { setActiveControl("clusters"); setShowUnclustered(true); 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: ITooltips) => { 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") { setShowUnclustered(true) } else { setShowUnclustered(false) } if (controlId === "search") { setIsSearchActive(prev => !prev); } if (controlId === "units") { setShowUnitsLayer(true); } else if (showUnitsLayer) { setShowUnitsLayer(false); } if (controlId === "heatmap" || controlId === "timeline") { 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 && ( <>
{isFullscreen && (
{showClusters && ( )} {showUnclustered && !showClusters && ( )}
)} {isFullscreen && showUnitsLayer && (
)} {isFullscreen && showTimelineLayer && (
)} )} {isFullscreen && (
)}
)}
) }