Session-scoped operator position for field use: distance from me on channel detail, proximity sort and distance column on the channel list, and a you-are-here marker on embedded maps.
Tracking: codeplug-tool#70 · builds on #59 (device geolocation on edit/converter)
| Area |
Status |
Notes |
| Distance utilities |
Shipped |
haversineDistanceM, formatDistanceM in src/lib/geoDistance.ts |
| Session operator position |
Shipped |
OperatorPositionProvider / useOperatorPosition — memory only |
| CodeplugMap operator marker |
Shipped |
operatorPosition prop — blue “You” marker, included in bounds |
| Channel detail distance |
Shipped |
Location section + Use/Clear my location |
| Channel list sort + column |
Shipped |
Name / Distance from me; hideable distance column (default on) |
| Channel list distance filter |
Shipped |
Within distance switch + km slider; hides ungeolocated |
| Zone detail map marker |
Shipped |
Reuses session position |
| Term |
Meaning |
| Session position |
Operator lat/lon obtained via Use my location; lives in React context only — cleared on tab reload, not saved to localStorage or codeplug |
| Edit/converter position |
Same button (#59) but parent owns persistence (save channel or copy from converter) |
| Distance from me |
Haversine great-circle distance (WGS84, no elevation) between session position and channel coordinates |
| hideFromMap |
Affects map plotting only; channels with coordinates still appear in distance sort and distance column |
- Below 1 km: metres rounded, e.g.
850 m
- At or above 1 km: kilometres with one decimal, e.g.
12.4 km
- No session position or no channel coordinates:
—
| Path |
Role |
src/lib/geoDistance.ts |
Haversine + formatDistanceM |
src/lib/channels.ts |
channelHasGeolocation |
src/state/operatorPosition.tsx |
Session context |
src/routes/channels/detail.tsx |
Distance field, location controls |
src/routes/channels/list.tsx |
Sort, distance column, map |
src/routes/zones/detail.tsx |
Map marker |
src/components/CodeplugMap/CodeplugMap.tsx |
operatorPosition prop |
src/components/UseMyLocationButton/ |
Shared geolocation button |
- Trigger: explicit Use my location click only — no auto-prompt, no
watchPosition
- Privacy: browser Geolocation API locally; never uploaded; session-only unless user saves a channel on edit
- Permission denied: inline error on button; rest of page usable
- Distance sort: geolocated channels ascending; unlocated at bottom (sub-sorted by name). Without session position, sort falls back to name with helper text
- Distance filter: Within distance switch on channel list — hides channels without coordinates (
Use Location off or missing coords). Slider (5–200 km, marked) limits radius when session position is set; map shows filtered channels only
- Maps: operator marker distinct from channel markers; bounds include operator + channels when both present
- Channel detail → Use my location → distance appears; map shows channel + You markers
- Deny permission → inline error; no distance
- Channel list → sort by distance → nearest repeater first; unlocated channels last
- Within distance filter → ungeolocated hidden; slider limits radius when location set
- Distance column shows values when position set,
— when not
- Zone detail map → operator marker with zone hull
- Reload page → position cleared; distance hidden until requested again
- Clear my location → distance/marker removed across views