220 lines
10 KiB
TypeScript
220 lines
10 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useRef, useState } from "react"
|
|
import { Button } from "@/app/_components/ui/button"
|
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/app/_components/ui/tooltip"
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/app/_components/ui/popover"
|
|
import { ChevronDown } from "lucide-react"
|
|
import YearSelector from "./year-selector"
|
|
import MonthSelector from "./month-selector"
|
|
import CategorySelector from "./category-selector"
|
|
|
|
// Import all the icons we need
|
|
import {
|
|
AlertTriangle,
|
|
Shield,
|
|
FileText,
|
|
Users,
|
|
Map,
|
|
BarChart2,
|
|
Clock,
|
|
Filter,
|
|
Search,
|
|
RefreshCw,
|
|
Layers,
|
|
Siren,
|
|
BadgeAlert,
|
|
FolderOpen,
|
|
} from "lucide-react"
|
|
import { ITopTooltipsMapId } from "./map-tooltips"
|
|
|
|
interface TopControlProps {
|
|
onControlChange?: (controlId: ITopTooltipsMapId) => void
|
|
activeControl?: string
|
|
selectedYear: number
|
|
setSelectedYear: (year: number) => void
|
|
selectedMonth: number | "all"
|
|
setSelectedMonth: (month: number | "all") => void
|
|
selectedCategory: string | "all"
|
|
setSelectedCategory: (category: string | "all") => void
|
|
availableYears?: (number | null)[]
|
|
categories?: string[]
|
|
}
|
|
|
|
export default function TopControl({
|
|
onControlChange,
|
|
activeControl,
|
|
selectedYear,
|
|
setSelectedYear,
|
|
selectedMonth,
|
|
setSelectedMonth,
|
|
selectedCategory,
|
|
setSelectedCategory,
|
|
availableYears = [2022, 2023, 2024],
|
|
categories = [],
|
|
}: TopControlProps) {
|
|
const [showSelectors, setShowSelectors] = useState(false)
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
|
|
const [isClient, setIsClient] = useState(false)
|
|
|
|
const container = isClient ? document.getElementById("root") : null
|
|
|
|
useEffect(() => {
|
|
// This will ensure that the document is only used in the client-side context
|
|
setIsClient(true)
|
|
}, [])
|
|
|
|
// Define the primary crime data controls
|
|
const crimeControls = [
|
|
{ id: "incidents" as ITopTooltipsMapId, icon: <AlertTriangle size={20} />, label: "All Incidents" },
|
|
{ id: "heatmap" as ITopTooltipsMapId, icon: <Map size={20} />, label: "Crime Heatmap" },
|
|
{ id: "trends" as ITopTooltipsMapId, icon: <BarChart2 size={20} />, label: "Crime Trends" },
|
|
{ id: "patrol" as ITopTooltipsMapId, icon: <Shield size={20} />, label: "Patrol Areas" },
|
|
{ id: "clusters" as ITopTooltipsMapId, icon: <Users size={20} />, label: "Clusters" },
|
|
{ id: "timeline" as ITopTooltipsMapId, icon: <Clock size={20} />, label: "Time Analysis" },
|
|
]
|
|
|
|
// Define the additional tools and features
|
|
const additionalControls = [
|
|
{ id: "refresh" as ITopTooltipsMapId, icon: <RefreshCw size={20} />, label: "Refresh Data" },
|
|
{ id: "search" as ITopTooltipsMapId, icon: <Search size={20} />, label: "Search Cases" },
|
|
{ id: "alerts" as ITopTooltipsMapId, icon: <Siren size={20} className="text-red-500" />, label: "Active Alerts" },
|
|
{ id: "layers" as ITopTooltipsMapId, icon: <Layers size={20} />, label: "Map Layers" },
|
|
]
|
|
|
|
const toggleSelectors = () => {
|
|
setShowSelectors(!showSelectors)
|
|
}
|
|
|
|
return (
|
|
<div ref={containerRef} className="flex flex-col items-center gap-2">
|
|
<div className="flex items-center gap-2">
|
|
{/* Main crime controls */}
|
|
<div className="z-10 bg-background rounded-md p-1 flex items-center space-x-1">
|
|
<TooltipProvider>
|
|
{crimeControls.map((control) => (
|
|
<Tooltip key={control.id}>
|
|
<TooltipTrigger asChild>
|
|
<Button
|
|
variant={activeControl === control.id ? "default" : "ghost"}
|
|
size="icon"
|
|
className={`h-8 w-8 rounded-md ${activeControl === control.id
|
|
? "bg-white text-black hover:bg-white/90"
|
|
: "text-white hover:bg-white/10"
|
|
}`}
|
|
onClick={() => onControlChange?.(control.id)}
|
|
>
|
|
{control.icon}
|
|
<span className="sr-only">{control.label}</span>
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="bottom">
|
|
<p>{control.label}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
))}
|
|
</TooltipProvider>
|
|
</div>
|
|
|
|
{/* Additional controls */}
|
|
<div className="z-10 bg-background rounded-md p-1 flex items-center space-x-1">
|
|
<TooltipProvider>
|
|
{additionalControls.map((control) => (
|
|
<Tooltip key={control.id}>
|
|
<TooltipTrigger asChild>
|
|
<Button
|
|
variant={activeControl === control.id ? "default" : "ghost"}
|
|
size="icon"
|
|
className={`h-8 w-8 rounded-md ${activeControl === control.id
|
|
? "bg-white text-black hover:bg-white/90"
|
|
: "text-white hover:bg-white/10"
|
|
}`}
|
|
onClick={() => onControlChange?.(control.id)}
|
|
>
|
|
{control.icon}
|
|
<span className="sr-only">{control.label}</span>
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="bottom">
|
|
<p>{control.label}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
))}
|
|
|
|
{/* Filters button */}
|
|
<Tooltip>
|
|
<Popover open={showSelectors} onOpenChange={setShowSelectors}>
|
|
<PopoverTrigger asChild>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-8 w-8 rounded-md text-white hover:bg-white/10"
|
|
onClick={toggleSelectors}
|
|
>
|
|
<ChevronDown size={20} />
|
|
<span className="sr-only">Filters</span>
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent
|
|
container={containerRef.current || container || undefined}
|
|
className="w-auto p-3 bg-black/90 border-gray-700 text-white"
|
|
align="end"
|
|
style={{ zIndex: 2000 }}>
|
|
<div className="flex flex-col gap-3">
|
|
<div className="flex items-center gap-2">
|
|
<span className="text-xs w-16">Year:</span>
|
|
<YearSelector
|
|
availableYears={availableYears}
|
|
selectedYear={selectedYear}
|
|
onYearChange={setSelectedYear}
|
|
className="w-[180px]"
|
|
/>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<span className="text-xs w-16">Month:</span>
|
|
<MonthSelector
|
|
selectedMonth={selectedMonth}
|
|
onMonthChange={setSelectedMonth}
|
|
className="w-[180px]"
|
|
/>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<span className="text-xs w-16">Category:</span>
|
|
<CategorySelector
|
|
categories={categories}
|
|
selectedCategory={selectedCategory}
|
|
onCategoryChange={setSelectedCategory}
|
|
className="w-[180px]"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</PopoverContent>
|
|
</Popover>
|
|
</Tooltip>
|
|
</TooltipProvider>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Selectors row - visible when expanded */}
|
|
{showSelectors && (
|
|
<div className="z-10 bg-background rounded-md p-2 flex items-center gap-2 md:hidden">
|
|
<YearSelector
|
|
availableYears={availableYears}
|
|
selectedYear={selectedYear}
|
|
onYearChange={setSelectedYear}
|
|
className="w-[100px]"
|
|
/>
|
|
<MonthSelector selectedMonth={selectedMonth} onMonthChange={setSelectedMonth} className="w-[100px]" />
|
|
<CategorySelector
|
|
categories={categories}
|
|
selectedCategory={selectedCategory}
|
|
onCategoryChange={setSelectedCategory}
|
|
className="w-[100px]"
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|