refactor: ♻️ refactor crime management into small components

This commit is contained in:
vergiLgood1 2025-04-15 00:31:39 +07:00
parent c6f803b08c
commit 2bf335d59b
13 changed files with 389 additions and 287 deletions

View File

@ -0,0 +1,24 @@
export default function ActiveOfficers() {
return (
<>
<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>
</>
)
}

View File

@ -0,0 +1,19 @@
import { Search } from "lucide-react"
export default function CaseSearch() {
const recentSearches = ["CR-7823", "CR-7825", "John Doe", "Jane Smith"]
return (
<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: {recentSearches.join(", ")}</div>
</div>
)
}

View File

@ -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 (
<div className="space-y-4 mt-4">
{statistics.map((stat) => (
<div key={stat.name}>
<div className="flex justify-between mb-1 text-sm">
<span>{stat.name}</span>
<span className={stat.textColor}>{stat.change}</span>
</div>
<Progress value={stat.value} className="h-2 bg-slate-200" indicatorClassName={stat.color} />
</div>
))}
</div>
)
}

View File

@ -0,0 +1,20 @@
import { Badge } from "@/app/_components/ui/badge"
export default function DashboardHeader() {
return (
<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>
)
}

View File

@ -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 (
<div className="space-y-4 mt-4">
{metrics.map((metric) => (
<div key={metric.name}>
<div className="flex justify-between mb-1 text-sm">
<span>{metric.name}</span>
<span>{metric.display}</span>
</div>
<Progress value={metric.value} className="h-2" />
</div>
))}
</div>
)
}

View File

@ -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 (
<div className="space-y-2 mt-4">
{callMetrics.map((metric) => (
<div key={metric.label} className="flex justify-between items-center">
<span className="text-sm">{metric.label}</span>
<div className="flex items-center">
<span className="text-lg font-bold mr-1">{metric.value}</span>
{metric.badge && (
<span className={`text-xs px-1.5 py-0.5 rounded-full ${metric.badge.className}`}>
{metric.badge.text}
</span>
)}
</div>
</div>
))}
</div>
)
}

View File

@ -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 (
<div className="space-y-2 mt-4">
{evidenceItems.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>
)
}

View File

@ -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 (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
{cases.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>
)
}

View File

@ -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 (
<div className="space-y-2 mt-4">
{persons.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={getStatusClass(person.status)}>
{person.status}
</Badge>
</div>
))}
</div>
)
}

View File

@ -0,0 +1,20 @@
export default function RecentArrests() {
const crimeTypes = ["Assault", "Theft", "DUI", "Drugs", "Trespassing", "Vandalism"]
return (
<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">
{crimeTypes.map((crime) => (
<div key={crime} className="px-2 py-1 rounded-md text-xs font-medium text-center">
{crime}
</div>
))}
</div>
</div>
)
}

View File

@ -1,289 +1,110 @@
"use client" "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 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: <MapPin className="w-5 h-5" />,
colSpan: "2",
rowSpan: "2",
suffixMenu: <YearSelector years={[2020, 2021, 2022, 2023, 2024]} selectedYear="" onChange={() => { }} />,
component: <CrimeMap />,
},
{
title: "Crime Statistics",
description: "Weekly crime rate analysis",
icon: <BarChart3 className="w-5 h-5" />,
component: <CrimeStatistics />,
},
{
title: "Active Officers",
description: "Personnel currently on duty",
icon: <Shield className="w-5 h-5" />,
component: <ActiveOfficers />,
},
{
title: "High Priority Cases",
description: "Cases requiring immediate attention",
icon: <AlertTriangle className="w-5 h-5 text-red-500" />,
colSpan: "2",
component: <HighPriorityCases />,
},
{
title: "Evidence Tracking",
description: "Recently logged evidence items",
icon: <Briefcase className="w-5 h-5" />,
component: <EvidenceTracking />,
},
{
title: "Persons of Interest",
description: "Individuals under investigation",
icon: <User className="w-5 h-5" />,
component: <PersonsOfInterest />,
},
{
title: "Department Performance",
description: "Case resolution metrics",
icon: <BarChart3 className="w-5 h-5" />,
component: <DepartmentPerformance />,
},
{
title: "Recent Arrests",
description: "Last 24 hours",
icon: <Users className="w-5 h-5" />,
component: <RecentArrests />,
},
{
title: "Emergency Calls",
description: "911 call volume",
icon: <Clock className="w-5 h-5" />,
component: <EmergencyCalls />,
},
{
title: "Case Search",
description: "Quick access to case files",
icon: <Search className="w-5 h-5" />,
component: <CaseSearch />,
},
];
export default function CrimeManagement() { export default function CrimeManagement() {
return ( return (
<div className="container py-4 min-h-screen"> <div className="container py-4 min-h-screen">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="flex items-center justify-between mb-8"> <DashboardHeader />
<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> <BentoGrid>
<BentoGridItem {bentoGridItems.map((item, index) => (
title="Incident Map" <BentoGridItem
description="Recent crime locations in the district" key={index}
icon={<MapPin className="w-5 h-5" />} title={item.title}
colSpan="2" description={item.description}
rowSpan="2" icon={item.icon}
> colSpan={item.colSpan}
{/* <div className="mt-4 rounded-md border flex items-center justify-center relative overflow-hidden"> rowSpan={item.rowSpan}
<div className="absolute inset-0 opacity-50 bg-[url('/placeholder.svg?height=400&width=600')] bg-center bg-cover"></div> suffixMenu={item.suffixMenu}
</div> */} >
<CrimeMap /> {item.component}
</BentoGridItem> </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> </BentoGrid>
</div> </div>
</div> </div>
) );
} }

View File

@ -2,6 +2,8 @@ import { cn } from "@/app/_lib/utils"
import type React from "react" import type React from "react"
import type { HTMLAttributes } from "react" import type { HTMLAttributes } from "react"
// Define specific types for colSpan and rowSpan
export type GridSpan = "1" | "2" | "3"
interface BentoGridProps extends HTMLAttributes<HTMLDivElement> { interface BentoGridProps extends HTMLAttributes<HTMLDivElement> {
className?: string className?: string
@ -16,15 +18,17 @@ export function BentoGrid({ className, children, ...props }: BentoGridProps) {
) )
} }
interface BentoGridItemProps extends HTMLAttributes<HTMLDivElement> { export interface BentoGridItemProps extends HTMLAttributes<HTMLDivElement> {
className?: string className?: string
title?: string title?: string
description?: string description?: string
header?: React.ReactNode header?: React.ReactNode
icon?: React.ReactNode icon?: React.ReactNode
children?: React.ReactNode children?: React.ReactNode
colSpan?: "1" | "2" | "3" colSpan?: GridSpan
rowSpan?: "1" | "2" | "3" rowSpan?: GridSpan
suffixMenu?: React.ReactNode
component?: React.ReactNode
} }
export function BentoGridItem({ export function BentoGridItem({
@ -36,6 +40,7 @@ export function BentoGridItem({
children, children,
colSpan = "1", colSpan = "1",
rowSpan = "1", rowSpan = "1",
suffixMenu,
...props ...props
}: BentoGridItemProps) { }: BentoGridItemProps) {
return ( return (
@ -51,16 +56,19 @@ export function BentoGridItem({
{...props} {...props}
> >
{header && <div className="mb-4">{header}</div>} {header && <div className="mb-4">{header}</div>}
<div className="flex items-center gap-3 mb-4"> <div className="flex items-center justify-between gap-3 mb-4">
{icon && ( <div className="flex items-center gap-3">
<div className="p-2 w-10 h-10 shrink-0 rounded-full flex items-center justify-center bg-muted">{icon}</div> {icon && (
)} <div className="p-2 w-10 h-10 shrink-0 rounded-full flex items-center justify-center bg-muted">{icon}</div>
{(title || description) && ( )}
<div className="space-y-1"> {(title || description) && (
{title && <h3 className="font-semibold tracking-tight">{title}</h3>} <div className="space-y-1">
{description && <p className="text-sm text-muted-foreground">{description}</p>} {title && <h3 className="font-semibold tracking-tight">{title}</h3>}
</div> {description && <p className="text-sm text-muted-foreground">{description}</p>}
)} </div>
)}
</div>
{suffixMenu && <div>{suffixMenu}</div>}
</div> </div>
{children && <div>{children}</div>} {children && <div>{children}</div>}
</div> </div>

View File

@ -1,4 +1,4 @@
import { IDistrictGeoData } from "./crime-management"; import { IDistrictGeoData } from "./district";
export interface IGeoJSONPolygon { export interface IGeoJSONPolygon {
type: 'Polygon' | 'MultiPolygon'; type: 'Polygon' | 'MultiPolygon';