refactoring-backend #3
@@ -176,6 +176,8 @@ Reference: `Docs/Refactoring.md` for full analysis of each issue.
|
||||
|
||||
**Goal:** Move `useAuth()` into its own file `frontend/src/hooks/useAuth.ts` and `useTimezone()` into `frontend/src/hooks/useTimezone.ts`. Each provider file should only define and export the context object and the provider component. The hooks should import the context from the provider file and re-export it from the `hooks/` directory.
|
||||
|
||||
**Status:** Completed.
|
||||
|
||||
**Possible traps and issues:**
|
||||
- Every file that currently imports `useAuth` from `providers/AuthProvider` must update its import path. Run a global search for `from "../providers/AuthProvider"` and `from "../../providers/AuthProvider"` to find all consumers before moving.
|
||||
- The context object (`AuthContext`, `TimezoneContext`) must remain exported from the provider file so the hook can import it. Do not move the context — only the hook function.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import { Navigate, useLocation } from "react-router-dom";
|
||||
import { useAuth } from "../providers/AuthProvider";
|
||||
import { useAuth } from "../hooks/useAuth";
|
||||
|
||||
interface RequireAuthProps {
|
||||
/** The protected page content to render when authenticated. */
|
||||
|
||||
15
frontend/src/hooks/useAuth.ts
Normal file
15
frontend/src/hooks/useAuth.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useContext } from "react";
|
||||
import { AuthContext, type AuthContextValue } from "../providers/AuthProvider";
|
||||
|
||||
/**
|
||||
* Access authentication state and actions from a mounted AuthProvider.
|
||||
*
|
||||
* @throws {Error} When called outside of `<AuthProvider>`.
|
||||
*/
|
||||
export function useAuth(): AuthContextValue {
|
||||
const ctx = useContext(AuthContext);
|
||||
if (ctx === null) {
|
||||
throw new Error("useAuth must be used within <AuthProvider>.");
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
15
frontend/src/hooks/useTimezone.ts
Normal file
15
frontend/src/hooks/useTimezone.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useContext } from "react";
|
||||
import { TimezoneContext } from "../providers/TimezoneProvider";
|
||||
|
||||
/**
|
||||
* Return the configured IANA timezone from the mounted TimezoneProvider.
|
||||
*
|
||||
* @throws {Error} When called outside of `<TimezoneProvider>`.
|
||||
*/
|
||||
export function useTimezone(): string {
|
||||
const context = useContext(TimezoneContext);
|
||||
if (context === undefined) {
|
||||
throw new Error("useTimezone must be used within <TimezoneProvider>.");
|
||||
}
|
||||
return context.timezone;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
NavigationRegular,
|
||||
} from "@fluentui/react-icons";
|
||||
import { NavLink, Outlet, useNavigate } from "react-router-dom";
|
||||
import { useAuth } from "../providers/AuthProvider";
|
||||
import { useAuth } from "../hooks/useAuth";
|
||||
import { useServerStatus } from "../hooks/useServerStatus";
|
||||
import { useBlocklistStatus } from "../hooks/useBlocklist";
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||
import type { ChangeEvent, FormEvent } from "react";
|
||||
import { ApiError } from "../api/client";
|
||||
import { useAuth } from "../providers/AuthProvider";
|
||||
import { useAuth } from "../hooks/useAuth";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Styles
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
@@ -25,7 +24,7 @@ interface AuthState {
|
||||
expiresAt: string | null;
|
||||
}
|
||||
|
||||
interface AuthContextValue {
|
||||
export interface AuthContextValue {
|
||||
/** `true` when a valid session token is held in state. */
|
||||
isAuthenticated: boolean;
|
||||
/**
|
||||
@@ -41,7 +40,7 @@ interface AuthContextValue {
|
||||
// Context
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const AuthContext = createContext<AuthContextValue | null>(null);
|
||||
export const AuthContext = createContext<AuthContextValue | null>(null);
|
||||
|
||||
const SESSION_KEY = "bangui_token";
|
||||
const SESSION_EXPIRES_KEY = "bangui_expires_at";
|
||||
@@ -97,22 +96,3 @@ export function AuthProvider({
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Hook
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Access authentication state and actions.
|
||||
*
|
||||
* Must be called inside a component rendered within `<AuthProvider>`.
|
||||
*
|
||||
* @throws {Error} When called outside of `<AuthProvider>`.
|
||||
*/
|
||||
export function useAuth(): AuthContextValue {
|
||||
const ctx = useContext(AuthContext);
|
||||
if (ctx === null) {
|
||||
throw new Error("useAuth must be used within <AuthProvider>.");
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -9,19 +9,19 @@
|
||||
* always receive a safe fallback.
|
||||
*/
|
||||
|
||||
import { createContext, useContext, useMemo } from "react";
|
||||
import { createContext, useMemo } from "react";
|
||||
import { useTimezoneData } from "../hooks/useTimezoneData";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Context definition
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
interface TimezoneContextValue {
|
||||
export interface TimezoneContextValue {
|
||||
/** IANA timezone string, e.g. ``"Europe/Berlin"`` or ``"UTC"``. */
|
||||
timezone: string;
|
||||
}
|
||||
|
||||
const TimezoneContext = createContext<TimezoneContextValue>({ timezone: "UTC" });
|
||||
export const TimezoneContext = createContext<TimezoneContextValue | undefined>(undefined);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Provider
|
||||
@@ -53,24 +53,3 @@ export function TimezoneProvider({
|
||||
<TimezoneContext.Provider value={value}>{children}</TimezoneContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Hook
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return the IANA timezone string configured during setup.
|
||||
*
|
||||
* Must be used inside a {@link TimezoneProvider}.
|
||||
*
|
||||
* @returns The configured timezone, e.g. ``"Europe/Berlin"``.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* const { timezone } = useTimezone();
|
||||
* const label = formatDate(item.created_at, timezone);
|
||||
* ```
|
||||
*/
|
||||
export function useTimezone(): string {
|
||||
return useContext(TimezoneContext).timezone;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user