fix(qsl): show a verified confirmation as verified, not as "No"

Same bug as yesterday's, one screen further on. The QSL Info table maps the
statuses it knows — Y, R, I, M — and falls through to "No" for anything else.
ADIF's V is anything else. So a contact confirmed AND validated by LoTW was
reported as not received, in the one place an operator opens to check.

V now has its own label, Verified, in the green of a confirmation, and it is in
the dropdown too. That second half matters more than it looks: a select whose
value is not among its items renders blank, so a verified contact looked like
nothing had been recorded — and the operator's next click would have replaced
the strongest confirmation they hold with whatever they picked instead.

The QSL Manager's bulk list is deliberately left alone: it sets paper QSL
status across a selection and defaults to "leave", so it never displays a
stored value, and "verified" is not something a paper card can be.
This commit is contained in:
2026-08-15 09:42:17 +02:00
parent 5bf7eb45d7
commit a6842382b2
3 changed files with 16 additions and 6 deletions
+12 -2
View File
@@ -41,9 +41,14 @@ function pfxOf(call: string): string {
const BANDS = ['2190m','630m','160m','80m','60m','40m','30m','20m','17m','15m','12m','10m','6m','4m','2m','1.25m','70cm','33cm','23cm','13cm','9cm','6cm','3cm','1.25cm','6mm','4mm','2.5mm','2mm','1mm'];
const MODES = ['SSB','CW','FT8','FT4','RTTY','PSK31','AM','FM','DIGITALVOICE','MFSK','OLIVIA','JS8','JT65','JT9'];
// label holds an i18n key (resolved with t() at render time).
// V is in the list because the log HOLDS it: a LoTW download writes "verified"
// rather than "yes". A dropdown without it renders a verified contact as blank,
// which reads as "nothing recorded" — and the operator's next click would replace
// the strongest confirmation they have with whatever they picked instead.
const QSL_STATUSES = [
{ value: '_', label: 'qedit.qslDash' },
{ value: 'Y', label: 'qedit.qslYes' },
{ value: 'V', label: 'qedit.qslVerified' },
{ value: 'N', label: 'qedit.qslNo' },
{ value: 'R', label: 'qedit.qslRequested' },
{ value: 'I', label: 'qedit.qslIgnore' },
@@ -99,9 +104,14 @@ function StatusCell({ value }: { value?: string }) {
// every row; painting that orange (as it used to be, in the
// same orange as Requested) made the table shout about a
// non-problem and told you nothing apart.
// Verified green — ADIF's V: confirmed AND validated by the awarding body.
// It is what a LoTW download writes, and this table used
// to fall through to "No" for it — reporting a verified
// contact as unconfirmed, in the one place an operator
// goes to check.
// Ignore dashed — deliberately excluded, on purpose.
const label = v === 'Y' ? t('qedit.qslYes') : v === 'R' ? t('qedit.qslRequested') : v === 'I' ? t('qedit.qslIgnore') : v === 'M' ? t('qedit.statusModified') : t('qedit.qslNo');
const cls = v === 'Y' ? 'bg-success text-success-foreground border border-success'
const label = v === 'Y' ? t('qedit.qslYes') : v === 'V' ? t('qedit.qslVerified') : v === 'R' ? t('qedit.qslRequested') : v === 'I' ? t('qedit.qslIgnore') : v === 'M' ? t('qedit.statusModified') : t('qedit.qslNo');
const cls = v === 'Y' || v === 'V' ? 'bg-success text-success-foreground border border-success'
: v === 'R' ? 'bg-info-muted text-info-muted-foreground border border-info-border'
: v === 'M' ? 'bg-warning text-warning-foreground border border-warning'
: v === 'I' ? 'bg-muted text-muted-foreground border border-dashed border-border italic'
File diff suppressed because one or more lines are too long