'use client';
import { MapContainer, TileLayer, Marker, Popup, Tooltip, useMapEvents } from "react-leaflet";
import Link from "next/link";
import type { SensorResponse } from "@/lib/types";
import L from 'leaflet';
// Fix Leaflet default icon path broken by webpack
if (typeof window !== 'undefined') {
delete (L.Icon.Default.prototype as any)._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon-2x.png',
iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon.png',
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png',
});
}
const createNeonIcon = () => {
return new L.DivIcon({
className: "bg-transparent",
html: `
`,
iconSize: [24, 24],
iconAnchor: [12, 12],
popupAnchor: [0, -12],
});
};
const createPendingIcon = () => {
return new L.DivIcon({
className: "bg-transparent",
html: `
`,
iconSize: [32, 32],
iconAnchor: [16, 16],
popupAnchor: [0, -16],
});
};
interface ClickHandlerProps {
onMapClick?: (lat: number, lng: number) => void;
}
function MapClickHandler({ onMapClick }: ClickHandlerProps) {
useMapEvents({
click(e) {
if (onMapClick) {
onMapClick(e.latlng.lat, e.latlng.lng);
}
},
});
return null;
}
interface GlobalMapProps {
sensors: SensorResponse[];
onMapClick?: (lat: number, lng: number) => void;
pendingLatLng?: { lat: number; lng: number } | null;
}
export function GlobalMap({ sensors, onMapClick, pendingLatLng }: GlobalMapProps) {
const neonIcon = createNeonIcon();
const pendingIcon = createPendingIcon();
return (
{sensors?.map((sensor) => (
{sensor.locationName || sensor.sensorId}
{sensor.locationName || "Unknown Sector"}
NODE ID: {sensor.sensorId}
LAT: {sensor.latitude} | LNG: {sensor.longitude}
Access Telemetry
))}
{/* Pending marker from map click */}
{pendingLatLng && (
DEPLOY HERE
)}
);
}