'use client'; import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet'; import L from 'leaflet'; import Link from 'next/link'; import { SensorWithLatestReading } from '@/lib/types'; import { useEffect, useState } from 'react'; // Fix for default marker icon in Next.js delete (L.Icon.Default.prototype as any)._getIconUrl; L.Icon.Default.mergeOptions({ iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png', iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png', }); // Custom marker icon based on water quality function getMarkerIcon(reading: any) { const color = reading ? '#10b981' : '#6b7280'; // Green if has data, gray otherwise return L.divIcon({ className: 'custom-marker', html: `
`, iconSize: [24, 24], iconAnchor: [12, 12], }); } // Component to handle map events function MapEvents({ selectedSensor }: { selectedSensor: SensorWithLatestReading | null }) { const map = useMap(); useEffect(() => { if (selectedSensor) { map.flyTo([selectedSensor.latitude, selectedSensor.longitude], 10, { duration: 1.5 }); } }, [selectedSensor, map]); return null; } interface MapViewProps { sensors: SensorWithLatestReading[]; selectedSensor: SensorWithLatestReading | null; onSelectSensor: (sensor: SensorWithLatestReading | null) => void; } export default function MapView({ sensors, selectedSensor, onSelectSensor }: MapViewProps) { const [isClient, setIsClient] = useState(false); useEffect(() => { setIsClient(true); }, []); if (!isClient) { return (Loading map...
No data available
)} Open Full Dashboard