'use client'; import { useEffect } from 'react'; import { MapContainer, TileLayer, Polyline, CircleMarker, Popup, useMap } from 'react-leaflet'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { LatLngBounds, LatLng } from 'leaflet'; import 'leaflet/dist/leaflet.css'; import { getDetectionModeConfig, DETECTION_TYPES } from '@/constants/detectionModeConfig'; import { DetectionType } from '@/types'; type Detection = { id: number; type: string; class: string; confidence: number; latitude: number; longitude: number; frame_number: number; }; type MapModalProps = { open: boolean; onClose: () => void; detections: Detection[]; detectionType: DetectionType | string; }; // Component to auto-fit map bounds to show all markers function FitBounds({ bounds }: { bounds: LatLngBounds }) { const map = useMap(); useEffect(() => { if (!map || !bounds.isValid()) return; const timer = setTimeout(() => { map.invalidateSize(); map.fitBounds(bounds, { padding: [50, 50], maxZoom: 16, animate: true, }); }, 200); return () => clearTimeout(timer); }, [bounds, map]); return null; } export default function MapModal({ open, onClose, detections, detectionType }: MapModalProps) { const validDetections = detections.filter((d) => d.latitude && d.longitude); if (validDetections.length === 0) { return ( Detection Map
No GPS data available for detections.
); } const routeCoordinates: [number, number][] = validDetections.map((d) => [ d.latitude, d.longitude, ]); const bounds = new LatLngBounds( new LatLng(routeCoordinates[0][0], routeCoordinates[0][1]), new LatLng(routeCoordinates[0][0], routeCoordinates[0][1]), ); routeCoordinates.forEach((coord) => bounds.extend(new LatLng(coord[0], coord[1]))); const center: [number, number] = [ (bounds.getNorth() + bounds.getSouth()) / 2, (bounds.getEast() + bounds.getWest()) / 2, ]; const modeConfig = getDetectionModeConfig(detectionType); return ( {modeConfig.label} Map

{validDetections.length} points of interest identified with GPS data

{validDetections.map((detection, idx) => { const type = (detection.type || '').toLowerCase(); const typeConfig = DETECTION_TYPES[type]; const color = typeConfig ? { fill: typeConfig.color, stroke: typeConfig.color } : { fill: '#64748b', stroke: '#475569' }; return (
{(detection.type || '').replace(/_/g, ' ')} #{detection.id}
Frame {detection.frame_number}
Confidence {(detection.confidence * 100).toFixed(1)}%
Location Details
Latitude {detection.latitude.toFixed(6)}
Longitude {detection.longitude.toFixed(6)}
); })}
); }