Files
plm-lottery/app
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
..
2026-07-21 10:26:31 +02:00