fix(awards): the entry-form picker offers only the awards this station follows

F3 listed every award that existed, enabled or not, followed or not — so
a station chasing three of them assigned references from a list of twenty
and had to know which of the twenty mattered.

It now applies the same two rules the Awards tab already uses: an award
switched off in the editor is not a candidate for anything, and when a
selection of followed awards exists, only those are offered. An empty
selection still means all of them, so nobody loses a picker by never
having chosen.
This commit is contained in:
2026-08-25 17:07:30 +02:00
parent df1d2767cd
commit 97ae05d688
2 changed files with 20 additions and 7 deletions
+16 -5
View File
@@ -1,13 +1,13 @@
import { useEffect, useMemo, useState } from 'react';
import { X, Plus, Loader2 } from 'lucide-react';
import { SearchAwardReferences, GetAwardDefs, GetAwardReferenceMeta, AwardRefsNew } from '../../wailsjs/go/main/App';
import { SearchAwardReferences, GetAwardDefs, GetAwardReferenceMeta, AwardRefsNew, GetTrackedAwards } from '../../wailsjs/go/main/App';
import {
Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
} from '@/components/ui/select';
import { useI18n } from '@/lib/i18n';
type AwardRef = { code: string; name: string; dxcc: number; group: string; subgrp: string };
type AwardDef = { code: string; name: string; field?: string; dxcc_filter?: number[] | null; dynamic?: boolean };
type AwardDef = { code: string; name: string; field?: string; dxcc_filter?: number[] | null; dynamic?: boolean; valid?: boolean };
type Meta = { code: string; count: number; can_update: boolean };
// Fields auto-derived from structured QSO data — their awards (DXCC/WAZ/WAS/…)
@@ -94,11 +94,16 @@ export function AwardRefSelector({ dxcc, value, onChange, fieldValues, heightCla
}
}, [value]);
// The awards the operator FOLLOWS, exactly as the Awards tab reads them.
// This panel used to offer every award that existed, so a station chasing
// three of them was picking references out of a list of twenty.
const [tracked, setTracked] = useState<Set<string>>(new Set());
useEffect(() => {
Promise.all([GetAwardDefs(), GetAwardReferenceMeta()])
.then(([d, m]) => {
Promise.all([GetAwardDefs(), GetAwardReferenceMeta(), GetTrackedAwards()])
.then(([d, m, tr]) => {
setDefs((d ?? []) as any);
setMetas(Object.fromEntries(((m ?? []) as Meta[]).map((x) => [String(x.code).toUpperCase(), x])));
setTracked(new Set(((tr ?? []) as string[]).map((c) => String(c).toUpperCase())));
})
.catch(() => {});
}, []);
@@ -111,6 +116,12 @@ export function AwardRefSelector({ dxcc, value, onChange, fieldValues, heightCla
return defs.filter((d) => {
// Computed awards (field = dxcc/cqz/…) are derived automatically.
if (COMPUTED_FIELDS.has(String(d.field ?? '').toLowerCase())) return false;
// Switched off in the award editor: not a candidate for anything.
if (d.valid === false) return false;
// Followed awards only, when a selection has been made. An empty
// selection means "all of them" — the same rule the Awards tab uses, so
// the two lists cannot disagree about what this station chases.
if (tracked.size > 0 && !tracked.has(String(d.code).toUpperCase())) return false;
const scope = d.dxcc_filter ?? [];
if (scope.length > 0 && (!dxcc || !scope.includes(dxcc))) return false;
// Offer the award even when its reference list isn't loaded yet: a custom
@@ -122,7 +133,7 @@ export function AwardRefSelector({ dxcc, value, onChange, fieldValues, heightCla
return true;
}).map((d) => ({ code: d.code, name: d.name, field: String(d.field ?? '').toLowerCase() }))
.sort((a, b) => a.code.localeCompare(b.code));
}, [defs, metas, dxcc]);
}, [defs, metas, dxcc, tracked]);
// Keep the selected award valid as the offered list changes with the call.
useEffect(() => {