Qsl
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
GetClublogCtyInfo, SetClublogCtyEnabled, DownloadClublogCty,
|
||||
GetSecretStatus, SetPassphrase, RemovePassphrase,
|
||||
GetEmailSettings, SaveEmailSettings, TestEmail,
|
||||
QSLGetEmailTemplates, QSLSaveEmailTemplates,
|
||||
GetDVKMessages, SetDVKLabel, DVKStartRecord, DVKStopRecord, DVKPreview, DVKStop, GetDVKStatus,
|
||||
ListClusterServers, SaveClusterServer, DeleteClusterServer,
|
||||
GetClusterAutoConnect, SetClusterAutoConnect,
|
||||
@@ -462,6 +463,10 @@ export function SettingsModal({ onClose, onSaved, initialSection }: Props) {
|
||||
});
|
||||
const [emailMsg, setEmailMsg] = useState('');
|
||||
const setEmailField = (patch: Partial<EmailCfg>) => setEmailCfg((s) => ({ ...s, ...patch }));
|
||||
// eQSL card e-mail (subject/body templates + auto-send on log).
|
||||
type EQSLCfg = { subject: string; body: string; auto_send: boolean };
|
||||
const [eqslCfg, setEqslCfg] = useState<EQSLCfg>({ subject: '', body: '', auto_send: false });
|
||||
const setEqslField = (patch: Partial<EQSLCfg>) => setEqslCfg((s) => ({ ...s, ...patch }));
|
||||
// ClubLog Country File (cty.xml) exception status.
|
||||
type ClubInfo = { enabled: boolean; loaded: boolean; date: string; count: number };
|
||||
const [clubInfo, setClubInfo] = useState<ClubInfo>({ enabled: false, loaded: false, date: '', count: 0 });
|
||||
@@ -632,6 +637,7 @@ export function SettingsModal({ onClose, onSaved, initialSection }: Props) {
|
||||
try { setWkPorts((await ListSerialPorts() ?? []) as string[]); } catch {}
|
||||
try { setAudioCfg(await GetAudioSettings() as any); } catch {}
|
||||
try { setEmailCfg(await GetEmailSettings() as any); } catch {}
|
||||
try { setEqslCfg(await QSLGetEmailTemplates() as any); } catch {}
|
||||
reloadAudioDevices();
|
||||
reloadDvk();
|
||||
} catch (e: any) {
|
||||
@@ -791,6 +797,7 @@ export function SettingsModal({ onClose, onSaved, initialSection }: Props) {
|
||||
await SaveWinkeyerSettings(wk as any);
|
||||
await SaveAudioSettings(audioCfg as any);
|
||||
await SaveEmailSettings(emailCfg as any);
|
||||
await QSLSaveEmailTemplates(eqslCfg as any);
|
||||
await SaveBackupSettings(backupCfg as any);
|
||||
await SaveQSLDefaults(qslDefaults as any);
|
||||
await SaveExternalServices(extSvc as any);
|
||||
@@ -860,16 +867,16 @@ export function SettingsModal({ onClose, onSaved, initialSection }: Props) {
|
||||
<Input className="font-mono uppercase" value={p.operator ?? ''} onChange={(e) => updateActive({ operator: e.target.value })} placeholder="F4XYZ" />
|
||||
<div className="text-[10px] text-muted-foreground">Who's at the radio (ADIF OPERATOR).</div>
|
||||
</div>
|
||||
<div className="space-y-1 col-span-2">
|
||||
<Label>Operator name</Label>
|
||||
<Input className="max-w-xs" value={p.op_name ?? ''} onChange={(e) => updateActive({ op_name: e.target.value })} placeholder="e.g. Greg" />
|
||||
<div className="text-[10px] text-muted-foreground">Your first name — used as the signature on QSL cards.</div>
|
||||
</div>
|
||||
<div className="space-y-1 col-span-2">
|
||||
<Label>Owner callsign</Label>
|
||||
<Input className="font-mono uppercase max-w-xs" value={p.owner_callsign ?? ''} onChange={(e) => updateActive({ owner_callsign: e.target.value })} placeholder="(leave blank if same as station)" />
|
||||
<div className="text-[10px] text-muted-foreground">Legal station owner — only differs at club stations or remote setups (ADIF STATION_OWNER).</div>
|
||||
</div>
|
||||
<div className="space-y-1 col-span-2">
|
||||
<Label>Operator name</Label>
|
||||
<Input className="max-w-xs" value={p.op_name ?? ''} onChange={(e) => updateActive({ op_name: e.target.value })} placeholder="e.g. Greg" />
|
||||
<div className="text-[10px] text-muted-foreground">Your first name — used as the signature on QSL cards.</div>
|
||||
</div>
|
||||
<div className="col-span-2 text-[10px] text-muted-foreground uppercase tracking-wider mt-1">
|
||||
Auto-filled from the callsign — editable (stamped as MY_* on each QSO)
|
||||
</div>
|
||||
@@ -3077,6 +3084,24 @@ export function SettingsModal({ onClose, onSaved, initialSection }: Props) {
|
||||
</Button>
|
||||
<span className="text-[11px] text-muted-foreground">{emailMsg}</span>
|
||||
</div>
|
||||
|
||||
<div className="pt-2 mt-2 border-t border-border space-y-2">
|
||||
<Label className="text-sm font-semibold">eQSL card e-mail</Label>
|
||||
<div className="text-[11px] text-muted-foreground">
|
||||
Message sent with the QSL card. Variables: {'{CALL}'} {'{DATE}'} {'{BAND}'} {'{MODE}'} {'{MYCALL}'}.
|
||||
</div>
|
||||
<Input className="h-8" placeholder="Subject" value={eqslCfg.subject}
|
||||
onChange={(e) => setEqslField({ subject: e.target.value })} />
|
||||
<Textarea rows={3} className="text-sm" placeholder="Body" value={eqslCfg.body}
|
||||
onChange={(e) => setEqslField({ body: e.target.value })} />
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
||||
<Checkbox checked={eqslCfg.auto_send} onCheckedChange={(c) => setEqslField({ auto_send: !!c })} />
|
||||
Auto-send eQSL when a QSO is logged
|
||||
</label>
|
||||
<div className="text-[11px] text-muted-foreground">
|
||||
Sends automatically only when the contact has an e-mail address and a default QSL template exists.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user