"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, MessageSquare, MapPin, Calendar, Info, ExternalLink } from "lucide-react" import YearSelector from "./year-selector" import MonthSelector from "./month-selector" import CategorySelector from "./category-selector" import ActionSearchBar from "@/app/_components/action-search-bar" import { AnimatePresence, motion } from "framer-motion" import { AlertTriangle, Shield, FileText, Users, Map, BarChart2, Clock, Filter, Search, RefreshCw, Layers, Siren, BadgeAlert, FolderOpen, XCircle, } from "lucide-react" import { ITopTooltipsMapId } from "./map-tooltips" import { IconAnalyze, IconMessage } from "@tabler/icons-react" import { FloatingActionSearchBar } from "../../floating-action-search-bar" import { format } from 'date-fns' import { Card } from "@/app/_components/ui/card" // Sample crime data for suggestions const SAMPLE_CRIME_DATA = [ { id: "CR-12345-2023", description: "Robbery at Main Street" }, { id: "CR-23456-2023", description: "Assault in Central Park" }, { id: "CI-7890-2023", description: "Burglary report at Downtown" }, { id: "CI-4567-2024", description: "Vandalism at City Hall" }, { id: "CR-34567-2024", description: "Car theft on 5th Avenue" }, ]; const ACTIONS = [ { id: "crime_id", label: "Search by Crime ID", icon: , description: "e.g., CR-12345", category: "Search", prefix: "CR-", regex: /^CR-\d+(-\d{4})?$/, placeholder: "CR-12345-2023", }, { id: "incident_id", label: "Search by Incident ID", icon: , description: "e.g., CI-789", category: "Search", prefix: "CI-", regex: /^CI-\d+(-\d{4})?$/, placeholder: "CI-7890-2023", }, { id: "coordinates", label: "Search by Coordinates", icon: , description: "e.g., -6.2, 106.8", category: "Search", prefix: "", regex: /^-?\d+(\.\d+)?,\s*-?\d+(\.\d+)?$/, placeholder: "-6.2, 106.8", }, { id: "description", label: "Search by Description", icon: , description: "e.g., robbery", category: "Search", prefix: "", regex: /.+/, placeholder: "Enter crime description", }, { id: "address", label: "Search by Address", icon: , description: "e.g., Jalan Sudirman", category: "Search", prefix: "", regex: /.+/, placeholder: "Enter location or address", }, ] // Define the primary crime data controls const crimeControls = [ { id: "incidents" as ITopTooltipsMapId, icon: , label: "All Incidents" }, { id: "heatmap" as ITopTooltipsMapId, icon: , label: "Crime Heatmap" }, { id: "trends" as ITopTooltipsMapId, icon: , label: "Crime Trends" }, { id: "patrol" as ITopTooltipsMapId, icon: , label: "Patrol Areas" }, { id: "clusters" as ITopTooltipsMapId, icon: , label: "Clusters" }, { id: "timeline" as ITopTooltipsMapId, icon: , label: "Time Analysis" }, ] // Define the additional tools and features const additionalControls = [ { id: "reports" as ITopTooltipsMapId, icon: , label: "Police Report" }, { id: "layers" as ITopTooltipsMapId, icon: , label: "Map Layers" }, { id: "alerts" as ITopTooltipsMapId, icon: , label: "Active Alerts" }, ] 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 [showSearch, setShowSearch] = useState(false) const containerRef = useRef(null) const searchInputRef = useRef(null) const [selectedSearchType, setSelectedSearchType] = useState(null) const [searchValue, setSearchValue] = useState("") const [suggestions, setSuggestions] = useState>([]) const [isInputValid, setIsInputValid] = useState(true) const [selectedSuggestion, setSelectedSuggestion] = useState<{ id: string; description: string; latitude?: number; longitude?: number; timestamp?: Date; category?: string; type?: string; address?: string; } | null>(null) const [showInfoBox, setShowInfoBox] = useState(false) const [isClient, setIsClient] = useState(false) const container = isClient ? document.getElementById("root") : null useEffect(() => { setIsClient(true) }, []) useEffect(() => { if (showSearch && searchInputRef.current) { setTimeout(() => { searchInputRef.current?.focus(); }, 100); } }, [showSearch]); const handleSearchTypeSelect = (actionId: string) => { const selectedAction = ACTIONS.find(action => action.id === actionId); if (selectedAction) { setSelectedSearchType(actionId); setSearchValue(selectedAction.prefix || ""); setIsInputValid(true); if (selectedAction.prefix) { const initialSuggestions = SAMPLE_CRIME_DATA.filter(item => { if (actionId === 'crime_id' && item.id.startsWith('CR-')) { return true; } else if (actionId === 'incident_id' && item.id.startsWith('CI-')) { return true; } else if (actionId === 'description') { return true; } else if (actionId === 'address') { return true; } return false; }); setSuggestions(initialSuggestions.slice(0, 5)); } } }; const handleClearSearchType = () => { setSelectedSearchType(null); setSearchValue(""); setSuggestions([]); if (searchInputRef.current) { setTimeout(() => { searchInputRef.current?.focus(); }, 50); } }; const handleSuggestionSelect = (item: { id: string, description: string }) => { setSearchValue(item.id); setSuggestions([]); const fullIncidentData = { ...item, timestamp: new Date(), latitude: -6.2088, longitude: 106.8456, category: selectedSearchType === 'crime_id' ? "Theft" : "Vandalism", type: selectedSearchType === 'crime_id' ? "Property Crime" : "Public Disturbance", address: "Jl. Sudirman No. 123, Jakarta" }; setSelectedSuggestion(fullIncidentData); setShowInfoBox(true); }; const handleFlyToIncident = () => { if (!selectedSuggestion || !selectedSuggestion.latitude || !selectedSuggestion.longitude) return; const flyToEvent = new CustomEvent('fly_to_incident', { detail: { longitude: selectedSuggestion.longitude, latitude: selectedSuggestion.latitude, id: selectedSuggestion.id, zoom: 15 }, bubbles: true }); document.dispatchEvent(flyToEvent); toggleSearch(); }; const handleCloseInfoBox = () => { setShowInfoBox(false); setSelectedSuggestion(null); }; const handleSearchChange = (value: string) => { const currentSearchType = selectedSearchType ? ACTIONS.find(action => action.id === selectedSearchType) : null; if (currentSearchType?.prefix && value) { if (!value.startsWith(currentSearchType.prefix)) { value = currentSearchType.prefix; } } setSearchValue(value); if (currentSearchType?.regex) { if (!value || value === currentSearchType.prefix) { setIsInputValid(true); } else { setIsInputValid(currentSearchType.regex.test(value)); } } else { setIsInputValid(true); } if (currentSearchType) { if (!value || value === currentSearchType.prefix) { const initialSuggestions = SAMPLE_CRIME_DATA.filter(item => { if (currentSearchType.id === 'crime_id' && item.id.startsWith('CR-')) { return true; } else if (currentSearchType.id === 'incident_id' && item.id.startsWith('CI-')) { return true; } else if (currentSearchType.id === 'description') { return true; } else if (currentSearchType.id === 'address') { return true; } return false; }); setSuggestions(initialSuggestions.slice(0, 5)); } else { const filteredSuggestions = SAMPLE_CRIME_DATA.filter(item => { if (currentSearchType.id === 'crime_id' && item.id.startsWith('CR-')) { return item.id.toLowerCase().includes(value.toLowerCase()); } else if (currentSearchType.id === 'incident_id' && item.id.startsWith('CI-')) { return item.id.toLowerCase().includes(value.toLowerCase()); } else if (currentSearchType.id === 'description') { return item.description.toLowerCase().includes(value.toLowerCase()); } else if (currentSearchType.id === 'address') { return item.description.toLowerCase().includes(value.toLowerCase()); } return false; }); setSuggestions(filteredSuggestions); } } else { setSuggestions([]); } }; const toggleSelectors = () => { setShowSelectors(!showSelectors) } const toggleSearch = () => { setShowSearch(!showSearch) if (!showSearch && onControlChange) { onControlChange("search" as ITopTooltipsMapId) } } return (
{crimeControls.map((control) => (

{control.label}

))}
{additionalControls.map((control) => (

{control.label}

))}
Year:
Month:
Category:

Search Incidents

{showSelectors && (
)} {showSearch && ( <>

Search Incidents

{!showInfoBox ? ( <> a.id === selectedSearchType)?.placeholder : "Select a search type..."} inputClassName={!isInputValid ? "border-destructive focus-visible:ring-destructive bg-destructive/50" : ""} /> {!isInputValid && selectedSearchType && (
Invalid format. {ACTIONS.find(a => a.id === selectedSearchType)?.description}
)} {suggestions.length > 0 && (
    {suggestions.map((item, index) => (
  • handleSuggestionSelect(item)} > {item.id}
    {item.description}
  • ))}
)} {searchValue.length > 0 && searchValue !== (ACTIONS.find(a => a.id === selectedSearchType)?.prefix || '') && selectedSearchType && suggestions.length === 0 && (

No matching incidents found

)}

{selectedSearchType ? ( <> {ACTIONS.find(a => a.id === selectedSearchType)?.icon} {ACTIONS.find(a => a.id === selectedSearchType)?.description} ) : ( Select a search type and enter your search criteria )}

) : (

{selectedSuggestion?.id}

{selectedSuggestion && (

{selectedSuggestion.description}

{selectedSuggestion.timestamp && (

{format(selectedSuggestion.timestamp, 'PPP p')}

)} {selectedSuggestion.address && (

{selectedSuggestion.address}

)}

Category

{selectedSuggestion.category || 'N/A'}

Type

{selectedSuggestion.type || 'N/A'}

)}
)}
)}
) }