From 0b0718e047b8826ab38c020cfff561a5c8580e3e Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 2 May 2026 17:14:45 -0500 Subject: [PATCH] feat(rover): Maidenhead grid overlay on location detail map LocationMap hook now adds a togglable grid layer (matching the contact map pattern) so the rover-location detail page shows the standard Maidenhead overlay alongside the marker. --- assets/js/location_map_hook.ts | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/assets/js/location_map_hook.ts b/assets/js/location_map_hook.ts index e5e28266..0195f786 100644 --- a/assets/js/location_map_hook.ts +++ b/assets/js/location_map_hook.ts @@ -1,8 +1,11 @@ import type { ViewHook } from "phoenix_live_view" +import { updateGridOverlay } from "./maidenhead_grid" interface LocationMapHook extends ViewHook { map: L.Map marker: L.CircleMarker + gridLayer: L.LayerGroup + gridVisible: boolean visibilityHandler: (() => void) | null } @@ -48,6 +51,39 @@ export const LocationMap: Partial = { }).addTo(map) this.marker.bindPopup(`${lat.toFixed(6)}, ${lon.toFixed(6)}`) + // Maidenhead grid overlay + toggle + this.gridLayer = L.layerGroup().addTo(map) + this.gridVisible = true + updateGridOverlay(map, this.gridLayer) + map.on("moveend", () => { + if (this.gridVisible) updateGridOverlay(map, this.gridLayer) + }) + + const GridToggle = L.Control.extend({ + options: { position: "topright" as const }, + onAdd: () => { + const btn = L.DomUtil.create("button", "leaflet-bar leaflet-control") + btn.innerHTML = "Grid" + btn.title = "Toggle Maidenhead grid" + btn.style.cssText = + "background:#fff;padding:4px 8px;font-size:12px;cursor:pointer;font-weight:600;" + L.DomEvent.disableClickPropagation(btn) + btn.onclick = () => { + this.gridVisible = !this.gridVisible + if (this.gridVisible) { + this.gridLayer.addTo(map) + updateGridOverlay(map, this.gridLayer) + btn.style.opacity = "1" + } else { + this.gridLayer.remove() + btn.style.opacity = "0.5" + } + } + return btn + } + }) + new GridToggle().addTo(map) + // LiveView reconnect / tab visibility — Leaflet needs invalidateSize. this.visibilityHandler = () => { if (document.visibilityState === "visible") this.map.invalidateSize()