fix(qsl): put the OpsLog card in the Manage Confirmation picker too
The previous commit added its row to the status table but left the picker listing only the column-backed channels, so the one channel you could actually tick was the one you could not select. Selecting it swaps the left panel for an OpsLog editor instead of the generic sent/received/date grid, which has no fields to bind to here: Sent is shown read-only (OpsLog stamps it when the card goes out), Received is the tick, and the PSE QSL / TNX indicator sits next to them since that stamp is what the flag is for.
This commit is contained in:
@@ -73,6 +73,11 @@ const CONF_LABEL_KEYS: Record<string, string> = {
|
|||||||
QSL: 'qedit.confQslPaper',
|
QSL: 'qedit.confQslPaper',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// OpsLog's own card. Kept out of CONFIRMATIONS on purpose — that list maps QSO
|
||||||
|
// columns and this channel is backed by ADIF extras — but it still belongs in
|
||||||
|
// the channel picker and the status table alongside the rest.
|
||||||
|
const OPSLOG_CONF = 'OPSLOG';
|
||||||
|
|
||||||
// Colour-coded status cell for the confirmation grid.
|
// Colour-coded status cell for the confirmation grid.
|
||||||
function StatusCell({ value }: { value?: string }) {
|
function StatusCell({ value }: { value?: string }) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -675,43 +680,69 @@ export function QSOEditModal({ qso, onSave, onDelete, onClose, countries = [], b
|
|||||||
<Label>{t('qedit.manageConf')}</Label>
|
<Label>{t('qedit.manageConf')}</Label>
|
||||||
<Select value={confSel} onValueChange={setConfSel}>
|
<Select value={confSel} onValueChange={setConfSel}>
|
||||||
<SelectTrigger><SelectValue /></SelectTrigger>
|
<SelectTrigger><SelectValue /></SelectTrigger>
|
||||||
<SelectContent>{CONFIRMATIONS.map((c) => <SelectItem key={c.key} value={c.key}>{CONF_LABEL_KEYS[c.key] ? t(CONF_LABEL_KEYS[c.key]) : c.label}</SelectItem>)}</SelectContent>
|
<SelectContent>
|
||||||
|
{CONFIRMATIONS.map((c) => <SelectItem key={c.key} value={c.key}>{CONF_LABEL_KEYS[c.key] ? t(CONF_LABEL_KEYS[c.key]) : c.label}</SelectItem>)}
|
||||||
|
{/* Listed here but NOT in CONFIRMATIONS: that table maps
|
||||||
|
QSO columns, and this channel lives in the ADIF
|
||||||
|
extras. It gets its own editor below rather than the
|
||||||
|
generic sent/received/date grid, which has no field
|
||||||
|
to bind to. */}
|
||||||
|
<SelectItem value={OPSLOG_CONF}>{t('qedit.confOpsLog')}</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-3">
|
|
||||||
<div><Label>{t('qedit.sent')}</Label><QslSelect value={val(def.sent)} onChange={(v) => put(def.sent, v)} /></div>
|
|
||||||
<div><Label>{t('qedit.received')}</Label>
|
|
||||||
{def.rcvd
|
|
||||||
? <QslSelect value={val(def.rcvd)} onChange={(v) => put(def.rcvd, v)} />
|
|
||||||
: <Input disabled value="—" />}
|
|
||||||
</div>
|
|
||||||
<div><Label>{t('qedit.dateSent')}</Label><AdifDateInput value={val(def.sentDate)} onChange={(v) => put(def.sentDate, v)} /></div>
|
|
||||||
<div><Label>{t('qedit.dateReceived')}</Label><AdifDateInput value={val(def.rcvdDate)} onChange={(v) => put(def.rcvdDate, v)} disabled={!def.rcvdDate} /></div>
|
|
||||||
{def.via && (
|
|
||||||
<div className="col-span-2"><Label>{t('qedit.via')}</Label><Input value={val(def.via)} onChange={(e) => put(def.via, e.target.value)} placeholder={t('qedit.viaPlaceholder')} /></div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<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
|
{confSel === OPSLOG_CONF ? (
|
||||||
is backed by ADIF extras, not by QSO columns, and its
|
/* OpsLog's own card. "Sent" is stamped when the card
|
||||||
"received" flag writes immediately rather than on Save
|
actually goes out, so it is shown, not offered: ticking
|
||||||
(a removed extras key would not survive the merge). The
|
it by hand would record something that never happened.
|
||||||
PSE/TNX stamp printed on the card is derived from it, so
|
"Received" drives the PSE/TNX stamp printed on the card,
|
||||||
it is shown right here — that stamp is the whole reason
|
which is the whole reason the flag exists — hence the
|
||||||
the flag exists. */}
|
live indicator next to it. It writes immediately rather
|
||||||
<div className="border-t border-border/60 pt-3 space-y-1.5">
|
than on Save, because clearing an extras key would not
|
||||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
survive the merge Save does. */
|
||||||
<Checkbox checked={qslReceived} onCheckedChange={(c) => toggleQslReceived(!!c)} />
|
<div className="space-y-3">
|
||||||
{t('qedit.qslReceived')}
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<span className="text-[11px] font-mono px-1.5 py-0.5 rounded bg-muted text-muted-foreground" title={t('qedit.pseTnxHint')}>
|
<div>
|
||||||
{qslReceived ? 'TNX' : 'PSE QSL'}
|
<Label>{t('qedit.sent')}</Label>
|
||||||
</span>
|
<Input disabled value={opslogQslSent ? t('qedit.qslYes') : t('qedit.qslNo')} />
|
||||||
</label>
|
</div>
|
||||||
<p className="text-[11px] text-muted-foreground">{t('qedit.pseTnxHint')}</p>
|
<div>
|
||||||
</div>
|
<Label>{t('qedit.received')}</Label>
|
||||||
|
<label className="flex h-9 items-center gap-2 text-sm cursor-pointer">
|
||||||
|
<Checkbox checked={qslReceived} onCheckedChange={(c) => toggleQslReceived(!!c)} />
|
||||||
|
{t('qedit.qslReceived')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="text-[11px] font-mono px-1.5 py-0.5 rounded bg-muted text-muted-foreground">
|
||||||
|
{qslReceived ? 'TNX' : 'PSE QSL'}
|
||||||
|
</span>
|
||||||
|
<span className="text-[11px] text-muted-foreground">{t('qedit.pseTnxHint')}</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-[11px] text-muted-foreground">{t('qedit.opslogSentHint')}</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="grid grid-cols-2 gap-3">
|
||||||
|
<div><Label>{t('qedit.sent')}</Label><QslSelect value={val(def.sent)} onChange={(v) => put(def.sent, v)} /></div>
|
||||||
|
<div><Label>{t('qedit.received')}</Label>
|
||||||
|
{def.rcvd
|
||||||
|
? <QslSelect value={val(def.rcvd)} onChange={(v) => put(def.rcvd, v)} />
|
||||||
|
: <Input disabled value="—" />}
|
||||||
|
</div>
|
||||||
|
<div><Label>{t('qedit.dateSent')}</Label><AdifDateInput value={val(def.sentDate)} onChange={(v) => put(def.sentDate, v)} /></div>
|
||||||
|
<div><Label>{t('qedit.dateReceived')}</Label><AdifDateInput value={val(def.rcvdDate)} onChange={(v) => put(def.rcvdDate, v)} disabled={!def.rcvdDate} /></div>
|
||||||
|
{def.via && (
|
||||||
|
<div className="col-span-2"><Label>{t('qedit.via')}</Label><Input value={val(def.via)} onChange={(e) => put(def.via, e.target.value)} placeholder={t('qedit.viaPlaceholder')} /></div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<p className="text-[11px] text-muted-foreground">
|
||||||
|
{t('qedit.qslPanelHint')} <strong>{t('qedit.saveChanges')}</strong>.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right: live status grid for every channel.
|
{/* Right: live status grid for every channel.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user