feat(bandmap): show new POTA, new county and worked-callsign
The band map coloured only the entity status and dropped the other three markers on the floor — not for want of data: they were already in the status entry it receives, the local type simply never declared them, so a new park on an entity you have worked was indistinguishable from any other worked spot. Colours are the DX-cluster list's, taken from it rather than chosen: --info for a worked callsign, --success for a new county and a new park. The same fact must not be blue in one panel and green in the next. They STACK, they do not replace. These markers are orthogonal to the entity status — worked entity plus new park is an ordinary combination — and the cluster list already spells them out side by side rather than letting one win. So the pill keeps the status colour and the markers take its left strip, split into one segment each. That strip previously repeated the pill's own colour and carried no information at all, which is what made it the right place. Note that a new county and a new park share --success in the cluster list, so they share it here too. Splitting them means changing both views together, which is the moment to do it — when the per-marker colour setting arrives.
This commit is contained in:
@@ -24,7 +24,39 @@ interface Spot {
|
||||
spotter?: string;
|
||||
}
|
||||
|
||||
type SpotStatusEntry = { status: string; country?: string };
|
||||
// The FULL status entry, not the two fields the map used to declare. The extra
|
||||
// markers were already arriving in this object — the local type simply never
|
||||
// mentioned them, so they could not be drawn.
|
||||
type SpotStatusEntry = {
|
||||
status?: string;
|
||||
country?: string;
|
||||
worked_call?: boolean;
|
||||
new_county?: boolean;
|
||||
new_pota?: boolean;
|
||||
new_pfx?: boolean;
|
||||
};
|
||||
|
||||
// Extra markers, ORTHOGONAL to the entity status: a spot can be a worked entity
|
||||
// AND a new park. The cluster grid stacks them as separate badges rather than
|
||||
// letting one replace another, so the map stacks them too — as segments of the
|
||||
// pill's left accent bar, which until now only repeated the pill's own colour
|
||||
// and carried no information of its own.
|
||||
//
|
||||
// Colours are the cluster grid's, deliberately: the same fact must not be blue
|
||||
// in one panel and green in the next. NOTE that a new county and a new park
|
||||
// share --success there, so they share it here.
|
||||
const EXTRA_MARKERS: { key: 'new_pota' | 'new_county' | 'worked_call'; cls: string; label: string }[] = [
|
||||
{ key: 'new_pota', cls: 'bg-success', label: 'bmp.legendNewPota' },
|
||||
{ key: 'new_county', cls: 'bg-success', label: 'bmp.legendNewCounty' },
|
||||
{ key: 'worked_call', cls: 'bg-info', label: 'bmp.legendWorkedCall' },
|
||||
];
|
||||
|
||||
// markersFor returns the extra markers active on a spot, in a fixed order so
|
||||
// the bar reads the same way every time.
|
||||
function markersFor(e: SpotStatusEntry | undefined): typeof EXTRA_MARKERS {
|
||||
if (!e) return [];
|
||||
return EXTRA_MARKERS.filter((m) => !!e[m.key]);
|
||||
}
|
||||
|
||||
interface Props {
|
||||
band: string;
|
||||
@@ -567,10 +599,21 @@ export function BandMap({ band, spots, spotStatus, currentFreqHz, onSpotClick, o
|
||||
'hover:translate-x-0.5 hover:shadow',
|
||||
style.pill,
|
||||
)}
|
||||
title={`${p.spot.dx_call}${entry?.country ? ' · ' + entry.country : ''} · ${p.spot.freq_khz.toFixed(1)} kHz · ${statusLabel(st, t)}${p.spot.comment ? ' · ' + p.spot.comment : ''}${p.spot.spotter ? ' · de ' + p.spot.spotter : ''}`}
|
||||
title={`${p.spot.dx_call}${entry?.country ? ' · ' + entry.country : ''} · ${p.spot.freq_khz.toFixed(1)} kHz · ${statusLabel(st, t)}${markersFor(entry).map((m) => ' · ' + t(m.label)).join('')}${p.spot.comment ? ' · ' + p.spot.comment : ''}${p.spot.spotter ? ' · de ' + p.spot.spotter : ''}`}
|
||||
>
|
||||
{/* Status accent strip on the left */}
|
||||
<span className={cn('w-1 shrink-0', style.bar)} aria-hidden />
|
||||
{/* Left accent strip. With no extra marker it repeats the status
|
||||
colour, exactly as before; otherwise it splits into one
|
||||
segment per marker, so "worked entity + new park" shows both
|
||||
instead of one hiding the other. */}
|
||||
{(() => {
|
||||
const marks = markersFor(entry);
|
||||
if (marks.length === 0) return <span className={cn('w-1 shrink-0', style.bar)} aria-hidden />;
|
||||
return (
|
||||
<span className="w-1 shrink-0 flex flex-col" aria-hidden>
|
||||
{marks.map((m) => <span key={m.key} className={cn('flex-1', m.cls)} />)}
|
||||
</span>
|
||||
);
|
||||
})()}
|
||||
<span className="flex items-center gap-1.5 px-2 font-mono text-[11px] font-bold leading-none">
|
||||
<span>{p.spot.dx_call}</span>
|
||||
{mode && (
|
||||
@@ -590,6 +633,10 @@ export function BandMap({ band, spots, spotStatus, currentFreqHz, onSpotClick, o
|
||||
<LegendDot cls="bg-warning" label={t('bmp.legendNewBand')} />
|
||||
<LegendDot cls="bg-caution" label={t('bmp.legendNewSlot')} />
|
||||
<LegendDot cls="bg-muted-foreground/30" label={t("bmp.legendWorked")} />
|
||||
{/* The stacked markers, same colours as the cluster grid. */}
|
||||
<LegendDot cls="bg-success" label={t('bmp.legendNewPota')} />
|
||||
<LegendDot cls="bg-success" label={t('bmp.legendNewCounty')} />
|
||||
<LegendDot cls="bg-info" label={t('bmp.legendWorkedCall')} />
|
||||
{/* Sub-band shading, so the wash behind the pills is never colour-alone. */}
|
||||
<span className="mx-0.5 opacity-40">|</span>
|
||||
<LegendDot colour={SEG_CW} label={t("bmp.legendCW")} />
|
||||
|
||||
Reference in New Issue
Block a user