diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/active-officer.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/active-officer.tsx new file mode 100644 index 0000000..2220c2c --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/active-officer.tsx @@ -0,0 +1,24 @@ +export default function ActiveOfficers() { + return ( + <> +
+ {[1, 2, 3, 4, 5].map((i) => ( +
+ {i} +
+ ))} +
+ +12 +
+
+
+ Total on duty: + 18/24 officers +
+ + ) + } + \ No newline at end of file diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/case-search.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/case-search.tsx new file mode 100644 index 0000000..33576e9 --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/case-search.tsx @@ -0,0 +1,19 @@ +import { Search } from "lucide-react" + +export default function CaseSearch() { + const recentSearches = ["CR-7823", "CR-7825", "John Doe", "Jane Smith"] + + return ( +
+
+ + +
+
Recent searches: {recentSearches.join(", ")}
+
+ ) +} diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/crime-stats.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/crime-stats.tsx new file mode 100644 index 0000000..a49b52c --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/crime-stats.tsx @@ -0,0 +1,23 @@ +import { Progress } from "@/app/_components/ui/progress" + +export default function CrimeStatistics() { + const statistics = [ + { name: "Violent Crime", value: 65, change: "+12%", color: "bg-red-500", textColor: "text-red-600" }, + { name: "Property Crime", value: 42, change: "-8%", color: "bg-yellow-500", textColor: "text-green-600" }, + { name: "Cybercrime", value: 78, change: "+23%", color: "bg-blue-500", textColor: "text-red-600" }, + ] + + return ( +
+ {statistics.map((stat) => ( +
+
+ {stat.name} + {stat.change} +
+ +
+ ))} +
+ ) +} diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/dashboard-header.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/dashboard-header.tsx new file mode 100644 index 0000000..b838dfd --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/dashboard-header.tsx @@ -0,0 +1,20 @@ +import { Badge } from "@/app/_components/ui/badge" + +export default function DashboardHeader() { + return ( +
+
+

Crime Management Dashboard

+

Overview of current cases, incidents, and department status

+
+
+ + System: Online + + + Alert Level: Normal + +
+
+ ) +} diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/departement-performance.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/departement-performance.tsx new file mode 100644 index 0000000..2b44abd --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/departement-performance.tsx @@ -0,0 +1,23 @@ +import { Progress } from "@/app/_components/ui/progress" + +export default function DepartmentPerformance() { + const metrics = [ + { name: "Case Clearance Rate", value: 68, display: "68%" }, + { name: "Response Time", value: 85, display: "4.2 min avg" }, + { name: "Evidence Processing", value: 72, display: "72%" }, + ] + + return ( +
+ {metrics.map((metric) => ( +
+
+ {metric.name} + {metric.display} +
+ +
+ ))} +
+ ) +} diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/emergency-call.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/emergency-call.tsx new file mode 100644 index 0000000..9785445 --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/emergency-call.tsx @@ -0,0 +1,37 @@ +export default function EmergencyCalls() { + const callMetrics = [ + { + label: "Current Hour", + value: "24", + badge: { text: "High", className: "bg-yellow-100 text-yellow-800" }, + }, + { + label: "Average Wait", + value: "1:42", + }, + { + label: "Operators Available", + value: "4/6", + badge: { text: "Understaffed", className: "bg-red-100 text-red-800" }, + }, + ] + + return ( +
+ {callMetrics.map((metric) => ( +
+ {metric.label} +
+ {metric.value} + {metric.badge && ( + + {metric.badge.text} + + )} +
+
+ ))} +
+ ) + } + \ No newline at end of file diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/evidence-tracking.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/evidence-tracking.tsx new file mode 100644 index 0000000..7b174db --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/evidence-tracking.tsx @@ -0,0 +1,31 @@ +import { FileText } from "lucide-react" +import { Badge } from "@/app/_components/ui/badge" + +export default function EvidenceTracking() { + const evidenceItems = [ + { 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" }, + ] + + return ( +
+ {evidenceItems.map((evidence) => ( +
+
+ +
+
+

{evidence.id}

+

+ {evidence.type} • Case #{evidence.case} +

+
+ + {evidence.status} + +
+ ))} +
+ ) +} diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/high-priority-case.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/high-priority-case.tsx new file mode 100644 index 0000000..64b1ced --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/high-priority-case.tsx @@ -0,0 +1,34 @@ +import { AlertTriangle } from "lucide-react" +import { Badge } from "@/app/_components/ui/badge" + +export default function HighPriorityCases() { + const cases = [ + { 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" }, + { id: "CR-7832", type: "Assault", location: "East District", priority: "Medium", time: "8h ago" }, + ] + + return ( +
+ {cases.map((case_) => ( +
+
+ +
+
+
+

Case #{case_.id}

+ + {case_.priority} + +
+

+ {case_.type} • {case_.location} • {case_.time} +

+
+
+ ))} +
+ ) +} diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/person-interest.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/person-interest.tsx new file mode 100644 index 0000000..7c606f0 --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/person-interest.tsx @@ -0,0 +1,42 @@ +import { User } from "lucide-react" +import { Badge } from "@/app/_components/ui/badge" + +export default function PersonsOfInterest() { + const persons = [ + { 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" }, + ] + + const getStatusClass = (status: string) => { + switch (status) { + case "Wanted": + return "bg-red-100 text-red-800" + case "In Custody": + return "bg-green-100 text-green-800" + default: + return "bg-yellow-100 text-yellow-800" + } + } + + return ( +
+ {persons.map((person) => ( +
+
+ +
+
+

{person.name}

+

+ {person.id} • Case #{person.case} +

+
+ + {person.status} + +
+ ))} +
+ ) +} diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/recent-arrest.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/recent-arrest.tsx new file mode 100644 index 0000000..f8b9898 --- /dev/null +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/_components/recent-arrest.tsx @@ -0,0 +1,20 @@ +export default function RecentArrests() { + const crimeTypes = ["Assault", "Theft", "DUI", "Drugs", "Trespassing", "Vandalism"] + + return ( +
+
+
14
+
+3 from yesterday
+
+
+ {crimeTypes.map((crime) => ( +
+ {crime} +
+ ))} +
+
+ ) + } + \ No newline at end of file diff --git a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/page.tsx b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/page.tsx index 9978f09..228034f 100644 --- a/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/page.tsx +++ b/sigap-website/app/(pages)/(admin)/dashboard/crime-management/crime-overview/page.tsx @@ -1,289 +1,110 @@ "use client" +import { AlertTriangle, BarChart3, Briefcase, Clock, MapPin, Search, Shield, User, Users } from "lucide-react" +import { BentoGrid, BentoGridItem, BentoGridItemProps, GridSpan } from "@/app/_components/ui/bento-grid" -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" +import YearSelector from "@/app/_components/map/controls/year-selector" +import DashboardHeader from "./_components/dashboard-header" +import CrimeStatistics from "./_components/crime-stats" +import ActiveOfficers from "./_components/active-officer" +import HighPriorityCases from "./_components/high-priority-case" +import EvidenceTracking from "./_components/evidence-tracking" +import PersonsOfInterest from "./_components/person-interest" +import DepartmentPerformance from "./_components/departement-performance" +import RecentArrests from "./_components/recent-arrest" +import EmergencyCalls from "./_components/emergency-call" +import CaseSearch from "./_components/case-search" +const bentoGridItems: BentoGridItemProps[] = [ + { + title: "Incident Map", + description: "Recent crime locations in the district", + icon: , + colSpan: "2", + rowSpan: "2", + suffixMenu: { }} />, + component: , + }, + { + title: "Crime Statistics", + description: "Weekly crime rate analysis", + icon: , + component: , + }, + { + title: "Active Officers", + description: "Personnel currently on duty", + icon: , + component: , + }, + { + title: "High Priority Cases", + description: "Cases requiring immediate attention", + icon: , + colSpan: "2", + component: , + }, + { + title: "Evidence Tracking", + description: "Recently logged evidence items", + icon: , + component: , + }, + { + title: "Persons of Interest", + description: "Individuals under investigation", + icon: , + component: , + }, + { + title: "Department Performance", + description: "Case resolution metrics", + icon: , + component: , + }, + { + title: "Recent Arrests", + description: "Last 24 hours", + icon: , + component: , + }, + { + title: "Emergency Calls", + description: "911 call volume", + icon: , + component: , + }, + { + title: "Case Search", + description: "Quick access to case files", + icon: , + component: , + }, +]; export default function CrimeManagement() { return (
-
-
-

Crime Management Dashboard

-

Overview of current cases, incidents, and department status

-
-
- - System: Online - - - Alert Level: Normal - -
-
+ - } - colSpan="2" - rowSpan="2" - > - {/*
-
-
*/} - -
- - } - > -
-
-
- Violent Crime - +12% -
- -
-
-
- Property Crime - -8% -
- -
-
-
- Cybercrime - +23% -
- -
-
-
- - } - > -
- {[1, 2, 3, 4, 5].map((i) => ( -
- {i} -
- ))} -
- +12 -
-
-
- Total on duty: - 18/24 officers -
-
- - } - colSpan="2" - > -
- {[ - { 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_) => ( -
-
- -
-
-
-

Case #{case_.id}

- - {case_.priority} - -
-

- {case_.type} • {case_.location} • {case_.time} -

-
-
- ))} -
-
- - } - > -
- {[ - { 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) => ( -
-
- -
-
-

{evidence.id}

-

- {evidence.type} • Case #{evidence.case} -

-
- - {evidence.status} - -
- ))} -
-
- - } - > -
- {[ - { 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) => ( -
-
- -
-
-

{person.name}

-

- {person.id} • Case #{person.case} -

-
- - {person.status} - -
- ))} -
-
- - } - > -
-
-
- Case Clearance Rate - 68% -
- -
-
-
- Response Time - 4.2 min avg -
- -
-
-
- Evidence Processing - 72% -
- -
-
-
- - }> -
-
-
14
-
+3 from yesterday
-
-
- {["Assault", "Theft", "DUI", "Drugs", "Trespassing", "Vandalism"].map((crime) => ( -
- {crime} -
- ))} -
-
-
- - }> -
-
- Current Hour -
- 24 - High -
-
-
- Average Wait - 1:42 -
-
- Operators Available -
- 4/6 - Understaffed -
-
-
-
- - } - > -
-
- - -
-
- Recent searches: CR-7823, CR-7825, John Doe, Jane Smith -
-
-
+ {bentoGridItems.map((item, index) => ( + + {item.component} + + ))}
- ) + ); } diff --git a/sigap-website/app/_components/ui/bento-grid.tsx b/sigap-website/app/_components/ui/bento-grid.tsx index 4870102..8d4a8fc 100644 --- a/sigap-website/app/_components/ui/bento-grid.tsx +++ b/sigap-website/app/_components/ui/bento-grid.tsx @@ -2,6 +2,8 @@ import { cn } from "@/app/_lib/utils" import type React from "react" import type { HTMLAttributes } from "react" +// Define specific types for colSpan and rowSpan +export type GridSpan = "1" | "2" | "3" interface BentoGridProps extends HTMLAttributes { className?: string @@ -16,15 +18,17 @@ export function BentoGrid({ className, children, ...props }: BentoGridProps) { ) } -interface BentoGridItemProps extends HTMLAttributes { +export interface BentoGridItemProps extends HTMLAttributes { className?: string title?: string description?: string header?: React.ReactNode icon?: React.ReactNode children?: React.ReactNode - colSpan?: "1" | "2" | "3" - rowSpan?: "1" | "2" | "3" + colSpan?: GridSpan + rowSpan?: GridSpan + suffixMenu?: React.ReactNode + component?: React.ReactNode } export function BentoGridItem({ @@ -36,6 +40,7 @@ export function BentoGridItem({ children, colSpan = "1", rowSpan = "1", + suffixMenu, ...props }: BentoGridItemProps) { return ( @@ -51,16 +56,19 @@ export function BentoGridItem({ {...props} > {header &&
{header}
} -
- {icon && ( -
{icon}
- )} - {(title || description) && ( -
- {title &&

{title}

} - {description &&

{description}

} -
- )} +
+
+ {icon && ( +
{icon}
+ )} + {(title || description) && ( +
+ {title &&

{title}

} + {description &&

{description}

} +
+ )} +
+ {suffixMenu &&
{suffixMenu}
}
{children &&
{children}
}
diff --git a/sigap-website/app/_utils/types/map.ts b/sigap-website/app/_utils/types/map.ts index 3f494f7..e51724b 100644 --- a/sigap-website/app/_utils/types/map.ts +++ b/sigap-website/app/_utils/types/map.ts @@ -1,4 +1,4 @@ -import { IDistrictGeoData } from "./crime-management"; +import { IDistrictGeoData } from "./district"; export interface IGeoJSONPolygon { type: 'Polygon' | 'MultiPolygon';