Files

6.0 KiB

Component Dependencies — CMS Frontend

Dependency Overview

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 useSetupStatusApiClient 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