feat(bandmap,dxped): drop the ctrl+wheel zoom, badge the news

ctrl+wheel is the WINDOW zoom everywhere else in OpsLog, and one gesture
that resizes the whole app over one panel and one band map over another
is a gesture nobody can trust. The + and - buttons keep the zoom, and
the footer hint stops advertising what is gone.

The DX-World headlines now carry a chase badge like the announcements —
but ENTITY-LEVEL only. A headline names no band, and asking the slot
question without one answers 'new band' for every entity ever worked:
the one mistake that costs a QSO. So the news says NEW DXCC or worked,
and the sharper verdicts stay where the bands and modes are known.
This commit is contained in:
2026-08-31 18:57:44 +02:00
parent 4a017f6290
commit 2b6f1ba9d7
7 changed files with 119 additions and 53 deletions
@@ -26,6 +26,10 @@ type DXped = {
type News = {
title: string; link: string; pub_date: string; excerpt: string;
creator: string; image_url: string; tag: string; calls?: string[];
// Entity-level only — a headline names no band, so the backend answers
// 'new' or 'worked' and nothing finer.
status_chase?: string;
unconfirmed?: boolean;
};
// One badge per expedition, the strongest verdict winning — the same palette
@@ -180,6 +184,7 @@ export function DXpeditionsPanel() {
)}
{news.map((n, i) => {
const newsCalls = n.calls ?? [];
const newsBadge = CHASE_BADGE[n.status_chase ?? ''];
const newsAllWatched = newsCalls.length > 0 && newsCalls.every((c) => watched.has(c.toUpperCase()));
return (
<article key={`${n.link}-${i}`} className="rounded-md border border-border bg-muted/20 p-2">
@@ -193,6 +198,15 @@ export function DXpeditionsPanel() {
{n.tag && (
<span className="px-1 py-px rounded text-[9px] font-bold uppercase bg-primary/15 text-primary">{n.tag}</span>
)}
{newsBadge && (
<span className="px-1 py-px rounded text-[9px] font-bold uppercase tracking-wide border shrink-0"
title={n.unconfirmed ? t('dec.unconfTip') : undefined}
style={n.unconfirmed
? { color: newsBadge.colour, borderColor: newsBadge.colour, borderStyle: 'dashed', opacity: 0.6 }
: { color: newsBadge.colour, borderColor: newsBadge.colour }}>
{t(newsBadge.label)}
</span>
)}
<button type="button" onClick={() => n.link && BrowserOpenURL(n.link)}
className="text-xs font-medium text-left hover:underline">{n.title}</button>
</div>