Skip to content

bug: channel edit maidenhead/coords fields drift precision when switched cyclically #49

Description

@pskillen

Problem

On the channel edit page (#11), Maidenhead locator and lat/lon coordinate fields are both active at once. Editing one continuously updates the other:

  • Changing lat/lon calls coordsToLocator(lat, lon, 6) on each keystroke (edit.tsx NumberInput onChange handlers).
  • Blurring the locator field calls locatorToCoords via applyLocator, snapping to the centre of the 6-character square.

Cycling locator → coords → locator → coords incrementally reduces coordinate precision because each round-trip quantises to the Maidenhead cell centre at 6-char resolution (~5 km). A user entering precise GPS coordinates will see them drift if they touch both fields.

Root cause

Two authoritative inputs kept in sync bidirectionally. Maidenhead is a lossy representation at fixed precision; treating both as live sources of truth causes drift.

Intended fix

UI behaviour

  • One active input mode at a time: either coordinates (lat/lon) or Maidenhead locator — not both editable simultaneously.
  • Switch control: button or segmented control to change mode, with options:
    • Switch without converting (discard/sync the inactive field)
    • Switch with converting (populate the target from the current authoritative value)
  • Convert button: explicit one-shot "locator → coords" or "coords → locator" while staying in the current mode (optional; may be folded into switch-with-convert).
  • Detail page: display both read-only values derived from the stored authoritative source (no drift on view).

Data model

Add explicit storage for the operator's chosen representation:

  • New field on Channel, e.g. maidenheadLocator: string | null (precision as entered, normalised uppercase).
  • Mutual exclusivity: when maidenheadLocator is set, location is null (or vice versa). Only one is authoritative in the model.
  • useLocation still gates whether location data is active at all.
  • Update docs/features/data-model/ and schema version / migration for existing projects (default: coords-only from current location field).

Import / export

  • OpenGD77 import: unchanged — CPS provides Latitude / Longitude only; populate location, leave maidenheadLocator null.
  • OpenGD77 export: CPS expects coordinates — if maidenheadLocator is authoritative, convert via locatorToCoords at export time and emit lat/lon; if location is authoritative, emit as today.
  • No Maidenhead column in OpenGD77 CSV today.

Repro

  1. Edit a channel; enter precise coords (e.g. 55.953252, -3.188267).
  2. Tab to locator (auto-filled 6-char, e.g. IO85 + subsquare).
  3. Blur locator (applies locatorToCoords → centre of cell).
  4. Edit lat/lon slightly → locator updates → blur locator again.
  5. Observe coords have drifted from original precision.

Affected

  • src/models/codeplug.tsmaidenheadLocator (or equivalent) + migration
  • src/routes/channels/edit.tsx — mutually exclusive input UX
  • src/routes/channels/detail.tsx — read-only display from authoritative field
  • src/lib/import/ / export layer — coords conversion at boundary
  • docs/features/maidenhead.md, docs/features/data-model/

Notes / dependencies

Out of scope

  • Storing both coords and locator as independently authoritative (that recreates the bug).
  • Sub-6-char locator precision in the model unless explicitly entered by the user.

Workflow note

Branch from origin/main, atomic conventional commits, PR linking Closes #.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions