144 lines
6.0 KiB
Markdown
144 lines
6.0 KiB
Markdown
# Component Dependencies — CMS Frontend
|
|
|
|
## Dependency Overview
|
|
|
|
```mermaid
|
|
graph TD
|
|
subgraph Backend["Backend (Unit 0)"]
|
|
CorsPolicy["CorsPolicy\n(ServiceCollectionExtensions)"]
|
|
AuthCtrl["AuthController\n(updated)"]
|
|
AuthSvc["AuthService\n(no changes)"]
|
|
AuthCtrl --> AuthSvc
|
|
end
|
|
|
|
subgraph Infrastructure["Frontend Infrastructure Layer"]
|
|
ApiClient["ApiClient\n(fetch wrapper)"]
|
|
AuthContext["AuthContext\n(session state)"]
|
|
Router["RouterConfig\n(TanStack Router)"]
|
|
AuthContext --> ApiClient
|
|
end
|
|
|
|
subgraph Guards["Auth Guards"]
|
|
ProtectedRoute["ProtectedRoute"]
|
|
RoleGuard["RoleGuard"]
|
|
InitGuard["InitGuard"]
|
|
ProtectedRoute --> AuthContext
|
|
RoleGuard --> AuthContext
|
|
InitGuard --> ApiClient
|
|
end
|
|
|
|
subgraph Layout["Layout Components"]
|
|
AppLayout["AppLayout"]
|
|
Sidebar["Sidebar"]
|
|
ThemeProvider["ThemeProvider"]
|
|
AppLayout --> Sidebar
|
|
Sidebar --> AuthContext
|
|
end
|
|
|
|
subgraph QueryHooks["TanStack Query Hooks"]
|
|
useAvailability["useAvailabilityStatus"]
|
|
useUsers["useUsers + useInviteUser"]
|
|
useInvitation["useValidateInvitation\nuseCompleteSetup"]
|
|
useSetup["useSetupStatus\nuseCreateOwner"]
|
|
useAvailability --> ApiClient
|
|
useUsers --> ApiClient
|
|
useInvitation --> ApiClient
|
|
useSetup --> ApiClient
|
|
end
|
|
|
|
subgraph Pages["Page Components"]
|
|
LoginPage["LoginPage"]
|
|
SetupPage["SetupPage"]
|
|
InviteCompletePage["InviteCompletePage"]
|
|
DashboardPage["DashboardPage"]
|
|
UsersPage["UsersPage"]
|
|
ProfilePage["ProfilePage"]
|
|
SettingsPage["SettingsPage"]
|
|
CmsPage["CmsPage"]
|
|
|
|
LoginPage --> AuthContext
|
|
SetupPage --> useSetup
|
|
InviteCompletePage --> useInvitation
|
|
DashboardPage --> useAvailability
|
|
UsersPage --> useUsers
|
|
ProfilePage --> AuthContext
|
|
SettingsPage --> useAvailability
|
|
end
|
|
|
|
Router --> Guards
|
|
Router --> AppLayout
|
|
AppLayout --> Pages
|
|
|
|
style CorsPolicy fill:#4CAF50,stroke:#2E7D32,color:#fff
|
|
style AuthCtrl fill:#4CAF50,stroke:#2E7D32,color:#fff
|
|
style AuthSvc fill:#FFC107,stroke:#F57F17,color:#000
|
|
style ApiClient fill:#FFC107,stroke:#F57F17,color:#000
|
|
style AuthContext fill:#FFC107,stroke:#F57F17,color:#000
|
|
style Router fill:#FFC107,stroke:#F57F17,color:#000
|
|
style ProtectedRoute fill:#FF5722,stroke:#BF360C,color:#fff
|
|
style RoleGuard fill:#FF5722,stroke:#BF360C,color:#fff
|
|
style InitGuard fill:#FF5722,stroke:#BF360C,color:#fff
|
|
style AppLayout fill:#9C27B0,stroke:#4A148C,color:#fff
|
|
style Sidebar fill:#9C27B0,stroke:#4A148C,color:#fff
|
|
style ThemeProvider fill:#9C27B0,stroke:#4A148C,color:#fff
|
|
style useAvailability fill:#009688,stroke:#004D40,color:#fff
|
|
style useUsers fill:#009688,stroke:#004D40,color:#fff
|
|
style useInvitation fill:#009688,stroke:#004D40,color:#fff
|
|
style useSetup fill:#009688,stroke:#004D40,color:#fff
|
|
style LoginPage fill:#2196F3,stroke:#0D47A1,color:#fff
|
|
style SetupPage fill:#2196F3,stroke:#0D47A1,color:#fff
|
|
style InviteCompletePage fill:#2196F3,stroke:#0D47A1,color:#fff
|
|
style DashboardPage fill:#2196F3,stroke:#0D47A1,color:#fff
|
|
style UsersPage fill:#2196F3,stroke:#0D47A1,color:#fff
|
|
style ProfilePage fill:#2196F3,stroke:#0D47A1,color:#fff
|
|
style SettingsPage fill:#2196F3,stroke:#0D47A1,color:#fff
|
|
style CmsPage fill:#2196F3,stroke:#0D47A1,color:#fff
|
|
```
|
|
|
|
---
|
|
|
|
## Dependency Matrix
|
|
|
|
| Component | Depends On | Used By |
|
|
|-----------|-----------|---------|
|
|
| **ApiClient** | `import.meta.env.VITE_API_BASE_URL`, `AuthContext.accessToken` | All TanStack Query hooks, `InitGuard` |
|
|
| **AuthContext** | `ApiClient` (for login/logout/refresh calls) | `ProtectedRoute`, `RoleGuard`, `Sidebar`, `ProfilePage`, `LoginPage` |
|
|
| **RouterConfig** | `ProtectedRoute`, `RoleGuard`, `InitGuard`, `AppLayout` | App root |
|
|
| **ProtectedRoute** | `AuthContext` | Router (wraps authenticated routes) |
|
|
| **RoleGuard** | `AuthContext` | Router (wraps role-restricted routes) |
|
|
| **InitGuard** | `useSetupStatus` → `ApiClient` | Router (root-level check) |
|
|
| **AppLayout** | `Sidebar`, `ThemeProvider` | Authenticated routes |
|
|
| **Sidebar** | `AuthContext` | `AppLayout` |
|
|
| **useAvailabilityStatus** | `ApiClient` | `DashboardPage`, `SettingsPage` |
|
|
| **useUsers / useInviteUser** | `ApiClient` | `UsersPage` |
|
|
| **useValidateInvitation / useCompleteSetup** | `ApiClient` | `InviteCompletePage` |
|
|
| **useSetupStatus / useCreateOwner** | `ApiClient` | `InitGuard`, `SetupPage` |
|
|
| **DashboardPage** | `useAvailabilityStatus`, `AuthContext` | Router |
|
|
| **UsersPage** | `useUsers`, `useInviteUser`, `InviteUserDialog` | Router |
|
|
| **ProfilePage** | `AuthContext` (user data from context — no API call) | Router |
|
|
| **SettingsPage** | `useAvailabilityStatus` | Router |
|
|
| **InviteCompletePage** | `useValidateInvitation`, `useCompleteSetup` | Router |
|
|
| **LoginPage** | `AuthContext.login()` | Router |
|
|
| **SetupPage** | `useCreateOwner` | Router |
|
|
|
|
---
|
|
|
|
## Communication Patterns
|
|
|
|
| Pattern | Where Used |
|
|
|---------|-----------|
|
|
| **React Context** | Auth state shared from `AuthContext` to guards, sidebar, profile, login page |
|
|
| **TanStack Query** | Server state (availability, users, invitation, setup) — cached, auto-refetch |
|
|
| **Cookie (httpOnly)** | Browser ↔ Backend: refresh token — set by backend, never read by JS |
|
|
| **In-memory state** | Access token held in `AuthContext` — cleared on page refresh (intentional) |
|
|
| **LocalStorage** | Theme preference only (`cms-theme`) — no auth data |
|
|
|
|
---
|
|
|
|
## Key Dependency Rules (Security Baseline)
|
|
|
|
- `ApiClient` is the **only** module that makes HTTP calls — no direct `fetch` in pages/components
|
|
- `accessToken` is accessed **only** through `AuthContext` — never passed as prop or stored elsewhere
|
|
- `refreshToken` is **never accessible to JavaScript** — httpOnly cookie only
|
|
- Role checks happen in `RoleGuard` (routing) and `Sidebar` (UX) — backend is authoritative
|