You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When out and about, an operator may have their codeplug on a phone and want to know how far they are from a repeater or other geolocated channel — and see it on a map. Today:
Channel detail shows coordinates, locator, and an embedded map, but no distance from the operator.
Channel list sorts alphabetically only; no proximity sort.
Maps (CodeplugMap on channel detail, channel list, zone detail) plot channels/zones but not the operator's position.
#59 shipped UseMyLocationButton for seeding coordinates on edit/converter, but there is no session operator position reused across browse views for distance and map context.
Intended outcome
Add operator-position awareness for field use — distance display, proximity sort, and "you are here" on maps.
Operator position (session)
Introduce a session-scoped operator position (lat/lon + optional accuracy), obtained via existing useGeolocation / UseMyLocationButton — not persisted to localStorage or codeplug.
Provide a shared hook or context, e.g. useOperatorPosition() — set on explicit user action; clear on tab close or manual "Clear my location".
When operator position is known and channel has useLocation + coordinates:
Show distance from me in Location section (e.g. 12.4 km or 850 m — pick sensible threshold for unit switch).
On embedded CodeplugMap: plot operator marker (distinct style from channel marker) plus channel marker; fit bounds or centre to show both when reasonable.
When position unknown: show Use my location to enable distance; distance row hidden or "—".
Channel list
Add sort control: Name (default) | Distance from me.
Distance sort: channels with geolocation ascending by haversine distance; channels without location at bottom (stable sub-sort by name).
Distance sort requires operator position — if unset, show helper + Use my location button; disable sort or prompt on select.
Optional v1: Distance optional column when position known (defer if sort alone is enough).
Channel list map (CodeplugMap at bottom of list): show operator marker when position set.
Zone detail map
On zone detail CodeplugMap: show operator marker when position set (zone hull + member channels + you).
No per-member distance table required for v1.
Distance math
New util src/lib/geoDistance.ts (or extend src/lib/geo.ts): haversine distance in metres; format for display (formatDistanceM(m)).
Use WGS84 coords throughout; no elevation.
Affected
New useOperatorPosition hook or lightweight context (session state only)
src/lib/geo.ts or geoDistance.ts — haversine + formatting
Operator position is ephemeral — distinct from channel location and from saving QTH in Settings (out of scope).
Channels with hideFromMap still participate in distance sort/display if they have coordinates (hideFromMap affects map plots only — document behaviour).
Privacy: position used only after explicit button click; not uploaded; session-only.
Out of scope
Continuous GPS tracking / watchPosition while browsing.
Bearing / compass direction to repeater.
Filtering channel list by radius ("within 50 km") — sort is sufficient for v1.
Persisting last known operator position across sessions.
Problem
When out and about, an operator may have their codeplug on a phone and want to know how far they are from a repeater or other geolocated channel — and see it on a map. Today:
CodeplugMapon channel detail, channel list, zone detail) plot channels/zones but not the operator's position.#59 shipped
UseMyLocationButtonfor seeding coordinates on edit/converter, but there is no session operator position reused across browse views for distance and map context.Intended outcome
Add operator-position awareness for field use — distance display, proximity sort, and "you are here" on maps.
Operator position (session)
useGeolocation/UseMyLocationButton— not persisted to localStorage or codeplug.useOperatorPosition()— set on explicit user action; clear on tab close or manual "Clear my location".Channel detail page
When operator position is known and channel has
useLocation+ coordinates:12.4 kmor850 m— pick sensible threshold for unit switch).CodeplugMap: plot operator marker (distinct style from channel marker) plus channel marker; fit bounds or centre to show both when reasonable.Channel list
Name(default) | Distance from me.CodeplugMapat bottom of list): show operator marker when position set.Zone detail map
CodeplugMap: show operator marker when position set (zone hull + member channels + you).Distance math
src/lib/geoDistance.ts(or extendsrc/lib/geo.ts): haversine distance in metres; format for display (formatDistanceM(m)).Affected
useOperatorPositionhook or lightweight context (session state only)src/lib/geo.tsorgeoDistance.ts— haversine + formattingsrc/routes/channels/detail.tsx— distance field, map operator markersrc/routes/channels/list.tsx— sort control, optional map markersrc/routes/zones/detail.tsx— map operator markersrc/components/CodeplugMap/CodeplugMap.tsx— optionaloperatorPositionprop + marker renderingdocs/features/maidenhead.mdor map docs — session geolocation for browse vs editNotes / dependencies
UseMyLocationButton,useGeolocation,geolocation.ts) — reuse, don't fork.locationand from saving QTH in Settings (out of scope).hideFromMapstill participate in distance sort/display if they have coordinates (hideFromMap affects map plots only — document behaviour).Out of scope
operatorPositionprop pattern later.Manual verify
Workflow note
Branch from
origin/main, atomic conventional commits (distance util → operator position hook → CodeplugMap marker → detail → list sort → zone map → docs), PR linkingCloses #70.