diff --git a/client/src/pages/MapView.jsx b/client/src/pages/MapView.jsx
index adeba89..23976b6 100644
--- a/client/src/pages/MapView.jsx
+++ b/client/src/pages/MapView.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import { MapContainer, TileLayer, Marker, Popup, Circle } from 'react-leaflet';
+import { MapContainer, TileLayer, Marker, Popup, Circle, useMap } from 'react-leaflet';
import { Icon } from 'leaflet';
import { useSocket } from '../contexts/SocketContext';
import api from '../services/api';
@@ -24,6 +24,19 @@ Icon.Default.mergeOptions({
shadowUrl,
});
+// Component to handle dynamic map bounds
+const FitBounds = ({ bounds }) => {
+ const map = useMap();
+
+ useEffect(() => {
+ if (bounds && bounds.length === 2) {
+ map.fitBounds(bounds, { padding: [20, 20] });
+ }
+ }, [bounds, map]);
+
+ return null;
+};
+
// Custom icons
const createDeviceIcon = (status, hasDetections) => {
let color = '#6b7280'; // gray for offline/inactive
@@ -73,8 +86,9 @@ const MapView = () => {
const [devices, setDevices] = useState([]);
const [selectedDevice, setSelectedDevice] = useState(null);
const [loading, setLoading] = useState(true);
- const [mapCenter, setMapCenter] = useState([59.4, 18.1]); // Stockholm area center
- const [mapZoom, setMapZoom] = useState(11); // Closer zoom for Stockholm area
+ const [mapCenter, setMapCenter] = useState([59.3293, 18.0686]); // Default to Stockholm center
+ const [mapZoom, setMapZoom] = useState(10); // Default zoom level
+ const [mapBounds, setMapBounds] = useState(null);
const [showDroneDetections, setShowDroneDetections] = useState(true);
const [droneDetectionHistory, setDroneDetectionHistory] = useState([]);
const { recentDetections, deviceStatus } = useSocket();
@@ -131,15 +145,31 @@ const MapView = () => {
setDevices(deviceData);
- // Set map bounds to Stockholm area with all three detectors
- if (deviceData.length > 0 && devices.length === 0) {
- // Stockholm area bounds that include Arlanda, Naval Base, and Royal Castle
- const stockholmBounds = [
- [59.2, 17.8], // Southwest
- [59.7, 18.4] // Northeast
+ // Calculate bounds dynamically based on device locations
+ if (deviceData.length > 0) {
+ const lats = deviceData.map(device => device.geo_lat);
+ const lons = deviceData.map(device => device.geo_lon);
+
+ const minLat = Math.min(...lats);
+ const maxLat = Math.max(...lats);
+ const minLon = Math.min(...lons);
+ const maxLon = Math.max(...lons);
+
+ // Add padding around the bounds (10% on each side)
+ const latPadding = (maxLat - minLat) * 0.1;
+ const lonPadding = (maxLon - minLon) * 0.1;
+
+ const bounds = [
+ [minLat - latPadding, minLon - lonPadding], // Southwest
+ [maxLat + latPadding, maxLon + lonPadding] // Northeast
];
- setMapCenter([59.4, 18.1]); // Center of Stockholm area
- setMapZoom(11);
+
+ setMapBounds(bounds);
+
+ // Set center to the middle of all devices
+ const centerLat = (minLat + maxLat) / 2;
+ const centerLon = (minLon + maxLon) / 2;
+ setMapCenter([centerLat, centerLon]);
}
} catch (error) {
console.error('Error fetching devices:', error);
@@ -220,15 +250,8 @@ const MapView = () => {
center={mapCenter}
zoom={mapZoom}
className="h-full w-full"
- whenCreated={(map) => {
- // Set bounds to Stockholm area to show all three detectors
- const stockholmBounds = [
- [59.2, 17.8], // Southwest
- [59.7, 18.4] // Northeast
- ];
- map.fitBounds(stockholmBounds, { padding: [20, 20] });
- }}
>
+