Qsl
This commit is contained in:
+39
-5
@@ -41,6 +41,7 @@ import { Menubar, type Menu } from '@/components/Menubar';
|
||||
import { QSLManagerPanel } from '@/components/QSLManagerModal';
|
||||
import { QslDesignerModal } from '@/components/qsl/QslDesignerModal';
|
||||
import { SendEQSLModal } from '@/components/qsl/SendEQSLModal';
|
||||
import { AutoEQSL } from '@/components/qsl/AutoEQSL';
|
||||
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||
import { SettingsModal } from '@/components/SettingsModal';
|
||||
import { QSOEditModal } from '@/components/QSOEditModal';
|
||||
@@ -631,6 +632,19 @@ export default function App() {
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
// Single band map docked beside the table (toggled by the toolbar button,
|
||||
// visible across tabs). Independent of the multi-band "Band Map" tab.
|
||||
const [showBandMap, setShowBandMap] = useState(false);
|
||||
const [bandMapSide, setBandMapSide] = useState<'left' | 'right'>(
|
||||
() => (localStorage.getItem('bandmap.side') === 'left' ? 'left' : 'right'),
|
||||
);
|
||||
const toggleBandMapSide = useCallback(() => {
|
||||
setBandMapSide((s) => {
|
||||
const next = s === 'right' ? 'left' : 'right';
|
||||
writeUiPref('bandmap.side', next);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
type SortKey = 'time' | 'call' | 'freq' | 'band' | 'mode' | 'spotter' | 'source';
|
||||
const [clusterSort, setClusterSort] = useState<{ key: SortKey; dir: 'asc' | 'desc' }>({ key: 'time', dir: 'desc' });
|
||||
// Cached per-call slot status: "new" | "new-band" | "new-slot" | "worked".
|
||||
@@ -2256,10 +2270,10 @@ export default function App() {
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant={activeTab === 'bandmap' ? 'default' : 'outline'}
|
||||
variant={showBandMap ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
onClick={() => setActiveTab('bandmap')}
|
||||
title="Open the Band Map tab (several bands side by side)"
|
||||
onClick={() => setShowBandMap((v) => !v)}
|
||||
title="Toggle a single band map docked on the side (use the Band Map tab for several at once)"
|
||||
className="h-8"
|
||||
>
|
||||
Band map
|
||||
@@ -2376,7 +2390,7 @@ export default function App() {
|
||||
className={cn('bg-card shadow-sm border-border',
|
||||
compact
|
||||
? 'flex gap-2 items-end flex-nowrap px-3 py-2 border-b shrink-0 overflow-hidden'
|
||||
: 'flex flex-col gap-1.5 px-2.5 py-1.5 flex-1 min-w-[520px] max-w-[760px] border rounded-lg [&_label]:text-[11px] [&_label]:mb-0.5 [&_label]:h-3')}
|
||||
: 'flex flex-col gap-1.5 px-2.5 py-1.5 flex-1 min-w-[520px] max-w-[660px] border rounded-lg [&_label]:text-[11px] [&_label]:mb-0.5 [&_label]:h-3')}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' && (e.target as HTMLElement).tagName === 'INPUT') {
|
||||
e.preventDefault();
|
||||
@@ -2552,7 +2566,8 @@ export default function App() {
|
||||
|
||||
{/* ===== LOWER: tabbed table / cluster / band map ===== */}
|
||||
{compact ? null : <>
|
||||
<div className="grid gap-2.5 p-2.5 flex-1 min-h-0 grid-rows-[minmax(0,1fr)] grid-cols-[1fr]">
|
||||
<div className={cn('grid gap-2.5 p-2.5 flex-1 min-h-0 grid-rows-[minmax(0,1fr)]',
|
||||
showBandMap ? (bandMapSide === 'left' ? 'grid-cols-[300px_1fr]' : 'grid-cols-[1fr_300px]') : 'grid-cols-[1fr]')}>
|
||||
<section className="bg-card border border-border rounded-lg shadow-sm flex flex-col min-h-0 overflow-hidden">
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex flex-col min-h-0 flex-1">
|
||||
<TabsList className="px-3 shrink-0">
|
||||
@@ -3081,6 +3096,21 @@ export default function App() {
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</section>
|
||||
|
||||
{showBandMap && (
|
||||
<div className={cn('bg-card border border-border rounded-lg shadow-sm flex flex-col min-h-0 overflow-hidden', bandMapSide === 'left' && 'order-first')}>
|
||||
<BandMap
|
||||
side={bandMapSide}
|
||||
onToggleSide={toggleBandMapSide}
|
||||
band={band}
|
||||
spots={spots.filter((s) => s.band === band)}
|
||||
spotStatus={spotStatus}
|
||||
currentFreqHz={band && freqMhz ? Math.round(parseFloat(freqMhz) * 1_000_000) : 0}
|
||||
onSpotClick={handleSpotClick}
|
||||
onClose={() => setShowBandMap(false)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>}
|
||||
|
||||
@@ -3173,6 +3203,10 @@ export default function App() {
|
||||
/>
|
||||
)}
|
||||
|
||||
<AutoEQSL
|
||||
onSent={(call) => showToast(`eQSL sent to ${call}`)}
|
||||
onError={(msg) => showToast(msg)}
|
||||
/>
|
||||
<QslDesignerModal open={qslDesignerOpen} onClose={() => setQslDesignerOpen(false)} />
|
||||
<SendEQSLModal
|
||||
open={eqslQsoId !== null}
|
||||
|
||||
Reference in New Issue
Block a user