Settings card to link and unlink with the NPSSO, shows the expiry
date. Import page gets a PSN source; blocked when the link has ended.
English and German texts.
useImportPolling and useSettingsLoad take the effects out of ImportView
and SettingsPage, line for line. useSettingsLoad no longer sets state
after unmount. Tests for both hooks. Issue #6.
/reset-password page for the email request and the new password,
ChangePasswordCard in settings, password reset button on the admin
users page, 'Forgot password?' link on the login page, de/en texts.
Show the stat groups on /stats, the pile trend on the dashboard card,
one switch per group in the settings, and the shared groups on the
public profile.
A Steam card in the settings links, verifies or unlinks the Steam
account through "Sign in through Steam". After the way back the page
shows the outcome and refreshes the session, so Core gets the new
Steam ID at once. Registration and settings no longer ask for a typed
Steam ID.
The token is no longer stored; a tbp_session flag remembers the
login. apiFetch renews the session once on a 401 and sends the
request again. Parallel requests and other tabs share one refresh,
because Auth revokes the session when a refresh token is used twice.
Only a 401 from the refresh ends the session; a 502 or no network
shows the normal error.
All authenticated calls now use apiFetch, and only utils/auth.js
touches the stored token. The cookie login can then change these two
files instead of every page.
/u/<name> shows a public profile without login. Settings get the switch and
the link; every settings save now sends the other saved values, and removing
the display name also makes the profile private.
Every 401 from Auth or Core now goes through useSessionExpired: the login page
says the session expired and returns to the last page after login. App no
longer removes a token that only the browser clock calls expired, so a backend
401 is the one signal. A 403 on the profile now shows an error instead.
Settings: new Profil card with display name and Steam ID. Registration: optional display name. The dashboard falls back to the email prefix when no display name is set.
Add shadcn/ui (Radix + Tailwind 4) components, zinc/violet theme tokens and self-hosted Inter. New header with user menu, Steam cover art, skeletons and toasts. Replace @mdi/font with lucide-react. Fix: top-owned list on the landing page only showed with top-played entries; numbers use the app language.
Number("76561198005679788") is 76561198005679790 in JavaScript, so the wrong
Steam ID was saved. The Steam ID now stays a 17-digit string. Theme and
language saves no longer send steamId 0. After a save the new token from Auth
replaces the old one.
Add Vitest and run it in CI.