64 lines
2.3 KiB
TypeScript
64 lines
2.3 KiB
TypeScript
// In file: src/app/_components/DynamicDeviceMap.tsx
|
|
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
import { MapContainer, TileLayer, Marker, Polyline, useMap, useMapEvents } from "react-leaflet";
|
|
import L from "leaflet";
|
|
import "leaflet/dist/leaflet.css";
|
|
|
|
// Fix default Leaflet icon paths
|
|
delete (L.Icon.Default as any)._getIconUrl;
|
|
L.Icon.Default.mergeOptions({
|
|
iconRetinaUrl: '/leaflet/marker-icon-2x.png',
|
|
iconUrl: '/leaflet/marker-icon.png',
|
|
shadowUrl: '/leaflet/marker-shadow.png',
|
|
});
|
|
|
|
// Helper component that forces the map to update its view
|
|
function MapViewUpdater({ center }: { center: L.LatLngExpression }) {
|
|
const map = useMap();
|
|
useEffect(() => {
|
|
// When the 'center' prop changes, fly the map to the new location
|
|
map.flyTo(center, map.getZoom());
|
|
}, [center, map]);
|
|
return null;
|
|
}
|
|
|
|
interface FenceMapProps {
|
|
latestGPS?: { lat: number; lng: number };
|
|
onFenceChange: (fence: Array<{ lat: number; lng: number }>) => void;
|
|
}
|
|
|
|
const FenceMap = ({ latestGPS, onFenceChange }: FenceMapProps) => {
|
|
const [fence, setFence] = useState<Array<{ lat: number; lng: number }>>([]);
|
|
useMapEvents({
|
|
click: (e) => {
|
|
const newFence = [...fence, { lat: e.latlng.lat, lng: e.latlng.lng }];
|
|
setFence(newFence);
|
|
onFenceChange(newFence);
|
|
},
|
|
});
|
|
return (
|
|
<>
|
|
{fence.length > 1 && <Polyline pathOptions={{ color: "red" }} positions={fence} />}
|
|
{latestGPS && <Marker position={[latestGPS.lat, latestGPS.lng]} />}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export const DeviceMap = ({ latestGPS, onFenceChange }: { latestGPS?: { lat: number; lng: number } | null; onFenceChange: (fence: Array<{ lat: number; lng: number }>) => void; }) => {
|
|
// Use live GPS if available, otherwise default to a reasonable fallback
|
|
const center: L.LatLngExpression = latestGPS ? [latestGPS.lat, latestGPS.lng] : [-37.76, 145.04];
|
|
|
|
// For debugging, let's see what coordinates this component is receiving
|
|
console.log("DeviceMap received latestGPS:", latestGPS);
|
|
|
|
return (
|
|
<MapContainer center={center} zoom={13} style={{ height: "300px", width: "100%" }}>
|
|
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
|
|
<FenceMap latestGPS={latestGPS} onFenceChange={onFenceChange} />
|
|
<MapViewUpdater center={center} /> {/* This component will handle map movement */}
|
|
</MapContainer>
|
|
);
|
|
};
|