diff --git a/public/index.html b/public/index.html index 706954f..06bf916 100644 --- a/public/index.html +++ b/public/index.html @@ -1496,7 +1496,7 @@ // ============================================ // LEAFLET MAP COMPONENT // ============================================ - const WorldMap = ({ deLocation, dxLocation, onDXChange, potaSpots, mySpots, dxPaths, satellites }) => { + const WorldMap = ({ deLocation, dxLocation, onDXChange, potaSpots, mySpots, dxPaths, satellites, showDXPaths, showPOTA, showSatellites }) => { const mapRef = useRef(null); const mapInstanceRef = useRef(null); const tileLayerRef = useRef(null); @@ -1513,7 +1513,7 @@ const satMarkersRef = useRef([]); const satTracksRef = useRef([]); - // Load map view settings from localStorage + // Load map style from localStorage const getStoredMapSettings = () => { try { const stored = localStorage.getItem('openhamclock_mapSettings'); @@ -1523,19 +1523,15 @@ const storedSettings = getStoredMapSettings(); const [mapStyle, setMapStyle] = useState(storedSettings.mapStyle || 'dark'); - const [showSatellites, setShowSatellites] = useState(storedSettings.showSatellites !== false); - const [showDXPaths, setShowDXPaths] = useState(storedSettings.showDXPaths !== false); - // Save map view settings to localStorage when they change + // Save map style to localStorage when changed useEffect(() => { try { localStorage.setItem('openhamclock_mapSettings', JSON.stringify({ - mapStyle, - showSatellites, - showDXPaths + mapStyle })); } catch (e) { console.error('Failed to save map settings:', e); } - }, [mapStyle, showSatellites, showDXPaths]); + }, [mapStyle]); // Initialize map useEffect(() => { @@ -1836,6 +1832,7 @@ } }, [dxPaths, showDXPaths]); + // Update POTA markers useEffect(() => { if (!mapInstanceRef.current) return; const map = mapInstanceRef.current; @@ -1844,21 +1841,23 @@ potaMarkersRef.current.forEach(m => map.removeLayer(m)); potaMarkersRef.current = []; - // Add new POTA markers - potaSpots.forEach(spot => { - if (spot.lat && spot.lon) { - const icon = L.divIcon({ - className: '', - html: `
${spot.call}
`, - iconAnchor: [20, 10] - }); - const marker = L.marker([spot.lat, spot.lon], { icon }) - .bindPopup(`${spot.call}
${spot.ref}
${spot.freq} ${spot.mode}`) - .addTo(map); - potaMarkersRef.current.push(marker); - } - }); - }, [potaSpots]); + // Add new POTA markers if enabled + if (showPOTA && potaSpots) { + potaSpots.forEach(spot => { + if (spot.lat && spot.lon) { + const icon = L.divIcon({ + className: '', + html: `
${spot.call}
`, + iconAnchor: [20, 10] + }); + const marker = L.marker([spot.lat, spot.lon], { icon }) + .bindPopup(`${spot.call}
${spot.ref}
${spot.freq} ${spot.mode}`) + .addTo(map); + potaMarkersRef.current.push(marker); + } + }); + } + }, [potaSpots, showPOTA]); // Update satellite markers and tracks useEffect(() => { @@ -1976,53 +1975,65 @@ ))} - {/* Satellite toggle */} - - - {/* DX Paths toggle */} - + {/* Map Legend - Bottom of map */} +
+ {/* DX Paths Band Colors */} + {showDXPaths && ( +
+ DX: + 160m + 80m + 40m + 30m + 20m + 17m + 15m + 12m + 10m + 6m +
+ )} + {showDXPaths && (showPOTA || showSatellites) && |} + + {/* POTA */} + {showPOTA && ( +
+
+ POTA +
+ )} + + {/* Satellites */} + {showSatellites && ( +
+ πŸ›° + SAT +
+ )} + + {/* DE/DX markers */} + | +
+ ● DE + ● DX + β˜€ Sun +
+
); }; @@ -2201,13 +2212,32 @@ ); }; - const DXClusterPanel = ({ spots, loading, activeSource }) => ( + const DXClusterPanel = ({ spots, loading, activeSource, showOnMap, onToggleMap }) => (
🌐 DX CLUSTER
{loading &&
} {activeSource && {activeSource}} + ● LIVE
@@ -2224,12 +2254,31 @@
); - const POTAPanel = ({ activities, loading }) => ( + const POTAPanel = ({ activities, loading, showOnMap, onToggleMap }) => (
πŸ• POTA ACTIVITY
{loading &&
} + ● LIVE
@@ -2345,7 +2394,8 @@ deGrid, dxGrid, deSunTimes, dxSunTimes, dxLocation, onDXChange, spaceWeather, bandConditions, potaSpots, dxCluster, dxPaths, contests, propagation, mySpots, satellites, localWeather, use12Hour, onTimeFormatToggle, - onSettingsClick, onFullscreenToggle, isFullscreen + onSettingsClick, onFullscreenToggle, isFullscreen, + mapLayers, toggleDXPaths, togglePOTA, toggleSatellites }) => { const bearing = calculateBearing(config.location.lat, config.location.lon, dxLocation.lat, dxLocation.lon); const distance = calculateDistance(config.location.lat, config.location.lon, dxLocation.lat, dxLocation.lon); @@ -2517,6 +2567,9 @@ mySpots={mySpots.data} dxPaths={dxPaths.data} satellites={satellites.positions} + showDXPaths={mapLayers.showDXPaths} + showPOTA={mapLayers.showPOTA} + showSatellites={mapLayers.showSatellites} />
@@ -2525,8 +2578,26 @@ {/* DX Cluster */}
- 🌐 DX CLUSTER ● LIVE - {dxCluster.activeSource && {dxCluster.activeSource}} + 🌐 DX CLUSTER +
+ + ● LIVE +
{dxCluster.data.slice(0, 8).map((s, i) => ( @@ -2565,7 +2636,25 @@ {/* POTA */}
-
πŸ• POTA
+
+ πŸ• POTA + +
{potaSpots.data.slice(0, 4).map((a, i) => (
@@ -2990,6 +3079,27 @@ const [showSettings, setShowSettings] = useState(false); const [isFullscreen, setIsFullscreen] = useState(false); + // Map layer visibility state with localStorage persistence + const [mapLayers, setMapLayers] = useState(() => { + try { + const stored = localStorage.getItem('openhamclock_mapLayers'); + const defaults = { showDXPaths: true, showPOTA: true, showSatellites: true }; + return stored ? { ...defaults, ...JSON.parse(stored) } : defaults; + } catch (e) { return { showDXPaths: true, showPOTA: true, showSatellites: true }; } + }); + + // Save map layer preferences when changed + useEffect(() => { + try { + localStorage.setItem('openhamclock_mapLayers', JSON.stringify(mapLayers)); + } catch (e) { console.error('Failed to save map layers:', e); } + }, [mapLayers]); + + // Toggle handlers for map layers + const toggleDXPaths = useCallback(() => setMapLayers(prev => ({ ...prev, showDXPaths: !prev.showDXPaths })), []); + const togglePOTA = useCallback(() => setMapLayers(prev => ({ ...prev, showPOTA: !prev.showPOTA })), []); + const toggleSatellites = useCallback(() => setMapLayers(prev => ({ ...prev, showSatellites: !prev.showSatellites })), []); + // 12/24 hour format preference with localStorage persistence const [use12Hour, setUse12Hour] = useState(() => { try { @@ -3125,6 +3235,10 @@ onSettingsClick={() => setShowSettings(true)} onFullscreenToggle={handleFullscreenToggle} isFullscreen={isFullscreen} + mapLayers={mapLayers} + toggleDXPaths={toggleDXPaths} + togglePOTA={togglePOTA} + toggleSatellites={toggleSatellites} /> - +
Click map to set DX β€’ 73 de {config.callsign}
@@ -3337,11 +3462,50 @@ {/* RIGHT SIDEBAR */}
+ {/* Satellite Toggle at top */} +
+ πŸ›° SATELLITES + +
+ {/* DX Cluster - Compact */}
- 🌐 DX CLUSTER ● LIVE - {dxCluster.activeSource && {dxCluster.activeSource}} + 🌐 DX CLUSTER ● LIVE +
+ + {dxCluster.activeSource && {dxCluster.activeSource}} +
{dxCluster.data.slice(0, 8).map((s, i) => ( @@ -3359,7 +3523,25 @@ {/* POTA - Compact */}
-
πŸ• POTA ACTIVATORS
+
+ πŸ• POTA ACTIVATORS + +
{potaSpots.data.slice(0, 5).map((a, i) => (