|
|
@@ -1323,7 +1323,12 @@ export default function App() {
|
|
|
|
// Status filter chips. Empty set = show every status (including
|
|
|
|
// Status filter chips. Empty set = show every status (including
|
|
|
|
// already-worked). Otherwise only matching spots pass.
|
|
|
|
// already-worked). Otherwise only matching spots pass.
|
|
|
|
type SpotStatusKey = 'new' | 'new-band' | 'new-mode' | 'new-slot' | 'worked';
|
|
|
|
type SpotStatusKey = 'new' | 'new-band' | 'new-mode' | 'new-slot' | 'worked';
|
|
|
|
const [clusterStatusFilter, setClusterStatusFilter] = useState<Set<SpotStatusKey>>(() => lsSet<SpotStatusKey>('opslog.clusterStatusFilter'));
|
|
|
|
// What the cluster can be FILTERED on. A superset of the entity status: a new
|
|
|
|
|
|
|
|
// county or a new park is not a DXCC state, it is another dimension of the
|
|
|
|
|
|
|
|
// same spot — which is why the grid shows them as separate badges. Filtering
|
|
|
|
|
|
|
|
// is an OR across all of them, as it already was for a worked callsign.
|
|
|
|
|
|
|
|
type SpotFilterKey = SpotStatusKey | 'new-pota' | 'new-county';
|
|
|
|
|
|
|
|
const [clusterStatusFilter, setClusterStatusFilter] = useState<Set<SpotFilterKey>>(() => lsSet<SpotFilterKey>('opslog.clusterStatusFilter'));
|
|
|
|
// Mode filter chips. Empty set = show every mode. Categories map the
|
|
|
|
// Mode filter chips. Empty set = show every mode. Categories map the
|
|
|
|
// inferred per-spot mode onto SSB (phone) / CW / DATA (digital).
|
|
|
|
// inferred per-spot mode onto SSB (phone) / CW / DATA (digital).
|
|
|
|
type SpotModeCat = 'SSB' | 'CW' | 'DATA';
|
|
|
|
type SpotModeCat = 'SSB' | 'CW' | 'DATA';
|
|
|
@@ -4269,7 +4274,10 @@ export default function App() {
|
|
|
|
// entity status is still new-band/new-slot (the grid flags it WKD CALL),
|
|
|
|
// entity status is still new-band/new-slot (the grid flags it WKD CALL),
|
|
|
|
// matching the "Hide worked" toggle. Additive: it still matches its own
|
|
|
|
// matching the "Hide worked" toggle. Additive: it still matches its own
|
|
|
|
// entity status too, so it stays visible under NEW BAND / NEW SLOT.
|
|
|
|
// entity status too, so it stays visible under NEW BAND / NEW SLOT.
|
|
|
|
const matches = clusterStatusFilter.has(st) || (!!e?.worked_call && clusterStatusFilter.has('worked'));
|
|
|
|
const matches = clusterStatusFilter.has(st)
|
|
|
|
|
|
|
|
|| (!!e?.worked_call && clusterStatusFilter.has('worked'))
|
|
|
|
|
|
|
|
|| (!!e?.new_pota && clusterStatusFilter.has('new-pota'))
|
|
|
|
|
|
|
|
|| (!!e?.new_county && clusterStatusFilter.has('new-county'));
|
|
|
|
if (!matches) return false;
|
|
|
|
if (!matches) return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (clusterHideWorked) {
|
|
|
|
if (clusterHideWorked) {
|
|
|
@@ -4381,10 +4389,14 @@ export default function App() {
|
|
|
|
<div className="text-[10px] uppercase tracking-wider text-muted-foreground mb-1">Status</div>
|
|
|
|
<div className="text-[10px] uppercase tracking-wider text-muted-foreground mb-1">Status</div>
|
|
|
|
<div className="flex flex-wrap gap-1">
|
|
|
|
<div className="flex flex-wrap gap-1">
|
|
|
|
{([
|
|
|
|
{([
|
|
|
|
{ k: 'new' as SpotStatusKey, label: 'NEW', cls: 'bg-danger-muted text-danger-muted-foreground border-danger-border' },
|
|
|
|
{ k: 'new' as SpotFilterKey, label: 'NEW', cls: 'bg-danger-muted text-danger-muted-foreground border-danger-border' },
|
|
|
|
{ k: 'new-band' as SpotStatusKey, label: 'NEW BAND', cls: 'bg-warning-muted text-warning-muted-foreground border-warning-border' },
|
|
|
|
{ k: 'new-band' as SpotFilterKey, label: 'NEW BAND', cls: 'bg-warning-muted text-warning-muted-foreground border-warning-border' },
|
|
|
|
{ k: 'new-mode' as SpotStatusKey, label: 'NEW MODE', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' },
|
|
|
|
{ k: 'new-mode' as SpotFilterKey, label: 'NEW MODE', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' },
|
|
|
|
{ k: 'new-slot' as SpotStatusKey, label: 'NEW SLOT', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' },
|
|
|
|
{ k: 'new-slot' as SpotFilterKey, label: 'NEW SLOT', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' },
|
|
|
|
|
|
|
|
// Same colours as the badges in the grid — a filter that does not
|
|
|
|
|
|
|
|
// look like what it selects has to be learned twice.
|
|
|
|
|
|
|
|
{ k: 'new-pota' as SpotFilterKey, label: 'NEW POTA', cls: 'bg-success-muted text-success-muted-foreground border-success-border' },
|
|
|
|
|
|
|
|
{ k: 'new-county' as SpotFilterKey, label: 'NEW COUNTY', cls: 'bg-info-muted text-info-muted-foreground border-info-border' },
|
|
|
|
// (no WORKED chip — use the "Hide worked" checkbox to drop dupes.)
|
|
|
|
// (no WORKED chip — use the "Hide worked" checkbox to drop dupes.)
|
|
|
|
]).map((s) => {
|
|
|
|
]).map((s) => {
|
|
|
|
const on = clusterStatusFilter.has(s.k);
|
|
|
|
const on = clusterStatusFilter.has(s.k);
|
|
|
|