Finishes functional design for unit 0 (back-end changes before front-end work)

This commit is contained in:
2026-06-18 21:40:45 +02:00
parent 9e49489f7e
commit 53a307cdbd
14 changed files with 1065 additions and 4 deletions
@@ -0,0 +1,198 @@
# Units of Work — CMS Frontend
## Overview
The CMS frontend is decomposed into **7 sequential units** (Unit 06). Each unit builds on the previous; dependencies flow strictly forward. All units together produce a single deployable SPA + updated backend API.
```mermaid
graph LR
U0["Unit 0\nBackend Prerequisites"]
U1["Unit 1\nProject Scaffold"]
U2["Unit 2\nAuth Pages"]
U3["Unit 3\nLayout & Nav"]
U4["Unit 4\nDashboard"]
U5["Unit 5\nUser Management"]
U6["Unit 6\nRemaining Pages"]
U0 --> U1 --> U2 --> U3 --> U4 --> U5 --> U6
style U0 fill:#4CAF50,stroke:#2E7D32,color:#fff
style U1 fill:#FFC107,stroke:#F57F17,color:#000
style U2 fill:#FF5722,stroke:#BF360C,color:#fff
style U3 fill:#9C27B0,stroke:#4A148C,color:#fff
style U4 fill:#2196F3,stroke:#0D47A1,color:#fff
style U5 fill:#009688,stroke:#004D40,color:#fff
style U6 fill:#607D8B,stroke:#263238,color:#fff
```
---
## Unit 0 — Backend Prerequisites
**Type**: Backend (.NET) — blocking prerequisite for all frontend units
**Priority**: Must complete before Unit 1
### Deliverables
- `ServiceCollectionExtensions.cs` — add `AddCorsFrontendPolicy()` reading `Cors:AllowedOrigins[]` from config
- `Program.cs` — add `app.UseCors("FrontendPolicy")` before `UseAuthentication`
- `AuthController.cs` — update `Login`, `Refresh`, `Revoke` to use httpOnly cookie
- `RefreshTokenRequest.cs`**remove** (no backward compatibility needed; refresh now uses httpOnly cookie)
- `TokenResponse.cs` — add `Name` property (display name from `UserName` or `Email`)
- `appsettings.json` — add `Cors` section (production placeholder)
- `appsettings.Development.json` — add `Cors:AllowedOrigins: ["http://localhost:5173"]`
- Tests — update `AuthController` tests for cookie-based flow
### Key Decisions
- Cookie name: `refreshToken`, Path: `/api/v1/auth`, HttpOnly, Secure, SameSite=Strict
- CORS: `AllowCredentials()` required for cookie flow
- `name` field in `TokenResponse` maps from `user.UserName ?? user.Email`
---
## Unit 1 — Project Scaffold & Infrastructure
**Type**: Frontend — foundation for all subsequent units
**Depends on**: Unit 0 (API must be reachable with CORS)
### Deliverables
```
frontend/
├── src/
│ ├── api/
│ │ ├── client.ts # ApiClient: fetch + auth header + 401 interceptor
│ │ └── types.ts # Shared TS interfaces (User, AuthResponse, etc.)
│ ├── auth/
│ │ ├── AuthContext.tsx # AuthProvider: in-memory token + user state
│ │ └── useAuth.ts # useAuth hook
│ ├── components/
│ │ ├── layout/
│ │ │ └── ThemeProvider.tsx
│ │ └── error/
│ │ └── ErrorBoundary.tsx
│ ├── main.tsx # Entry: QueryClientProvider + AuthProvider + RouterProvider
│ └── app.tsx # App root
├── .env.example # VITE_API_BASE_URL=http://localhost:5000
├── .env # gitignored
├── vite.config.ts
├── tailwind.config.ts # Primary color #ac0000
├── tsconfig.json
└── package.json # pnpm workspace
```
### Key Decisions
- TanStack Router file-based routing initialized (empty route tree)
- shadcn/ui configured with `#ac0000` primary
- `ApiClient` created; `AuthContext` wired up; `QueryClient` configured
---
## Unit 2 — Authentication Pages
**Type**: Frontend — public + session management
**Depends on**: Unit 1 (ApiClient, AuthContext)
### Deliverables
```
frontend/src/
├── auth/
│ ├── ProtectedRoute.tsx # Redirects unauthenticated → /login
│ ├── RoleGuard.tsx # Redirects wrong role → /403
│ └── InitGuard.tsx # Redirects uninitialized → /setup
├── api/
│ └── useSetup.ts # useSetupStatus, useCreateOwner
└── routes/
├── __root.tsx # Root route: InitGuard + global ErrorBoundary
├── login.tsx # LoginPage
├── setup.tsx # SetupPage
└── invite.complete.tsx # InviteCompletePage
```
### Key Decisions
- `react-hook-form` + `zod` for all forms; password schema enforces exact backend rules
- `InitGuard` in `__root.tsx` blocks all routes until setup status confirmed
- `ProtectedRoute` uses `beforeLoad` in TanStack Router
---
## Unit 3 — Layout & Navigation
**Type**: Frontend — authenticated shell
**Depends on**: Unit 2 (ProtectedRoute, RoleGuard, AuthContext)
### Deliverables
```
frontend/src/
├── components/layout/
│ ├── AppLayout.tsx # Shell: Sidebar + <Outlet />
│ └── Sidebar.tsx # Role-filtered nav, logout, theme toggle
└── routes/
└── _authenticated.tsx # Authenticated layout route wrapping all protected pages
```
### Key Decisions
- `_authenticated.tsx` is a TanStack Router layout route — all child routes inherit `ProtectedRoute`
- Sidebar filters nav items by `user.role` from `AuthContext`
- Responsive: hamburger menu on mobile
---
## Unit 4 — Dashboard
**Type**: Frontend — first authenticated page
**Depends on**: Unit 3 (AppLayout, AuthContext)
### Deliverables
```
frontend/src/
├── api/
│ └── useAvailability.ts # useAvailabilityStatus (staleTime: 30s)
├── components/shared/
│ └── AvailabilityStatusBadge.tsx
└── routes/
└── index.tsx # DashboardPage: welcome + availability widget
```
---
## Unit 5 — User Management
**Type**: Frontend — Owner/Admin feature
**Depends on**: Unit 3 (AppLayout, RoleGuard), Unit 4 (patterns established)
### Deliverables
```
frontend/src/
├── api/
│ ├── useUsers.ts # useUsers, useInviteUser
│ └── useInvitation.ts # useValidateInvitation, useCompleteSetup
├── components/users/
│ └── InviteUserDialog.tsx # Two-step: invite form → share link
└── routes/
└── users.tsx # UsersPage: user table + invite dialog
```
---
## Unit 6 — Remaining Pages & Documentation
**Type**: Frontend + Documentation
**Depends on**: Unit 3 (AppLayout, RoleGuard)
### Deliverables
```
frontend/src/routes/
├── profile.tsx # ProfilePage: read-only user info
├── settings.tsx # SettingsPage: Owner-only, availability + placeholders
├── cms.tsx # CmsPage: Owner-only placeholder
├── 403.tsx # AccessDeniedPage
└── $404.tsx # NotFoundPage
```
**Documentation**:
- `README.md` — add **Frontend Development** section:
- Prerequisites (Node.js, pnpm)
- `pnpm install` in `frontend/`
- `.env` setup (copy `.env.example`)
- `pnpm dev` to start dev server
- `pnpm build` for production build
- Security headers note for production deployment