# Component Methods — CMS Frontend > **Note**: Detailed business rules and logic are defined per-unit in the Functional Design stage (CONSTRUCTION phase). This document captures method signatures, inputs, outputs, and high-level purpose only. --- ## Backend — AuthController (updated) ```csharp // POST /api/v1/auth/login // Body: LoginRequest { Email, Password } // Sets: Set-Cookie: refreshToken=; HttpOnly; Secure; SameSite=Strict; Path=/api/v1/auth // Returns: { accessToken: string, expiresAt: datetime, user: { id, email, name, role, isActive } } Task Login(LoginRequest request) // POST /api/v1/auth/refresh // Reads: Cookie: refreshToken // Sets: Set-Cookie: refreshToken=; HttpOnly; Secure; SameSite=Strict; Path=/api/v1/auth // Returns: { accessToken: string, expiresAt: datetime, user: { id, email, name, role, isActive } } Task Refresh() // no body parameter — reads from cookie // POST /api/v1/auth/revoke // Requires: Authorization: Bearer // Reads: Cookie: refreshToken // Clears: Set-Cookie: refreshToken=; Expires=epoch; Path=/api/v1/auth // Returns: 204 No Content Task Revoke() // no body parameter — reads from cookie ``` ## Backend — ServiceCollectionExtensions (updated) ```csharp // Registers CORS policy "FrontendPolicy" using Cors:AllowedOrigins from configuration // Called in AddCoreInfrastructure() static void AddCorsFrontendPolicy(this IServiceCollection services, IConfiguration configuration) // Adds app.UseCors("FrontendPolicy") to the pipeline // Called in Program.cs after UseExceptionHandler, before UseAuthentication static void UseFrontendCors(this WebApplication app) ``` --- ## Frontend — ApiClient (`frontend/src/api/client.ts`) ```typescript // Base configured fetch wrapper; sets Authorization header and credentials: 'include' // Retries once on 401 after calling authContext.refresh() function createApiClient(getAccessToken: () => string | null, refresh: () => Promise): ApiClient // Typed GET request async function get(path: string, options?: RequestInit): Promise // Typed POST request async function post(path: string, body: unknown, options?: RequestInit): Promise ``` ## Frontend — AuthContext (`frontend/src/auth/AuthContext.tsx`) ```typescript interface AuthContextValue { isAuthenticated: boolean isLoading: boolean // true during initial session restore user: User | null // { id, email, name, role, isActive } accessToken: string | null // in-memory only, never in localStorage login(email: string, password: string): Promise logout(): Promise refresh(): Promise // called by ApiClient on 401; restores token from cookie } // Hook function useAuth(): AuthContextValue ``` ## Frontend — Route Guards ```typescript // ProtectedRoute: renders children if authenticated, redirects to /login otherwise // Used as a TanStack Router beforeLoad or as a wrapper component function ProtectedRoute({ children }: { children: ReactNode }): JSX.Element // RoleGuard: renders children if user.role is in allowedRoles, redirects to /403 otherwise function RoleGuard({ allowedRoles, children }: { allowedRoles: string[], children: ReactNode }): JSX.Element // InitGuard: checks GET /setup/status on app load; redirects to /setup if not initialized function InitGuard({ children }: { children: ReactNode }): JSX.Element ``` ## Frontend — TanStack Query hooks (`frontend/src/api/`) ```typescript // Fetch current availability status; staleTime: 30s function useAvailabilityStatus(): UseQueryResult // Fetch user list; staleTime: 60s function useUsers(): UseQueryResult // Invite a user; invalidates useUsers on success function useInviteUser(): UseMutationResult // Complete invitation setup (public, no auth required) function useCompleteSetup(): UseMutationResult // Validate invitation token (public) function useValidateInvitation(token: string): UseQueryResult ``` ## Frontend — Page component signatures ```typescript // All page components are default exports used as TanStack Router route components export default function LoginPage(): JSX.Element export default function SetupPage(): JSX.Element export default function InviteCompletePage(): JSX.Element // reads token from search params export default function DashboardPage(): JSX.Element export default function UsersPage(): JSX.Element export default function ProfilePage(): JSX.Element export default function SettingsPage(): JSX.Element export default function CmsPage(): JSX.Element export default function NotFoundPage(): JSX.Element export default function AccessDeniedPage(): JSX.Element ``` ## Frontend — Shared components ```typescript // Availability badge with colour-coding function AvailabilityStatusBadge({ status, message }: { status: 'Available' | 'Maintenance' | 'Unavailable' message?: string }): JSX.Element // Two-step invite dialog function InviteUserDialog({ open, onClose }: { open: boolean onClose: () => void }): JSX.Element // Error boundary — class component wrapping children class ErrorBoundary extends React.Component<{ fallback?: ReactNode children: ReactNode }> ``` --- ## TypeScript Type Definitions (`frontend/src/api/types.ts`) ```typescript interface User { id: string email: string name: string role: 'Owner' | 'Admin' | 'User' isActive: boolean } interface AuthResponse { accessToken: string expiresAt: string // ISO datetime user: User } interface AvailabilityStatusResponse { status: 'Available' | 'Maintenance' | 'Unavailable' checkedAt: string // ISO datetime message?: string } interface InviteUserRequest { email: string role: 'Admin' | 'User' } interface InviteResponse { inviteLink: string } interface CompleteSetupRequest { token: string displayName: string password: string } interface InvitationValidationResponse { valid: boolean email: string role: string } ```