diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index fbba91d..d12043d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -817,11 +817,11 @@ export default function App() { // map ("map1"), the locator street map ("map2"), the cluster grid or the // worked-before grid. Per-profile (stored via SetUIPref → profile-prefixed), // so it's loaded async on mount and re-read on profile:changed below. - type MainPaneKind = 'map1' | 'map2' | 'cluster' | 'worked' | 'flex'; + type MainPaneKind = 'map1' | 'map2' | 'cluster' | 'worked' | 'flex' | 'recent'; const [mainPaneLeft, setMainPaneLeft] = useState('map1'); const [mainPaneRight, setMainPaneRight] = useState('map2'); const loadMainPanes = useCallback(async () => { - const valid = (v: string): v is MainPaneKind => v === 'map1' || v === 'map2' || v === 'cluster' || v === 'worked' || v === 'flex'; + const valid = (v: string): v is MainPaneKind => v === 'map1' || v === 'map2' || v === 'cluster' || v === 'worked' || v === 'flex' || v === 'recent'; const [l, r] = await Promise.all([ GetUIPref('mainPaneLeft').catch(() => ''), GetUIPref('mainPaneRight').catch(() => ''), @@ -2837,6 +2837,28 @@ export default function App() { ); + case 'recent': + return ( +
+ openEdit(q.id as number)} + onUpdateFromCty={bulkUpdateFromCty} + onUpdateFromQRZ={bulkUpdateFromQRZ} + onUpdateFromClublog={bulkUpdateFromClublog} + onSendTo={bulkSendTo} + onSendRecording={bulkSendRecording} + onSendEQSL={(ids) => setEqslQsoId(ids[0] ?? null)} + onBulkEdit={openBulkEdit} + onExportSelected={exportSelectedADIF} + onExportFiltered={exportFilteredADIF} + onDelete={(ids) => setDeletingIds(ids)} + onRowSelected={(ids) => { setSelectedIds(ids); setSelectedId(ids[0] ?? null); }} + /> +
+ ); } }; diff --git a/frontend/src/components/SettingsModal.tsx b/frontend/src/components/SettingsModal.tsx index 24ecea6..28c103f 100644 --- a/frontend/src/components/SettingsModal.tsx +++ b/frontend/src/components/SettingsModal.tsx @@ -485,14 +485,16 @@ const MAIN_PANE_OPTIONS: { value: string; label: string }[] = [ { value: 'map2', label: 'Map — locator (street)' }, { value: 'cluster', label: 'Cluster spots' }, { value: 'worked', label: 'Worked before' }, + { value: 'recent', label: 'Recent QSOs' }, ]; function MainViewPanes({ onChanged, flexAvailable }: { onChanged?: (side: 'left' | 'right', value: string) => void; flexAvailable?: boolean }) { const [left, setLeft] = useState('map1'); const [right, setRight] = useState('map2'); - // FlexRadio is only offered when the CAT backend is a Flex. - const options = flexAvailable + // FlexRadio is only offered when the CAT backend is a Flex. Sorted A→Z. + const options = (flexAvailable ? [...MAIN_PANE_OPTIONS, { value: 'flex', label: 'FlexRadio controls' }] - : MAIN_PANE_OPTIONS; + : [...MAIN_PANE_OPTIONS] + ).sort((a, b) => a.label.localeCompare(b.label)); useEffect(() => { const valid = (v: string) => v === 'flex' || MAIN_PANE_OPTIONS.some((o) => o.value === v); Promise.all([GetUIPref('mainPaneLeft').catch(() => ''), GetUIPref('mainPaneRight').catch(() => '')])