Skip to content

fix(search): let operators filter by every band they can log (add 2200M/630M/4M/1.25M/33CM/13CM)#241

Merged
patrickrb merged 1 commit into
mainfrom
optio/task-5263b634-6b86-4cea-908e-9f1a1d915a18
Jul 24, 2026
Merged

fix(search): let operators filter by every band they can log (add 2200M/630M/4M/1.25M/33CM/13CM)#241
patrickrb merged 1 commit into
mainfrom
optio/task-5263b634-6b86-4cea-908e-9f1a1d915a18

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Problem

The Search → Band filter hard-coded its own band list that had drifted out of sync with the rest of the app. The logging forms (new-contact, QuickLogCard) present one-click band pills sourced from the canonical band plan (AMATEUR_BANDS in @/lib/bands), and the ADIF importer derives bands from the same plan — so a QSO can be logged/imported on any of 20 bands. But the search dropdown only offered 14, silently omitting:

  • 2200M, 630M (LF/MF digital)
  • 4M
  • 1.25M (222 MHz)
  • 33CM (902 MHz), 13CM (2.3 GHz)

Result: an operator could log a contact on, say, 4M or 630M with a single click, then find it impossible to filter for that band in Search — the option simply wasn't in the list. The hard-coded copy was also lowercase ('20m') while the app stores/derives uppercase ('20M'), a classic drift trap.

Solution

Source the Search band dropdown from the single source of truth, AMATEUR_BANDS, the same list the logging forms use. This removes the drift by construction — the search filter can no longer fall behind the band plan.

Server-side matching is already case-insensitive (UPPER(band) = UPPER($n) in buildContactSearchQuery), so switching the option values from lowercase to the canonical uppercase form matches existing stored data without any migration.

One line of behavior, plus an explanatory comment:

const BANDS = AMATEUR_BANDS;

Testing

  • Extended tests/bands.spec.ts with a test asserting the canonical band plan covers every band the search filter must offer — explicitly including the six previously-unfilterable bands and the legacy set (nothing regressed). This guards against the band plan ever being trimmed in a way that would re-break search coverage.
  • npm run typecheck — clean
  • npm run lint — clean
  • npm run build — succeeds (/search compiles)
  • npx playwright test tests/bands.spec.ts — 5/5 pass

Scope / follow-up

  • Kept strictly to the band filter (one problem, done well).
  • The Search mode dropdown is hard-coded the same way and has similar drift (e.g. JS8/FST4 submodes stored as modes since feat(adif): store the ADIF submode (FT4/JS8/PSK31) as the QSO mode on import #240 aren't offered). There is no canonical mode-list module to source from yet; introducing one and wiring the mode filter to it is a natural follow-up.

🤖 Generated with Claude Code

…0M/4M/1.25M/33CM/13CM)

The Search band filter hard-coded its own lowercase band list that had
drifted from the canonical band plan (`AMATEUR_BANDS` in @/lib/bands). The
logging forms (new-contact, QuickLogCard) present one-click pills for the full
band plan, but the search dropdown omitted 2200M, 630M, 4M, 1.25M, 33CM and
13CM — so an operator could log a QSO on those bands yet never filter it back
out. Source the dropdown from the shared band plan instead, eliminating the
drift by construction. Server-side matching is already case-insensitive
(`UPPER(band) = UPPER($n)`), so the uppercase canonical values match stored data.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nodelog Ready Ready Preview, Comment Jul 24, 2026 7:10am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant