feat(qsl): show the OpsLog card with the other confirmations
The OpsLog QSL marker sat under QSL Msg in "Contact's details", nowhere near the channel it belongs to, while the QSL Info tab listed every other confirmation — QSL, LoTW, eQSL, QRZ.com, Club Log, HRDLog — with a Sent and a Received column. It now has its own row in that table and the "QSL received" tick moved to the same tab, keeping the PSE QSL / TNX indicator that is the reason the flag exists at all: received prints TNX on the card, otherwise PSE QSL. Written by hand rather than added to CONFIRMATIONS: that table maps QSO columns, and this channel is backed by ADIF extras (APP_OPSLOG_QSL_RCVD, plus the older APP_OPSLOG_QSL_CARD_SENT for the sent side). Sent stays read-only — OpsLog stamps it when a card actually goes out, and a hand tick would record something that never happened.
This commit is contained in:
@@ -434,6 +434,10 @@ export function QSOEditModal({ qso, onSave, onDelete, onClose, countries = [], b
|
||||
// Saved with the normal Save via draft.extras.
|
||||
const OPSLOG_QSL_RCVD = 'APP_OPSLOG_QSL_RCVD';
|
||||
const qslReceived = !!String(draft.extras?.[OPSLOG_QSL_RCVD] ?? '').trim();
|
||||
// Sent side, for the confirmations table. Two key names because the marker was
|
||||
// renamed once and old QSOs still carry the first one — same test the Recent
|
||||
// QSOs "OpsLog QSL" column makes.
|
||||
const opslogQslSent = !!(draft.extras?.['APP_OPSLOG_QSL_SENT'] || draft.extras?.['APP_OPSLOG_QSL_CARD_SENT']);
|
||||
const toggleQslReceived = (on: boolean) => {
|
||||
// Reflect immediately in the draft (for the PSE/TNX indicator)…
|
||||
const next = { ...(draft.extras ?? {}) };
|
||||
@@ -617,18 +621,12 @@ export function QSOEditModal({ qso, onSave, onDelete, onClose, countries = [], b
|
||||
<div className="flex flex-col flex-1"><Label>Lat</Label><Input type="number" step="0.000001" value={draft.lat ?? ''} onChange={(e) => set('lat', numOrUndef(e.target.value) as any)} className="font-mono" /></div>
|
||||
<div className="flex flex-col flex-1"><Label>Lon</Label><Input type="number" step="0.000001" value={draft.lon ?? ''} onChange={(e) => set('lon', numOrUndef(e.target.value) as any)} className="font-mono" /></div>
|
||||
</div>
|
||||
{/* The OpsLog QSL marker used to sit here, under QSL Msg. It
|
||||
belongs with the other confirmation channels — see the QSL
|
||||
Info tab. */}
|
||||
<div>
|
||||
<Label>{t('qedit.qslMsg')}</Label>
|
||||
<Input value={draft.qsl_msg ?? ''} onChange={(e) => set('qsl_msg', e.target.value)} />
|
||||
<div className="mt-1 flex items-center gap-2">
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
||||
<Checkbox checked={qslReceived} onCheckedChange={(c) => toggleQslReceived(!!c)} />
|
||||
{t('qedit.qslReceived')}
|
||||
</label>
|
||||
<span className="text-[11px] font-mono px-1.5 py-0.5 rounded bg-muted text-muted-foreground" title={t('qedit.pseTnxHint')}>
|
||||
{qslReceived ? 'TNX' : 'PSE QSL'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div><Label>{t('qedit.qslVia')}</Label><Input value={draft.qsl_via ?? ''} onChange={(e) => set('qsl_via', e.target.value)} /></div>
|
||||
</div>
|
||||
@@ -696,6 +694,24 @@ export function QSOEditModal({ qso, onSave, onDelete, onClose, countries = [], b
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
{t('qedit.qslPanelHint')} <strong>{t('qedit.saveChanges')}</strong>.
|
||||
</p>
|
||||
|
||||
{/* OpsLog's own card channel. Not a CONFIRMATIONS entry: it
|
||||
is backed by ADIF extras, not by QSO columns, and its
|
||||
"received" flag writes immediately rather than on Save
|
||||
(a removed extras key would not survive the merge). The
|
||||
PSE/TNX stamp printed on the card is derived from it, so
|
||||
it is shown right here — that stamp is the whole reason
|
||||
the flag exists. */}
|
||||
<div className="border-t border-border/60 pt-3 space-y-1.5">
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
||||
<Checkbox checked={qslReceived} onCheckedChange={(c) => toggleQslReceived(!!c)} />
|
||||
{t('qedit.qslReceived')}
|
||||
<span className="text-[11px] font-mono px-1.5 py-0.5 rounded bg-muted text-muted-foreground" title={t('qedit.pseTnxHint')}>
|
||||
{qslReceived ? 'TNX' : 'PSE QSL'}
|
||||
</span>
|
||||
</label>
|
||||
<p className="text-[11px] text-muted-foreground">{t('qedit.pseTnxHint')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: live status grid for every channel.
|
||||
@@ -720,6 +736,17 @@ export function QSOEditModal({ qso, onSave, onDelete, onClose, countries = [], b
|
||||
<td className="w-24">{c.rcvd ? <StatusCell value={val(c.rcvd)} /> : <span className="block text-center text-[11px] text-muted-foreground">—</span>}</td>
|
||||
</tr>
|
||||
))}
|
||||
{/* OpsLog's own card, read from the ADIF extras rather
|
||||
than a QSO column — hence a hand-written row instead
|
||||
of a CONFIRMATIONS entry. "Sent" is stamped by OpsLog
|
||||
when the card actually goes out, so it stays
|
||||
read-only here: an operator ticking it by hand would
|
||||
be recording something that never happened. */}
|
||||
<tr className="text-xs">
|
||||
<td className="font-medium pr-3 py-0.5 whitespace-nowrap">{t('qedit.confOpsLog')}</td>
|
||||
<td className="w-24"><StatusCell value={opslogQslSent ? 'Y' : 'N'} /></td>
|
||||
<td className="w-24"><StatusCell value={qslReceived ? 'Y' : 'N'} /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user