dedupe j()/errText(), stale-fetch guard, empty bar-picker state
Six small, mostly-unrelated items from the #47 review round (#57):
1. 'Statistik zurücksetzen' now checks res.ok and shows the server's
error instead of silently re-rendering the un-reset data on a 401/500
with no indication anything went wrong.
2. DayChart now tracks its container width via ResizeObserver and calls
uPlot's setSize() on change — previously read once at plot-creation
time, so a resize/orientation-change (more visible on the phone/
tablet path into /stats) left the chart the wrong width.
3. .qty-btn (cart +/- buttons) grown from 28x28px to 44x44px, the
conventional minimum touch target — was the one conspicuously small
interactive control in the money path, at a fast-moving bar counter.
4. Tablet's bar-config fetch (App.tsx) now guards against an
out-of-order resolution if barId changes again while a previous
api.config() call is still in flight. Currently unreachable (nothing
triggers a second barId change mid-fetch today) but closes the gap
before the next 'add a cancel button to the loading screen' change
could make it live.
5. j()/errText() were duplicated byte-for-byte between Admin.tsx and
Stats.tsx (Admin.tsx's own comment noted this exact duplication had
already caused drift once before) — centralized in api.ts, both files
now import instead of redeclaring.
6. Tablet's bar picker now shows an explicit empty-state message when
zero bars exist (fresh install, or every bar deleted), previously
indistinguishable from 'still loading'.
Closes#57. Verified: tsc --noEmit and vite build both clean.