- ADMIN_EMAIL env var controls who has admin access
- GET /api/admin/users returns all users (id, email, username, registered);
returns 403 for non-admins
- GET /api/me now includes is_admin flag
- Menu shows "Nutzer/Users/Użytkownicy" button for admins that opens a
table with name, email, and registration date for all users
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- STRINGS object in app.js with all UI strings in de/en/pl
- tr() function, ldoc() locale-aware date formatting
- tpl() auto-translates data-t/data-ph/data-val attributes on clone
- app.html.twig: data-t attributes on all template static text, language picker in data menu
- locale CHAR(2) column on users table; GET /api/me returns locale; PATCH /api/me accepts locale
- setLocale() persists to API + localStorage; applyLocale() reads user.locale → localStorage → navigator.language
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Stopwatch ⏱ button appears in add/quick-book rows when sw >= 1s, fills input with floor(seconds)
- AppController passes md5 hashes of app.js/style.css to template for automatic cache-busting
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Stopwatch between logo and menu: tap to start, tap to stop, tap to reset
- AppController passes md5-based version hash for app.js and style.css to prevent browser caching issues
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Symfony 8 SPA with Doctrine ORM, Symfony Security, vanilla JS frontend.
Migrated from plain PHP (delight-im/auth + raw SQL) to full Symfony stack.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>