diff --git a/changelog.json b/changelog.json index 8359895..d5f0cd1 100644 --- a/changelog.json +++ b/changelog.json @@ -1,4 +1,14 @@ [ + { + "version": "0.22.5", + "date": "", + "en": [ + "Cluster filters gain NEW POTA and NEW COUNTY, alongside the existing status chips." + ], + "fr": [ + "Les filtres du cluster gagnent NEW POTA et NEW COUNTY, à côté des pastilles de statut existantes." + ] + }, { "version": "0.22.4", "date": "", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e97218c..8e7ea5f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1323,7 +1323,12 @@ export default function App() { // Status filter chips. Empty set = show every status (including // already-worked). Otherwise only matching spots pass. type SpotStatusKey = 'new' | 'new-band' | 'new-mode' | 'new-slot' | 'worked'; - const [clusterStatusFilter, setClusterStatusFilter] = useState>(() => lsSet('opslog.clusterStatusFilter')); + // What the cluster can be FILTERED on. A superset of the entity status: a new + // county or a new park is not a DXCC state, it is another dimension of the + // same spot — which is why the grid shows them as separate badges. Filtering + // is an OR across all of them, as it already was for a worked callsign. + type SpotFilterKey = SpotStatusKey | 'new-pota' | 'new-county'; + const [clusterStatusFilter, setClusterStatusFilter] = useState>(() => lsSet('opslog.clusterStatusFilter')); // Mode filter chips. Empty set = show every mode. Categories map the // inferred per-spot mode onto SSB (phone) / CW / DATA (digital). type SpotModeCat = 'SSB' | 'CW' | 'DATA'; @@ -4269,7 +4274,10 @@ export default function App() { // entity status is still new-band/new-slot (the grid flags it WKD CALL), // matching the "Hide worked" toggle. Additive: it still matches its own // entity status too, so it stays visible under NEW BAND / NEW SLOT. - const matches = clusterStatusFilter.has(st) || (!!e?.worked_call && clusterStatusFilter.has('worked')); + const matches = clusterStatusFilter.has(st) + || (!!e?.worked_call && clusterStatusFilter.has('worked')) + || (!!e?.new_pota && clusterStatusFilter.has('new-pota')) + || (!!e?.new_county && clusterStatusFilter.has('new-county')); if (!matches) return false; } if (clusterHideWorked) { @@ -4381,10 +4389,14 @@ export default function App() {
Status
{([ - { k: 'new' as SpotStatusKey, label: 'NEW', cls: 'bg-danger-muted text-danger-muted-foreground border-danger-border' }, - { k: 'new-band' as SpotStatusKey, label: 'NEW BAND', cls: 'bg-warning-muted text-warning-muted-foreground border-warning-border' }, - { k: 'new-mode' as SpotStatusKey, label: 'NEW MODE', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' }, - { k: 'new-slot' as SpotStatusKey, label: 'NEW SLOT', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' }, + { k: 'new' as SpotFilterKey, label: 'NEW', cls: 'bg-danger-muted text-danger-muted-foreground border-danger-border' }, + { k: 'new-band' as SpotFilterKey, label: 'NEW BAND', cls: 'bg-warning-muted text-warning-muted-foreground border-warning-border' }, + { k: 'new-mode' as SpotFilterKey, label: 'NEW MODE', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' }, + { k: 'new-slot' as SpotFilterKey, label: 'NEW SLOT', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' }, + // Same colours as the badges in the grid — a filter that does not + // look like what it selects has to be learned twice. + { k: 'new-pota' as SpotFilterKey, label: 'NEW POTA', cls: 'bg-success-muted text-success-muted-foreground border-success-border' }, + { k: 'new-county' as SpotFilterKey, label: 'NEW COUNTY', cls: 'bg-info-muted text-info-muted-foreground border-info-border' }, // (no WORKED chip — use the "Hide worked" checkbox to drop dupes.) ]).map((s) => { const on = clusterStatusFilter.has(s.k);