feat(bandmap): draw the band plan of the operator's IARU region
The band maps carried one hard-coded table — Region 1's — so a US operator's 40 m stopped at 7200 with stations spotted at 7250 hanging past the top of the map, and the SSB wash started 25 kHz early. The region is a station-level fact stated once (Settings → General, portable pref); lib/bandplan owns the three tables and publishes changes to the open maps the way the distance unit reaches the grids. The tables stay deliberately coarse: a band map's wash is context, not a regulatory chart, so only the differences an operator notices are split out — Region 2's 80 m to 4000 and 40 m to 7300 (phone from 7125), Region 3's 80 m to 3900, the wider VHF/UHF allocations. National fine print does not belong in a background tint.
This commit is contained in:
@@ -81,6 +81,7 @@ import {
|
||||
import { cn } from '@/lib/utils';
|
||||
import { writeUiPref } from '@/lib/uiPref';
|
||||
import { setUseMiles } from '@/lib/units';
|
||||
import { iaruRegion, setIaruRegion, type IaruRegion } from '@/lib/bandplan';
|
||||
import { getDateFormat, setDateFormat, type DateFormat } from '@/lib/dateFormat';
|
||||
import { useI18n, FlagGB, FlagFR, type Lang } from '@/lib/i18n';
|
||||
import { useTheme, CONCRETE_THEMES, type ThemeChoice } from '@/lib/theme';
|
||||
@@ -1749,6 +1750,7 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
|
||||
const [lookupOnBlur, setLookupOnBlur] = useState(() => localStorage.getItem('opslog.lookupOnBlur') === '1');
|
||||
const [groupDigital, setGroupDigital] = useState(() => localStorage.getItem('opslog.groupDigitalSlots') === '1');
|
||||
const [milesUnit, setMilesUnit] = useState(() => localStorage.getItem('opslog.distanceMiles') === '1');
|
||||
const [region, setRegion] = useState<IaruRegion>(() => iaruRegion());
|
||||
const [clusterWorkedSameSlot, setClusterWorkedSameSlot] = useState(() => localStorage.getItem('opslog.clusterWorkedSameSlot') === '1');
|
||||
// Declared HERE and not in ClusterPanel: that renderer is called as a plain
|
||||
// function by the PANELS map, so it must stay hooks-free.
|
||||
@@ -7239,6 +7241,24 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
|
||||
<Checkbox checked={groupDigital} onCheckedChange={(c) => { const v = !!c; setGroupDigital(v); writeUiPref('opslog.groupDigitalSlots', v ? '1' : '0'); }} />
|
||||
{t('gen.groupDigital')} <span className="text-xs text-muted-foreground">{t('gen.groupDigitalHint')}</span>
|
||||
</label>
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
{/* The IARU region drives the band edges and mode segments the band
|
||||
maps draw — Region 2's 40 m runs to 7300, Region 1's stops at
|
||||
7200 — and nothing else: spots and logging are region-blind. */}
|
||||
<span>{t('gen.iaruRegion')}</span>
|
||||
<Select value={String(region)} onValueChange={(v) => {
|
||||
const r = (v === '2' ? 2 : v === '3' ? 3 : 1) as IaruRegion;
|
||||
setRegion(r); setIaruRegion(r);
|
||||
}}>
|
||||
<SelectTrigger className="h-8 w-64"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">{t('gen.iaruR1')}</SelectItem>
|
||||
<SelectItem value="2">{t('gen.iaruR2')}</SelectItem>
|
||||
<SelectItem value="3">{t('gen.iaruR3')}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<span className="text-xs text-muted-foreground">{t('gen.iaruHint')}</span>
|
||||
</div>
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
||||
{/* Distances are computed in km everywhere and converted at display
|
||||
time — see lib/units. Changing this repaints the columns that
|
||||
|
||||
Reference in New Issue
Block a user