Adds auth pages

This commit is contained in:
2026-06-21 00:15:28 +02:00
parent 7dfc3a9692
commit ab93a5c7d1
28 changed files with 2785 additions and 45 deletions
@@ -0,0 +1,70 @@
# Code Generation Summary — Unit 2: Authentication Pages
**Status**: ✅ Complete
**Date**: 2026-06-21
**Plan**: `aidlc-docs/features/cms-frontend/construction/plans/unit-2-code-generation-plan.md`
---
## Files Created
| File | Purpose |
|---|---|
| `frontend/src/lib/schemas/auth.ts` | Shared Zod schemas: `passwordSchema`, `loginSchema`, `setupSchema`, `inviteCompleteSchema` |
| `frontend/src/components/ui/PasswordField.tsx` | Password input with show/hide toggle |
| `frontend/src/components/ui/FormBannerError.tsx` | Dismissible inline error banner for API errors |
| `frontend/src/components/auth/RoleGuard.tsx` | Role-based access wrapper; renders inline "Access Denied" for unauthorized roles |
| `frontend/src/api/useSetup.ts` | `useSetupStatus`, `useCreateOwner` hooks with module-level session cache |
| `frontend/src/api/useInvitation.ts` | `useValidateInvitation`, `useCompleteSetup` hooks |
| `frontend/src/mocks/invitation/handlers.ts` | MSW handlers for invitation validate/complete endpoints |
| `frontend/src/pages/SetupPage.tsx` | Full 5-field owner setup form (replaces stub) |
| `frontend/src/pages/InviteCompletePage.tsx` | Invitation completion page with token validation states |
| `frontend/src/pages/SetupPage.test.tsx` | Tests: render, validation, success, 409 error, InitGuard redirect |
| `frontend/src/pages/InviteCompletePage.test.tsx` | Tests: loading, invalid token states, form, success |
## Files Modified
| File | Change |
|---|---|
| `frontend/src/api/types.ts` | Added `SetupRequest`, `InvitationValidation`, `InviteCompleteRequest` interfaces |
| `frontend/src/router.tsx` | Full rewrite: InitGuard (`async beforeLoad` on rootRoute), `inviteCompleteRoute`, `RoleGuard` wrappers on `usersRoute`/`cmsRoute`, `_resetSetupStatusCache` export for tests |
| `frontend/src/pages/LoginPage.tsx` | Replaced inline schema with `loginSchema` from `@/lib/schemas/auth`; added `mode: 'onTouched'` |
| `frontend/src/mocks/setup/handlers.ts` | Added `POST /Setup` success handler, `setupUninitializedHandlers`, `setupConflictHandlers` |
| `frontend/src/mocks/index.ts` | Added `invitationHandlers` to combined handlers + re-exports |
| `frontend/src/i18n/locales/en/translation.json` | Added `setup`, `inviteComplete`, `nav.profile/settings`, `errors.accessDenied/sessionExpired` keys |
| `frontend/src/i18n/locales/nl/translation.json` | Dutch translations for all new keys |
| `frontend/src/test/RouteGuard.test.tsx` | Added InitGuard tests (setup redirect both ways) + RoleGuard tests |
---
## Story Coverage
| Story | Coverage |
|---|---|
| US-01 — Login | `loginSchema` extracted to shared file; `mode: 'onTouched'` added to LoginPage |
| US-02 — Session persistence | Unit 1 (AuthContext + ApiClient); no changes |
| US-03 — Logout | Unit 1 (AuthContext.logout()); no changes |
| US-04 — Redirect when unauthenticated | `authenticatedRoute.beforeLoad` (Unit 1); `RoleGuard` (Unit 2) |
| US-05 — Auto token refresh | Unit 1 (ApiClient 401 interceptor); no changes |
| US-06 — Owner initialization | `SetupPage`, `useCreateOwner`, `setupSchema`, InitGuard, EN/NL translations |
| US-07 — Redirect to setup when not initialized | InitGuard in `rootRoute.beforeLoad`, `fetchSetupStatus()` session cache |
| US-13 — Complete setup via invitation | `InviteCompletePage`, `useValidateInvitation`, `useCompleteSetup`, `invitationHandlers` |
| US-14 — Handle expired/invalid invitation | `InviteCompletePage` invalid token states (`EXPIRED`, `USED`, `NOT_FOUND`, no token) |
---
## Deviations from Plan
| Plan spec | Actual | Reason |
|---|---|---|
| `useSetupStatus()` with TanStack Query `staleTime: Infinity` | Module-level `_setupStatusCache` + `useState`/`useEffect` | TanStack Query is not installed in this project |
| `UserRole = 'Owner' \| 'Admin' \| 'User'` | `UserRole = 'Owner' \| 'Administrator' \| 'User'` | Matches existing `src/api/types.ts` and backend identity model |
| InitGuard as React component with `useEffect` | `async beforeLoad` on rootRoute | More idiomatic for TanStack Router; avoids render flash before redirect |
| `fetchSetupStatus` in separate module from router | Inlined in `router.tsx` with `_resetSetupStatusCache` export | Keeps router self-contained; simplifies test cache reset |
---
## Test Utilities Added
- `_resetSetupStatusCache()` exported from `src/router.tsx` — resets module-level setup cache between tests so each test controls its own MSW handler for `GET /Setup/status`
- `setupUninitializedHandlers` / `setupConflictHandlers` exported from `src/mocks/index.ts` — per-test MSW overrides