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>
9.1 KiB
9.1 KiB
Code Generation Plan — Unit 2: Authentication Pages
Status: 📋 Ready for approval
Unit Context
Unit: Unit 2 — Authentication Pages
Type: Frontend (React/TypeScript with TanStack Router)
Depends on: Unit 1 (ApiClient, AuthContext, router.tsx, MSW, shadcn primitives)
Stories Covered: US-01, US-02, US-03, US-04, US-05, US-06, US-07, US-13, US-14 (9 user stories)
Key Deliverables:
- SetupPage component (first Owner account creation with language preference)
- InviteCompletePage component (user invitation completion with token validation)
- InitGuard hook (system initialization status check before route access)
- RoleGuard hook (role-based access control for protected routes)
- API hooks: useSetup, useValidateInvitation, useCompleteInvitation
- Shared password validation schema (src/lib/schemas/auth.ts)
- Error handling components (FormErrorBanner, FieldError)
- i18n translations (extend translation.json for setup/invite/errors)
- MSW mock handlers (extend setupHandlers, new invitationHandlers)
- Unit tests for all components, hooks, and API integration
Code Generation Steps
Step 1: Create Shared Password Validation Schema
- Create
src/lib/schemas/auth.tswith:passwordSchema— Zod validation (8+ chars, uppercase, digit, special)confirmPasswordSchema— Confirm password field- Export both for use in SetupPage, InviteCompletePage, LoginPage
- Validate schema with LoginPage password validation (ensure alignment)
- Story traceability: US-01 (login), US-06 (setup), US-13 (invite complete)
Step 2: Create FormErrorBanner Component
- Create
src/components/ui/FormErrorBanner.tsx:- Props:
error: FormError | null,onDismiss: () => void - Red background with error message
- Dismissible close button
- Fade animation on dismiss
- Props:
- Add
data-testid="form-error-banner"attribute - Story traceability: US-06, US-13 (error display)
Step 3: Create FieldError Component
- Create
src/components/ui/FieldError.tsx:- Props:
message?: string - Small red text below input field
- Only render if message exists
- Props:
- Add
data-testid="field-error-[fieldname]"attributes - Story traceability: US-06, US-13 (field validation)
Step 4: Create API Hooks — Setup
- Create
src/api/useSetup.ts:useSetup()hook for POST /Setup- Returns:
{ mutate, isLoading, error } - Request:
{ name, email, password, language } - Response:
SetupResponsewith user data - Error handling: ProblemDetails format
- Add error logging for debugging
- Story traceability: US-06 (initialize system)
Step 5: Create API Hooks — Invitation
- Create
src/api/useInvitation.ts:useValidateInvitation(token: string)— GET /Invitation/validate- Auto-runs on mount if token provided
- Returns:
{ data, isLoading, error }
useCompleteInvitation()— POST /Invitation/complete- Returns:
{ mutate, isLoading, error }
- Returns:
- Request:
{ token, name, password } - Response:
InvitationCompletionResponsewith user data - Error handling: ProblemDetails format
- Add loading/error state management
- Story traceability: US-13, US-14 (complete invitation)
Step 6: Extend Password Schema in LoginPage
- Modify
src/pages/LoginPage.tsx:- Update to use shared
passwordSchemafromsrc/lib/schemas/auth.ts - Ensure no duplicate definitions
- Maintain existing LoginPage functionality
- Update to use shared
- Run tests to ensure no regressions
- Story traceability: US-01 (login)
Step 7: Create SetupPage Component
- Create
src/pages/SetupPage.tsx:- Form fields: name, email, password, confirmPassword, language
- Use react-hook-form + Zod (shared passwordSchema)
- Form state:
{ isLoading, error } - Submit: POST /Setup via useSetup hook
- Validation: Real-time inline (onBlur) + banner (onSubmit)
- Success: Show success message → redirect to /login after 2–3 sec
- Error: Show error banner with backend message
- Add data-testid attributes (form, fields, button)
- Use shadcn primitives (Button, Input, Label, Card)
- Use FormErrorBanner + FieldError for error display
- Add i18n keys:
setup.* - Story traceability: US-06 (initialize system), US-07 (redirect to setup)
Step 8: Create InviteCompletePage Component
- Create
src/pages/InviteCompletePage.tsx:- Extract token from URL query param
- On mount: validate token via useValidateInvitation
- States: loading → form/error
- If valid: Show form (email read-only, name, password, confirmPassword)
- If invalid: Show error state with link for new invitation
- Submit: POST /Invitation/complete
- Validation: Real-time inline + banner
- Success: Show success message → redirect to /login
- Error: Show error banner
- Add data-testid attributes
- Use shadcn primitives
- Use FormErrorBanner + FieldError
- Add i18n keys:
inviteComplete.* - Story traceability: US-13, US-14
Step 9: Create InitGuard Hook
- Create
src/auth/InitGuard.tsx:- Hook:
useInitGuard(): { initialized, isLoading, error } - Calls
GET /Setup/statuson app mount - Caching:
staleTime: Infinity(session-level) - Integrate into
src/router.tsx—__root.tsxroutebeforeLoad - Bypass routes:
/setup,/login,/invite/complete
- Hook:
- Story traceability: US-07
Step 10: Create RoleGuard Integration
- Implement RoleGuard logic in
src/router.tsx:/users: Owner or Admin role required/settings: Owner role required/cms: Owner role required- Page-level inline "Access Denied" message if denied
- Story traceability: Role-restricted routes
Step 11: Extend i18n Translations
- Modify
src/i18n/locales/en/translation.json:- Add
setup,inviteComplete, extenderrorssections
- Add
- Modify
src/i18n/locales/nl/translation.json:- Mirror structure in Dutch
- Verify both locales are valid JSON
- Story traceability: All UI strings
Step 12: Extend MSW Mock Handlers — Setup
- Modify
src/mocks/setup/:- Extend
GET /Setup/status - Add
POST /Setuphandler - After POST: mark
initialized: true
- Extend
- Story traceability: US-06
Step 13: Create MSW Mock Handlers — Invitation
- Create
src/mocks/invitation/index.ts:- Export
invitationHandlers GET /Invitation/validate?token=xxxPOST /Invitation/complete- Add to
src/mocks/browser.tsandsrc/mocks/server.ts
- Export
- Story traceability: US-13, US-14
Step 14: Update MSW Handler Index
- Modify
src/mocks/index.ts:- Export
invitationHandlers
- Export
Step 15: Create Unit Tests — SetupPage
- Create
src/pages/SetupPage.test.tsx:- Successful setup flow
- Validation errors (inline + banner)
- Backend errors
- Network error handling
- Language selection
- Target: >70% coverage
- Story traceability: US-06
Step 16: Create Unit Tests — InviteCompletePage
- Create
src/pages/InviteCompletePage.test.tsx:- Token validation (valid/invalid)
- Form fill and submission
- Error handling
- Read-only email field
- Target: >70% coverage
- Story traceability: US-13, US-14
Step 17: Create Unit Tests — InitGuard Hook
- Create
src/auth/InitGuard.test.tsx:- Initialized true/false scenarios
- Loading/error states
- Session cache behavior
- Target: >80% coverage
- Story traceability: US-07
Step 18: Create Unit Tests — RoleGuard
- Create tests for RoleGuard logic:
- Owner access to restricted routes
- Non-Owner denied with inline message
- Public routes bypass
- Target: >80% coverage
Step 19: Create Unit Tests — API Hooks
- Create
src/api/useSetup.test.tsandsrc/api/useInvitation.test.ts:- Success, error, loading states
- Token validation
- Target: >75% coverage
Step 20: Create Integration Tests
- Create
src/test/integration/unit-2-auth-flow.test.tsx:- Setup flow end-to-end
- Invitation flow end-to-end
- Role guard integration
- 401 refresh + retry
- Target: Happy path coverage
Step 21: Update Router Configuration
- Modify
src/router.tsx:- Add InitGuard to
__root.tsx - Add
/setuproute (SetupPage) - Add
/invite/completeroute (InviteCompletePage) - Add RoleGuard checks for protected routes
- Add InitGuard to
- Story traceability: All routing stories
Step 22: Update README & Documentation
- Update
frontend/README.md:- New Unit 2 features section
- Authentication flow documentation
- Role-based access control
- Add brief JSDoc comments to new hooks/components
Step 23: Final Verification
- [ ]
pnpm build— no errors - [ ]
pnpm lint— all checks pass - [ ]
pnpm format:check— formatting correct - [ ]
pnpm test— all tests pass - [ ] Dev server boots, test all flows
- [ ] Coverage: auth-related >70%, core >80%
- [ ] All data-testid attributes present
Step 24: Commit Changes
- Stage all files
- Create commit with proper message
- Reference stories: US-01–US-07, US-13–US-14
Total Steps: 24
Estimated Scope: 600–800 LOC, 4–6 hours, >70% coverage
Ready for Approval: Yes