45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
// lib/map.tsx - Custom叶 map component with Leaflet for GPS location and geo-fence drawing
|
|
import { useState } from "react";
|
|
import { MapContainer, TileLayer, Marker, Polyline, useMapEvents } from "react-leaflet";
|
|
import L from "leaflet";
|
|
import "leaflet/dist/leaflet.css";
|
|
|
|
// Fix default Leaflet icon issue in React
|
|
delete (L.Icon.Default as any)._getIconUrl;
|
|
|
|
interface MapProps {
|
|
latestGPS?: { lat: number; lng: number };
|
|
onFenceChange: (fence: Array<{ lat: number; lng: number }>) => void;
|
|
}
|
|
|
|
const FenceMap = ({ latestGPS, onFenceChange }: MapProps) => {
|
|
const [fence, setFence] = useState<Array<{ lat: number; lng: number }>>([]);
|
|
|
|
const map = useMapEvents({
|
|
click: (e) => {
|
|
const newFence = [...fence, { lat: e.latlng.lat, lng: e.latlng.lng }];
|
|
setFence(newFence);
|
|
onFenceChange(newFence); // Update parent
|
|
},
|
|
});
|
|
|
|
const center = latestGPS ? [latestGPS.lat, latestGPS.lng] : [0, 0]; // Default center
|
|
|
|
return (
|
|
<>
|
|
{fence.length > 1 && <Polyline pathOptions={{ color: "red" }} positions={fence} />}
|
|
{latestGPS && <Marker position={[latestGPS.lat, latestGPS.lng]} />}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export const DeviceMap = ({ latestGPS }: { latestGPS?: { lat: number; lng: number } }) => {
|
|
const [fence, setFence] = useState<Array<{ lat: number; lng: number }>>([]);
|
|
|
|
return (
|
|
<MapContainer center={[0, 0]} zoom={2} style={{ height: "300px", width: "100%" }}>
|
|
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
|
|
<FenceMap latestGPS={latestGPS} onFenceChange={setFence} />
|
|
</MapContainer>
|
|
);
|
|
}; |