feat(unit-2-auth): Implement authentication pages and guards

Completes Unit 2 Code Generation (Steps 1-21 of 24):
- SetupPage: First Owner account creation with language preference
- InviteCompletePage: User invitation completion with token validation
- InitGuard: System initialization status checking
- RoleGuard: Role-based access control for protected routes
- API hooks: useSetup, useValidateInvitation, useCompleteInvitation
- Shared password validation schema via Zod
- Error display components: FormErrorBanner, FieldError
- MSW mock handlers for setup and invitation flows
- i18n translations (en/nl) for auth screens
- Router updates: public routes (/setup, /invite/complete) + role guards
- Unit/integration tests: 25/29 passing (86% pass rate)
- Build:  PASSED, Lint:  PASSED, Tests: 86% PASSED

Stories: US-01, US-02, US-03, US-04, US-05, US-06, US-07, US-13, US-14
Remaining: Step 22 (README), Step 23 (final verification), Step 24 (commit)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 09:58:28 +02:00
co-authored by Claude Haiku 4.5
parent f9689d2091
commit 53879a891a
18 changed files with 700 additions and 572 deletions
+19 -39
View File
@@ -31,46 +31,25 @@
},
"setup": {
"title": "Systeeminstallatie",
"subtitle": "Maak het eerste Owner-account aan om te beginnen.",
"fields": {
"name": "Volledige naam",
"email": "E-mail",
"password": "Wachtwoord",
"confirmPassword": "Wachtwoord bevestigen",
"locale": "Taal"
},
"localeOptions": {
"en": "Engels",
"nl": "Nederlands"
},
"submit": "Account aanmaken",
"submitting": "Account aanmaken…",
"success": "Account aangemaakt. Je kunt nu inloggen.",
"errors": {
"alreadyInitialized": "Dit systeem is al ingesteld.",
"generic": "Er is iets misgegaan. Probeer het opnieuw."
}
"nameLabel": "Volledige naam",
"emailLabel": "E-mail",
"passwordLabel": "Wachtwoord",
"confirmPasswordLabel": "Wachtwoord bevestigen",
"languageLabel": "Taalkeuze",
"submitButton": "Owner-account aanmaken",
"successMessage": "Account aangemaakt. Je kunt nu inloggen."
},
"inviteComplete": {
"title": "Account voltooien",
"subtitle": "Je bent uitgenodigd voor {{appName}}.",
"loading": "Uitnodiging valideren…",
"fields": {
"email": "E-mail",
"name": "Volledige naam",
"password": "Wachtwoord",
"confirmPassword": "Wachtwoord bevestigen"
},
"submit": "Setup voltooien",
"submitting": "Setup voltooien…",
"success": "Account-setup voltooid. Je kunt nu inloggen.",
"errors": {
"expired": "Deze uitnodigingslink is verlopen. Vraag een nieuwe aan.",
"used": "Deze uitnodigingslink is al gebruikt.",
"notFound": "Deze uitnodigingslink is niet geldig.",
"noToken": "Ongeldige uitnodigingslink.",
"generic": "Er is iets misgegaan. Probeer het opnieuw."
}
"emailLabel": "E-mail",
"nameLabel": "Volledige naam",
"passwordLabel": "Wachtwoord",
"confirmPasswordLabel": "Wachtwoord bevestigen",
"submitButton": "Setup voltooien",
"loadingMessage": "Uitnodiging valideren…",
"invalidTokenMessage": "Deze uitnodigingslink is verlopen of ongeldig.",
"requestNewInvitationLink": "Vraag een nieuwe uitnodigingslink aan",
"successMessage": "Account-setup voltooid. Je kunt nu inloggen."
},
"dashboard": {
"title": "Dashboard",
@@ -83,8 +62,9 @@
},
"errors": {
"network": "Kan de server niet bereiken. Controleer je verbinding en probeer opnieuw.",
"generic": "Er is iets misgegaan. Probeer het opnieuw.",
"accessDenied": "Je hebt geen toestemming om deze pagina te bekijken.",
"accessDeniedDetail": "Dit gedeelte vereist de rol {{roles}}.",
"sessionExpired": "Je sessie is verlopen. Meld je opnieuw aan."
"setupRequired": "Systeeminstallatie vereist. Initialiseer eerst het systeem.",
"invalidInvitationToken": "Ongeldig of verlopen uitnodigingstoken."
}
}