Move Geofence toggle button to map header next to Export
Relocated the "Show/Hide Geofences" toggle button from floating position (top-right corner) to the main header toolbar. **Changes:** - Moved toggle button to header, positioned between Export and Admin buttons - Converted showGeofences from local state to prop passed from parent - Button now matches header design system (same styling as Export/Admin) - Purple background when active, white when inactive - Better UX: All controls now in one consistent location **New Button Position:** Export | Show/Hide Geofences | Admin | Logout Much cleaner and more intuitive than the floating button! 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@ export default function MapPage() {
|
|||||||
const [timeFilter, setTimeFilter] = useState<number>(1); // Default 1 hour
|
const [timeFilter, setTimeFilter] = useState<number>(1); // Default 1 hour
|
||||||
const [isPaused, setIsPaused] = useState(false);
|
const [isPaused, setIsPaused] = useState(false);
|
||||||
const [devices, setDevices] = useState<DeviceInfo[]>([]);
|
const [devices, setDevices] = useState<DeviceInfo[]>([]);
|
||||||
|
const [showGeofences, setShowGeofences] = useState(true);
|
||||||
|
|
||||||
// Custom range state
|
// Custom range state
|
||||||
const [filterMode, setFilterMode] = useState<"quick" | "custom">("quick");
|
const [filterMode, setFilterMode] = useState<"quick" | "custom">("quick");
|
||||||
@@ -128,7 +129,7 @@ export default function MapPage() {
|
|||||||
{/* Spacer to push buttons to the right */}
|
{/* Spacer to push buttons to the right */}
|
||||||
<div className="hidden lg:block lg:flex-1"></div>
|
<div className="hidden lg:block lg:flex-1"></div>
|
||||||
|
|
||||||
{/* Export, Admin and Logout Buttons */}
|
{/* Export, Geofences, Admin and Logout Buttons */}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<a
|
<a
|
||||||
href="/export"
|
href="/export"
|
||||||
@@ -137,6 +138,18 @@ export default function MapPage() {
|
|||||||
<span className="mr-1.5">📥</span>
|
<span className="mr-1.5">📥</span>
|
||||||
Export
|
Export
|
||||||
</a>
|
</a>
|
||||||
|
<button
|
||||||
|
onClick={() => setShowGeofences(!showGeofences)}
|
||||||
|
className={`inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg transition-all duration-200 shadow-sm ${
|
||||||
|
showGeofences
|
||||||
|
? "bg-purple-600 text-white border border-purple-600 hover:bg-purple-700 hover:border-purple-700"
|
||||||
|
: "bg-white text-gray-700 border border-gray-300 hover:bg-gray-50 hover:border-gray-400"
|
||||||
|
}`}
|
||||||
|
title={showGeofences ? "Hide Geofences" : "Show Geofences"}
|
||||||
|
>
|
||||||
|
<span className="mr-1.5">📍</span>
|
||||||
|
{showGeofences ? "Hide" : "Show"} Geofences
|
||||||
|
</button>
|
||||||
<a
|
<a
|
||||||
href="/admin"
|
href="/admin"
|
||||||
className="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-blue-600 rounded-lg hover:bg-blue-700 hover:border-blue-700 transition-all duration-200 shadow-sm"
|
className="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-blue-600 rounded-lg hover:bg-blue-700 hover:border-blue-700 transition-all duration-200 shadow-sm"
|
||||||
@@ -192,6 +205,7 @@ export default function MapPage() {
|
|||||||
filterMode={filterMode}
|
filterMode={filterMode}
|
||||||
startTime={startTime}
|
startTime={startTime}
|
||||||
endTime={endTime}
|
endTime={endTime}
|
||||||
|
showGeofences={showGeofences}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ interface MapViewProps {
|
|||||||
filterMode: "quick" | "custom";
|
filterMode: "quick" | "custom";
|
||||||
startTime: string; // datetime-local format
|
startTime: string; // datetime-local format
|
||||||
endTime: string; // datetime-local format
|
endTime: string; // datetime-local format
|
||||||
|
showGeofences: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeviceInfo {
|
interface DeviceInfo {
|
||||||
@@ -67,14 +68,13 @@ function SetViewOnChange({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MapView({ selectedDevice, timeFilter, isPaused, filterMode, startTime, endTime }: MapViewProps) {
|
export default function MapView({ selectedDevice, timeFilter, isPaused, filterMode, startTime, endTime, showGeofences }: MapViewProps) {
|
||||||
const [locations, setLocations] = useState<Location[]>([]);
|
const [locations, setLocations] = useState<Location[]>([]);
|
||||||
const [devices, setDevices] = useState<Record<string, DeviceInfo>>({});
|
const [devices, setDevices] = useState<Record<string, DeviceInfo>>({});
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [mapCenter, setMapCenter] = useState<[number, number] | null>(null);
|
const [mapCenter, setMapCenter] = useState<[number, number] | null>(null);
|
||||||
const [currentZoom, setCurrentZoom] = useState(12);
|
const [currentZoom, setCurrentZoom] = useState(12);
|
||||||
const [showGeofences, setShowGeofences] = useState(true);
|
|
||||||
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
// Add animation styles for latest marker
|
// Add animation styles for latest marker
|
||||||
@@ -228,22 +228,7 @@ export default function MapView({ selectedDevice, timeFilter, isPaused, filterMo
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full relative">
|
<div className="h-full w-full">
|
||||||
{/* Geofence Toggle Button */}
|
|
||||||
<div className="absolute top-4 right-4 z-[1000]">
|
|
||||||
<button
|
|
||||||
onClick={() => setShowGeofences(!showGeofences)}
|
|
||||||
className={`px-4 py-2 rounded-lg shadow-lg font-semibold text-sm transition-all ${
|
|
||||||
showGeofences
|
|
||||||
? "bg-purple-600 text-white hover:bg-purple-700"
|
|
||||||
: "bg-white text-gray-700 hover:bg-gray-100"
|
|
||||||
}`}
|
|
||||||
title={showGeofences ? "Hide Geofences" : "Show Geofences"}
|
|
||||||
>
|
|
||||||
📍 {showGeofences ? "Hide" : "Show"} Geofences
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<MapContainer
|
<MapContainer
|
||||||
center={[48.1351, 11.582]}
|
center={[48.1351, 11.582]}
|
||||||
zoom={12}
|
zoom={12}
|
||||||
|
|||||||
Reference in New Issue
Block a user