From 03598cfaffeea8874ff7948f30e3725dc8ce98e5 Mon Sep 17 00:00:00 2001 From: Gregory Salaun Date: Thu, 13 Aug 2026 11:30:27 +0200 Subject: [PATCH] feat(entry): NEW badge on the county in the entry strip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same answer the Details tab already gave, moved to where the county is now typed — a badge in a tab nobody has open while working a station is a badge that does not do its job. Debounced at 300 ms and keyed on state + county together: the field is typed into as well as filled by the lookup, and the check queries the log. A county name means nothing without its state, so both have to settle before asking. --- frontend/src/App.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f9e1288..ae37c78 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -91,7 +91,7 @@ import { ShutdownProgress } from '@/components/ShutdownProgress'; import { ClusterGrid } from '@/components/ClusterGrid'; import { cleanSpotter, inferSpotMode, spotModeCategory, spotStatusKey } from '@/lib/spot'; import { applySpotDisplay, readSpotDisplayOptions, spotIsWorked, SPOT_DISPLAY_OPTIONS_EXPOSED } from '@/lib/spotDisplay'; -import { GetRowColors, GetSpotTTLMinutes } from '../wailsjs/go/main/App'; +import { GetRowColors, GetSpotTTLMinutes, IsNewUSCounty } from '../wailsjs/go/main/App'; import { WorkedBeforeGrid } from '@/components/WorkedBeforeGrid'; import { NetControlPanel } from '@/components/NetControlPanel'; import { ContestPanel, CONTEST_DEFAULT, type ContestSession } from '@/components/ContestPanel'; @@ -4459,6 +4459,23 @@ export default function App() { // A numeric field stores undefined when cleared, not 0: zero is a real DXCC // number for "no entity" and a real answer for a zone, so an empty box must // stay empty rather than assert something. + // NEW badge on the county — the same answer the Details tab gives, moved to + // where the county is now typed. Debounced: this field is typed into as well + // as filled by the lookup, and the check hits the database. + const [entryNewCounty, setEntryNewCounty] = useState(false); + useEffect(() => { + const cnty = (details.cnty ?? '').trim(); + if (!cnty) { setEntryNewCounty(false); return; } + let alive = true; + const id = window.setTimeout(async () => { + try { + const isNew = await IsNewUSCounty(details.state ?? '', cnty); + if (alive) setEntryNewCounty(!!isNew); + } catch { if (alive) setEntryNewCounty(false); } + }, 300); + return () => { alive = false; window.clearTimeout(id); }; + }, [details.state, details.cnty]); + const num = (v: string): number | undefined => { const s = v.replace(/[^0-9]/g, ''); return s === '' ? undefined : parseInt(s, 10);