fix: relocated Lotw and Alerts

This commit is contained in:
2026-07-16 22:56:21 +02:00
parent dcf006905c
commit 46e3619a38
+16 -15
View File
@@ -2885,7 +2885,7 @@ export default function App() {
: d < 30 ? 'border-warning text-warning bg-warning/15' : d < 30 ? 'border-warning text-warning bg-warning/15'
: 'border-danger text-danger bg-danger/15'; : 'border-danger text-danger bg-danger/15';
return ( return (
<div className="self-end shrink-0" title={t('lotw.userTip', { date: lotwInfo.last_upload || '?', days: d })}> <div className="shrink-0" title={t('lotw.userTip', { date: lotwInfo.last_upload || '?', days: d })}>
<span className={cn('inline-flex items-center rounded-md border px-1.5 py-1 text-[9px] font-extrabold tracking-wide leading-none', cls)}> <span className={cn('inline-flex items-center rounded-md border px-1.5 py-1 text-[9px] font-extrabold tracking-wide leading-none', cls)}>
LoTW LoTW
</span> </span>
@@ -2901,7 +2901,7 @@ export default function App() {
// worked-before check doesn't include these, and see what's waiting. // worked-before check doesn't include these, and see what's waiting.
const offlinePendingCount = offlineStatus.pending ?? 0; const offlinePendingCount = offlineStatus.pending ?? 0;
const offlineBlock = offlinePendingCount === 0 ? null : ( const offlineBlock = offlinePendingCount === 0 ? null : (
<div className="relative self-end mb-0.5 shrink-0"> <div className="relative shrink-0">
<button type="button" onClick={() => { setPendingOpen((o) => !o); GetPendingQSOs().then((r: any) => setPendingList((r ?? []) as any[])).catch(() => {}); }} <button type="button" onClick={() => { setPendingOpen((o) => !o); GetPendingQSOs().then((r: any) => setPendingList((r ?? []) as any[])).catch(() => {}); }}
title={t('offline.tip', { n: offlinePendingCount })} title={t('offline.tip', { n: offlinePendingCount })}
className="relative inline-flex h-8 items-center gap-1.5 rounded-full border border-danger bg-danger/15 px-2.5 text-danger transition-colors hover:bg-danger/25"> className="relative inline-flex h-8 items-center gap-1.5 rounded-full border border-danger bg-danger/15 px-2.5 text-danger transition-colors hover:bg-danger/25">
@@ -2954,7 +2954,7 @@ export default function App() {
const hasAlerts = recentAlerts.length > 0; const hasAlerts = recentAlerts.length > 0;
// Only show the bell when there are pending alerts — hidden otherwise. // Only show the bell when there are pending alerts — hidden otherwise.
const alertLedBlock = !hasAlerts ? null : ( const alertLedBlock = !hasAlerts ? null : (
<div className="relative self-end mb-0.5 shrink-0"> <div className="relative shrink-0">
<button type="button" onClick={() => setAlertsPanelOpen((o) => !o)} <button type="button" onClick={() => setAlertsPanelOpen((o) => !o)}
title={hasAlerts ? t('alert.pending', { n: recentAlerts.length }) : t('alert.noneShort')} title={hasAlerts ? t('alert.pending', { n: recentAlerts.length }) : t('alert.noneShort')}
className={cn('relative inline-flex size-8 items-center justify-center rounded-full border transition-colors', className={cn('relative inline-flex size-8 items-center justify-center rounded-full border transition-colors',
@@ -3109,19 +3109,19 @@ export default function App() {
const logButtons = ( const logButtons = (
<div className="flex flex-col"> <div className="flex flex-col">
<Label className="mb-1 h-3.5">&nbsp;</Label> <Label className="mb-1 h-3.5">&nbsp;</Label>
<div className="flex gap-2"> <div className="flex gap-1.5">
{clusterServerStatuses.some((s) => s.state === 'connected') && ( {clusterServerStatuses.some((s) => s.state === 'connected') && (
<Button type="button" variant="outline" onClick={() => setShowSpotModal(true)} className="h-8" title="Send a DX spot to the master cluster"> <Button type="button" size="sm" variant="outline" onClick={() => setShowSpotModal(true)} className="h-8 px-2.5 text-xs" title="Send a DX spot to the master cluster">
<Satellite className="size-3.5" /> <Satellite className="size-3.5" />
{t('btn.spot')} {t('btn.spot')}
</Button> </Button>
)} )}
<Button type="button" variant="outline" onClick={() => { resetEntry(); callsignRef.current?.focus(); }} className="h-8" <Button type="button" size="sm" variant="outline" onClick={() => { resetEntry(); callsignRef.current?.focus(); }} className="h-8 px-2.5 text-xs"
title="Clear the QSO entry (always — unlike Esc which may be reserved for the CW keyer)"> title="Clear the QSO entry (always — unlike Esc which may be reserved for the CW keyer)">
<Eraser className="size-3.5" /> <Eraser className="size-3.5" />
{t('btn.clear')} {t('btn.clear')}
</Button> </Button>
<Button onClick={save} disabled={saving} className="h-8"> <Button size="sm" onClick={save} disabled={saving} className="h-8 px-3 text-xs">
<Send className="size-3.5" /> <Send className="size-3.5" />
{saving ? '…' : t('btn.logQso')} {saving ? '…' : t('btn.logQso')}
</Button> </Button>
@@ -3910,13 +3910,6 @@ export default function App() {
</div> </div>
{qthBlock} {qthBlock}
{gridBlock} {gridBlock}
{/* LoTW badge, offline outbox and the spot-alert LED grouped at the
right edge, so the alert always has a clear spot. */}
<div className="ml-auto flex items-end gap-2 shrink-0">
{lotwBlock}
{offlineBlock}
{alertLedBlock}
</div>
</div> </div>
{/* Row 3: tight left detail column (Band/Mode/Country) and {/* Row 3: tight left detail column (Band/Mode/Country) and
@@ -3933,11 +3926,19 @@ export default function App() {
</div> </div>
</div> </div>
{/* Bottom: TX freq, RX freq, RX band — plus the action buttons. */} {/* Bottom: TX freq, RX freq, RX band then the alert LED + LoTW badge
(vertically centred on the input row), then the action buttons. */}
<div className="flex gap-2 items-end"> <div className="flex gap-2 items-end">
{freqBlock} {freqBlock}
{rxFreqBlock} {rxFreqBlock}
{bandRxBlock} {bandRxBlock}
{(alertLedBlock || lotwBlock || offlineBlock) && (
<div className="flex items-center gap-2 h-9 self-end">
{alertLedBlock}
{lotwBlock}
{offlineBlock}
</div>
)}
<div className="ml-auto">{logButtons}</div> <div className="ml-auto">{logButtons}</div>
</div> </div>
</> </>