feat(watchlist): confirm an add, and both messages clear themselves

A green line under the toolbar says what was added (and as what — the contest
variant names the per-UTC-day rule); the already-exists error keeps its red
line. Both fade after four seconds: a stale 'added' from ten minutes ago reads
as a fresh one.
This commit is contained in:
2026-08-29 01:30:10 +02:00
parent 7795e13432
commit a9a6579a9a
2 changed files with 19 additions and 5 deletions
+17 -3
View File
@@ -84,6 +84,16 @@ export function WatchlistTab({ spots, spotStatus, onSpotSelect, onSpotClick }: P
return m === modeFilter;
};
const [error, setError] = useState('');
// A quiet confirmation under the toolbar; both messages clear themselves —
// a stale "added" from ten minutes ago reads as a fresh one.
const [notice, setNotice] = useState('');
const noticeTimer = useRef<number | undefined>(undefined);
const flash = (msg: string, isError: boolean) => {
if (noticeTimer.current) window.clearTimeout(noticeTimer.current);
setError(isError ? msg : '');
setNotice(isError ? '' : msg);
noticeTimer.current = window.setTimeout(() => { setError(''); setNotice(''); }, 4000) as unknown as number;
};
const [removeArm, setRemoveArm] = useState('');
// worked answer per "call|band|modeclass|contest" key.
const [worked, setWorked] = useState<Record<string, boolean>>({});
@@ -168,9 +178,12 @@ export function WatchlistTab({ spots, spotStatus, onSpotSelect, onSpotClick }: P
const add = async () => {
const c = addCall.trim().toUpperCase();
if (!c) return;
setError('');
try { await WatchlistAdd(c, addContest); setAddCall(''); await refresh(); }
catch (e: any) { setError(String(e?.message ?? e)); }
try {
await WatchlistAdd(c, addContest);
setAddCall('');
flash(t(addContest ? 'wl.addedContest' : 'wl.added', { call: c }), false);
await refresh();
} catch (e: any) { flash(String(e?.message ?? e), true); }
};
const remove = async (call: string) => {
@@ -296,6 +309,7 @@ export function WatchlistTab({ spots, spotStatus, onSpotSelect, onSpotClick }: P
</div>
</div>
{error && <div className="text-xs text-danger px-1">{error}</div>}
{notice && <div className="text-xs text-success px-1">{notice}</div>}
{/* cards */}
<div className="flex-1 min-h-0 overflow-y-auto space-y-2 pr-1">