MIF_E31221222/sigap-website/app/_components/map/crime-map.tsx

123 lines
4.9 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "@/app/_components/ui/card"
import { Skeleton } from "@/app/_components/ui/skeleton"
import DistrictLayer, { type DistrictFeature } from "./layers/district-layer"
import MapLegend from "./controls/map-legend"
import YearSelector from "./controls/year-selector"
import CrimeMarker, { type CrimeIncident } from "./markers/crime-marker"
import { useToast } from "@/app/_hooks/use-toast"
import MapView from "./map"
import { useQuery } from "@tanstack/react-query"
import { getAvailableYears } from "@/app/(pages)/(admin)/dashboard/crime-management/crime-overview/action"
const years = [2020, 2021, 2022, 2023, 2024, 2025]
export default function CrimeMap() {
const [loading, setLoading] = useState(false)
const [year, setYear] = useState<string>(new Date().getFullYear().toString())
const [availableYears, setAvailableYears] = useState<number[]>(years)
const [districtData, setDistrictData] = useState<DistrictFeature[]>([])
const [crimeIncidents, setCrimeIncidents] = useState<CrimeIncident[]>([])
const [showIncidents, setShowIncidents] = useState(false)
const { toast } = useToast()
// fetch available years (example function)
// const { data: year } = useQuery({
// queryKey: ["available-years"],
// queryFn: getAvailableYears,
// })
// Fetch crime incidents (example function)
const fetchCrimeIncidents = async (districtId: string) => {
try {
// This would be replaced with an actual API call
// const response = await fetch(`/api/crime-incidents?districtId=${districtId}&year=${year}`)
// const data = await response.json()
// For demonstration, we'll create some sample data
const sampleIncidents: CrimeIncident[] = [
{
id: "1",
latitude: -8.1842 + (Math.random() - 0.5) * 0.1,
longitude: 113.7031 + (Math.random() - 0.5) * 0.1,
description: "Theft incident",
date: "2023-05-15",
category: "Theft",
},
{
id: "2",
latitude: -8.1842 + (Math.random() - 0.5) * 0.1,
longitude: 113.7031 + (Math.random() - 0.5) * 0.1,
description: "Vandalism",
date: "2023-06-22",
category: "Property Crime",
},
{
id: "3",
latitude: -8.1842 + (Math.random() - 0.5) * 0.1,
longitude: 113.7031 + (Math.random() - 0.5) * 0.1,
description: "Assault",
date: "2023-07-10",
category: "Violent Crime",
},
]
setCrimeIncidents(sampleIncidents)
setShowIncidents(true)
} catch (error) {
console.error("Error fetching crime incidents:", error)
}
}
const handleDistrictClick = (feature: any) => {
const districtId = feature.properties.id
const districtName = feature.properties.name
toast({
title: `Selected: ${districtName}`,
description: "Loading crime incidents for this district...",
})
fetchCrimeIncidents(districtId)
}
const handleIncidentClick = (incident: CrimeIncident) => {
toast({
title: "Crime Incident",
description: `${incident.description} on ${incident.date}`,
})
}
return (
<Card className="w-full">
{/* <CardHeader className="flex flex-row items-center justify-between">
<CardTitle>Crime Rate Map - Jember Regency</CardTitle>
<YearSelector years={availableYears} selectedYear={year} onChange={setYear} />
</CardHeader> */}
<CardContent className="p-0">
{loading ? (
<Skeleton className="w-full rounded-md" />
) : (
<div className="relative">
<MapView mapStyle="mapbox://styles/mapbox/dark-v11">
{/* District Layer */}
<DistrictLayer data={districtData} onClick={handleDistrictClick} />
{/* Crime Incident Markers */}
{showIncidents &&
crimeIncidents.map((incident) => (
<CrimeMarker key={incident.id} incident={incident} onClick={handleIncidentClick} />
))}
{/* Map Legend */}
{/* <MapLegend position="bottom-right" /> */}
</MapView>
</div>
)}
</CardContent>
</Card>
)
}