290 lines
16 KiB
TypeScript
290 lines
16 KiB
TypeScript
"use client"
|
|
|
|
|
|
import { AlertTriangle, BarChart3, Briefcase, FileText, MapPin, Shield, User, Users, Clock, Search } from "lucide-react"
|
|
import { Badge } from "@/app/_components/ui/badge"
|
|
import { BentoGrid, BentoGridItem } from "@/app/_components/ui/bento-grid"
|
|
import { Progress } from "@/app/_components/ui/progress"
|
|
import CrimeMap from "@/app/_components/map/crime-map"
|
|
|
|
|
|
export default function CrimeManagement() {
|
|
return (
|
|
<div className="container py-4 min-h-screen">
|
|
<div className="max-w-7xl mx-auto">
|
|
<div className="flex items-center justify-between mb-8">
|
|
<div>
|
|
<h2 className="text-3xl font-bold tracking-tight">Crime Management Dashboard</h2>
|
|
<p className="text-muted-foreground">Overview of current cases, incidents, and department status</p>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Badge variant="outline" className="bg-green-100 text-green-800 hover:bg-green-100">
|
|
System: Online
|
|
</Badge>
|
|
<Badge variant="outline" className="bg-blue-100 text-blue-800 hover:bg-blue-100">
|
|
Alert Level: Normal
|
|
</Badge>
|
|
</div>
|
|
</div>
|
|
|
|
<BentoGrid>
|
|
<BentoGridItem
|
|
title="Incident Map"
|
|
description="Recent crime locations in the district"
|
|
icon={<MapPin className="w-5 h-5" />}
|
|
colSpan="2"
|
|
rowSpan="2"
|
|
>
|
|
{/* <div className="mt-4 rounded-md border flex items-center justify-center relative overflow-hidden">
|
|
<div className="absolute inset-0 opacity-50 bg-[url('/placeholder.svg?height=400&width=600')] bg-center bg-cover"></div>
|
|
</div> */}
|
|
<CrimeMap />
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem
|
|
title="Crime Statistics"
|
|
description="Weekly crime rate analysis"
|
|
icon={<BarChart3 className="w-5 h-5" />}
|
|
>
|
|
<div className="space-y-4 mt-4">
|
|
<div>
|
|
<div className="flex justify-between mb-1 text-sm">
|
|
<span>Violent Crime</span>
|
|
<span className="text-red-600">+12%</span>
|
|
</div>
|
|
<Progress value={65} className="h-2 bg-slate-200" indicatorClassName="bg-red-500" />
|
|
</div>
|
|
<div>
|
|
<div className="flex justify-between mb-1 text-sm">
|
|
<span>Property Crime</span>
|
|
<span className="text-green-600">-8%</span>
|
|
</div>
|
|
<Progress value={42} className="h-2 bg-slate-200" indicatorClassName="bg-yellow-500" />
|
|
</div>
|
|
<div>
|
|
<div className="flex justify-between mb-1 text-sm">
|
|
<span>Cybercrime</span>
|
|
<span className="text-red-600">+23%</span>
|
|
</div>
|
|
<Progress value={78} className="h-2 bg-slate-200" indicatorClassName="bg-blue-500" />
|
|
</div>
|
|
</div>
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem
|
|
title="Active Officers"
|
|
description="Personnel currently on duty"
|
|
icon={<Shield className="w-5 h-5" />}
|
|
>
|
|
<div className="flex -space-x-2 mt-4">
|
|
{[1, 2, 3, 4, 5].map((i) => (
|
|
<div
|
|
key={i}
|
|
className="w-10 h-10 rounded-full border-2 border-background bg-slate-200 flex items-center justify-center text-xs font-medium"
|
|
>
|
|
{i}
|
|
</div>
|
|
))}
|
|
<div className="w-10 h-10 rounded-full border-2 border-background bg-primary text-primary-foreground flex items-center justify-center text-xs font-medium">
|
|
+12
|
|
</div>
|
|
</div>
|
|
<div className="mt-4 flex justify-between text-sm">
|
|
<span className="text-muted-foreground">Total on duty:</span>
|
|
<span className="font-medium">18/24 officers</span>
|
|
</div>
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem
|
|
title="High Priority Cases"
|
|
description="Cases requiring immediate attention"
|
|
icon={<AlertTriangle className="w-5 h-5 text-red-500" />}
|
|
colSpan="2"
|
|
>
|
|
<div className="space-y-3 mt-4">
|
|
{[
|
|
{ id: "CR-7823", type: "Homicide", location: "Downtown", priority: "Critical", time: "2h ago" },
|
|
{ id: "CR-7825", type: "Armed Robbery", location: "North District", priority: "High", time: "4h ago" },
|
|
{ id: "CR-7830", type: "Kidnapping", location: "West Side", priority: "Critical", time: "6h ago" },
|
|
].map((case_) => (
|
|
<div key={case_.id} className="flex items-center gap-3 rounded-lg p-3 bg-red-50 border border-red-100">
|
|
<div className="w-10 h-10 rounded-full bg-red-100 flex items-center justify-center shrink-0">
|
|
<AlertTriangle className="h-5 w-5 text-red-600" />
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<div className="flex justify-between">
|
|
<p className="text-sm font-medium">Case #{case_.id}</p>
|
|
<Badge variant="outline" className="bg-red-100 text-red-800 hover:bg-red-100">
|
|
{case_.priority}
|
|
</Badge>
|
|
</div>
|
|
<p className="text-xs text-muted-foreground">
|
|
{case_.type} • {case_.location} • {case_.time}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem
|
|
title="Evidence Tracking"
|
|
description="Recently logged evidence items"
|
|
icon={<Briefcase className="w-5 h-5" />}
|
|
>
|
|
<div className="space-y-2 mt-4">
|
|
{[
|
|
{ id: "EV-4523", type: "Weapon", case: "CR-7823", status: "Processing" },
|
|
{ id: "EV-4525", type: "Digital Media", case: "CR-7825", status: "Secured" },
|
|
{ id: "EV-4527", type: "DNA Sample", case: "CR-7830", status: "Lab Analysis" },
|
|
].map((evidence) => (
|
|
<div key={evidence.id} className="flex items-center gap-2 rounded-lg p-2">
|
|
<div className="w-8 h-8 rounded bg-slate-200 flex items-center justify-center">
|
|
<FileText className="h-4 w-4" />
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium truncate">{evidence.id}</p>
|
|
<p className="text-xs text-muted-foreground">
|
|
{evidence.type} • Case #{evidence.case}
|
|
</p>
|
|
</div>
|
|
<Badge variant="outline" className="text-xs">
|
|
{evidence.status}
|
|
</Badge>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem
|
|
title="Persons of Interest"
|
|
description="Individuals under investigation"
|
|
icon={<User className="w-5 h-5" />}
|
|
>
|
|
<div className="space-y-2 mt-4">
|
|
{[
|
|
{ id: "POI-3421", name: "John Doe", case: "CR-7823", status: "Wanted" },
|
|
{ id: "POI-3422", name: "Jane Smith", case: "CR-7825", status: "In Custody" },
|
|
{ id: "POI-3423", name: "Robert Johnson", case: "CR-7830", status: "Under Surveillance" },
|
|
].map((person) => (
|
|
<div key={person.id} className="flex items-center gap-2 rounded-lg p-2">
|
|
<div className="w-8 h-8 rounded-full bg-slate-200 flex items-center justify-center">
|
|
<User className="h-4 w-4" />
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium truncate">{person.name}</p>
|
|
<p className="text-xs text-muted-foreground">
|
|
{person.id} • Case #{person.case}
|
|
</p>
|
|
</div>
|
|
<Badge
|
|
variant="outline"
|
|
className={
|
|
person.status === "Wanted"
|
|
? "bg-red-100 text-red-800"
|
|
: person.status === "In Custody"
|
|
? "bg-green-100 text-green-800"
|
|
: "bg-yellow-100 text-yellow-800"
|
|
}
|
|
>
|
|
{person.status}
|
|
</Badge>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem
|
|
title="Department Performance"
|
|
description="Case resolution metrics"
|
|
icon={<BarChart3 className="w-5 h-5" />}
|
|
>
|
|
<div className="space-y-4 mt-4">
|
|
<div>
|
|
<div className="flex justify-between mb-1 text-sm">
|
|
<span>Case Clearance Rate</span>
|
|
<span>68%</span>
|
|
</div>
|
|
<Progress value={68} className="h-2" />
|
|
</div>
|
|
<div>
|
|
<div className="flex justify-between mb-1 text-sm">
|
|
<span>Response Time</span>
|
|
<span>4.2 min avg</span>
|
|
</div>
|
|
<Progress value={85} className="h-2" />
|
|
</div>
|
|
<div>
|
|
<div className="flex justify-between mb-1 text-sm">
|
|
<span>Evidence Processing</span>
|
|
<span>72%</span>
|
|
</div>
|
|
<Progress value={72} className="h-2" />
|
|
</div>
|
|
</div>
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem title="Recent Arrests" description="Last 24 hours" icon={<Users className="w-5 h-5" />}>
|
|
<div className="mt-4">
|
|
<div className="flex items-center justify-between">
|
|
<div className="text-2xl font-bold">14</div>
|
|
<div className="text-xs px-2 py-1 rounded-full bg-green-100 text-green-800">+3 from yesterday</div>
|
|
</div>
|
|
<div className="grid grid-cols-3 gap-2 mt-4">
|
|
{["Assault", "Theft", "DUI", "Drugs", "Trespassing", "Vandalism"].map((crime) => (
|
|
<div key={crime} className="px-2 py-1 rounded-md text-xs font-medium text-center">
|
|
{crime}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem title="Emergency Calls" description="911 call volume" icon={<Clock className="w-5 h-5" />}>
|
|
<div className="space-y-2 mt-4">
|
|
<div className="flex justify-between items-center">
|
|
<span className="text-sm">Current Hour</span>
|
|
<div className="flex items-center">
|
|
<span className="text-lg font-bold mr-1">24</span>
|
|
<span className="text-xs px-1.5 py-0.5 rounded-full bg-yellow-100 text-yellow-800">High</span>
|
|
</div>
|
|
</div>
|
|
<div className="flex justify-between items-center">
|
|
<span className="text-sm">Average Wait</span>
|
|
<span className="text-lg font-bold">1:42</span>
|
|
</div>
|
|
<div className="flex justify-between items-center">
|
|
<span className="text-sm">Operators Available</span>
|
|
<div className="flex items-center">
|
|
<span className="text-lg font-bold mr-1">4/6</span>
|
|
<span className="text-xs px-1.5 py-0.5 rounded-full bg-red-100 text-red-800">Understaffed</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</BentoGridItem>
|
|
|
|
<BentoGridItem
|
|
title="Case Search"
|
|
description="Quick access to case files"
|
|
icon={<Search className="w-5 h-5" />}
|
|
>
|
|
<div className="mt-4">
|
|
<div className="relative">
|
|
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
|
<input
|
|
type="search"
|
|
placeholder="Search case number or name..."
|
|
className="w-full rounded-md border border-input bg-background px-9 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
/>
|
|
</div>
|
|
<div className="mt-3 text-xs text-muted-foreground">
|
|
Recent searches: CR-7823, CR-7825, John Doe, Jane Smith
|
|
</div>
|
|
</div>
|
|
</BentoGridItem>
|
|
</BentoGrid>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|