Commit Graph
5 Commits
Author SHA1 Message Date
davideandClaude Sonnet 5 e5af15087c Polish /report-bug's visual design and refine bug report semantics
Design pass on the bug report page, staying inside the site's existing
design system (tokens, IBM Plex Sans, card/badge/pill components, stroke
icon set) rather than introducing a new one:
- A slim top bar (brand mark + back-to-home pill button + language switcher)
  replaces the bare floating heading, so the page reads as part of the
  product instead of an orphaned form.
- The "write in English" notice moves inside the form card, right above the
  field it applies to, and switches from the amber "needs attention" tone to
  an accent-tinted info tone, so it doesn't visually collide with the
  bug-status badges' own use of amber for "not read yet".
- "Your reports" is promoted to a proper labeled section with a cleaner row
  layout (truncated description with a title tooltip, compact date).
- A character counter on the description field.
- The back-to-home control is now a bordered pill with an arrow icon instead
  of a bare text link with a hardcoded "←", which also meant dropping that
  hardcoded arrow from all 7 translations.

Also, two content refinements based on feedback:
- Max description length dropped from 5000 to 2000 characters, enforced on
  both the textarea and the API's Pydantic validator.
- The "read" status is relabeled from a passive "read"/"letta" to an active
  "acknowledged"/"presa in carico" (and each other language's own equivalent
  helpdesk term) — it communicates a team is on it, not just that someone
  glanced at it. Only the label changed; the underlying "read" status value
  in the API/DB is untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 16:28:37 +02:00
davideandClaude Sonnet 5 ee4e845c89 Add user bug reporting with admin triage (open/read/resolved)
Turns the /report-bug placeholder into a real form (POST /bug-reports,
optionally attributed to the logged-in user) and adds a "Segnalazioni bug"
section to /admin to view and triage them. A logged-in reporter can also
check their own report's status via GET /bug-reports/mine, since anonymous
submissions have no user to show a history to.

Status is a three-state lifecycle (open -> read -> resolved) rather than a
plain boolean, so an admin can acknowledge a report distinctly from actually
fixing it. The schema went through two migrations because the first one
(add bug_reports table) had already been applied against the running
instance with a `resolved` boolean before the three-state design was
decided, so a follow-up migration backfills it into `status` instead of
rewriting already-applied history.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 15:50:40 +02:00
davideandClaude Opus 5 dc4d5761df Format amounts, guard the loading state, and translate the new errors
Amounts were rendered by bare sats/SATS_PER_PLM division, so binary
floating-point artefacts reached the UI — a 0.7 PLM jackpot could display as
0.7000000000000001 (B-22). formatPlm() in app.js and fmtPlm() in admin.js route
every display site through Intl.NumberFormat with the already-resolved language.
Input fields deliberately keep the raw value: a grouped, localized string would
break parseFloat, and amounts sent to the server still go through
Math.round(x * SATS_PER_PLM).

withLoading kept a snapshot of the button's markup and restored it in finally,
but refreshMe() is fired from the SSE handler, the poll chain, placeBet, withdraw
and showDashboard, all sharing #refresh-btn. Two overlapping calls made the second
snapshot the *loading* label and then restore it permanently, leaving the button
stuck on "Aggiornamento…" (B-23). The in-flight promise now lives in a WeakMap
keyed by the button, so a nested call awaits the existing one and only the
outermost call touches the markup.

The registration form mirrors the constraints the server now enforces
(minlength/pattern/required) and register() pre-checks the password length, so the
failure is immediate and translated instead of a generic 422 (B-12).

Five new error codes are translated in all 7 languages — broadcast_failed,
amount_below_dust_limit, withdrawal_to_own_address, internal_error,
guide_unavailable — keeping the key sets identical, as the i18n contract in
CLAUDE.md requires (verified: 123 keys per language).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 00:35:14 +02:00
davideandClaude Opus 5 0cf35147ad Answer user-facing API failures with a machine-readable error code
The dashboard now speaks seven languages but every failure path still showed
the API's raw English text ("insufficient balance", "current password is
incorrect"), which is the most frequent and least forgiving part of the UI to
leave untranslated.

Rather than teach the API about locales, it keeps answering in one language
and hands the client something to translate: `detail` becomes
{code, message, params}, where message stays English for non-dashboard
consumers (curl, tests) and code maps onto `error.<code>` in i18n.js. An
unknown code falls back to message, so a client older or newer than the server
degrades to English instead of a blank toast.

Domain exceptions (BetError, WithdrawalError) subclass the new ApiError and
carry the code from where the failure actually happens; str(exc) is still the
English message, so existing tests keep matching on it. Interpolated values
travel in params rather than baked into the English sentence — amounts as
*_sats, from which the frontend derives a *_plm sibling, so each language can
place them wherever its grammar wants.

admin.js reads detail.message defensively: the admin endpoints still return a
bare string, but the shared auth dependencies now return the structured form.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 21:44:39 +02:00
davideandClaude Sonnet 5 bae08f2759 Extract inline JS from index.html/admin.html into app.js/admin.js
Mirrors the earlier CSS extraction (style.css/admin.css) — app/static/ is
now split cleanly by file type (markup, styles, script) instead of mixing
JS inline in the HTML. No behavior change: the script content moved
verbatim, referenced via <script src>. FastAPI's existing StaticFiles mount
serves the new files automatically, same as the CSS files already do.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 11:05:38 +02:00