Consolidate frontend storage keys into constants module

- Move magic strings from AuthProvider, MainLayout, and ThemeProvider to
  frontend/src/utils/constants.ts
- Add STORAGE_KEY_AUTHENTICATED, STORAGE_KEY_SIDEBAR_COLLAPSED, and
  STORAGE_KEY_THEME constants with JSDoc descriptions
- Update all three files to import and use centralized keys
- Prevents key drift and typo regressions across the frontend

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-28 09:48:28 +02:00
parent 72c4a0ed04
commit 252204ed97
5 changed files with 29 additions and 31 deletions

View File

@@ -44,6 +44,7 @@ import { useNavigate } from "react-router-dom";
import * as authApi from "../api/auth";
import { setUnauthorizedHandler } from "../api/client";
import { setAuthErrorHandler } from "../utils/fetchError";
import { STORAGE_KEY_AUTHENTICATED } from "../utils/constants";
import { SessionValidationLoading } from "../components/SessionValidationLoading";
import { useSessionValidation } from "../hooks/useSessionValidation";
@@ -65,8 +66,6 @@ export interface AuthContextValue {
export const AuthContext = createContext<AuthContextValue | null>(null);
const IS_AUTHENTICATED_KEY = "bangui_authenticated";
// ---------------------------------------------------------------------------
// Provider
// ---------------------------------------------------------------------------
@@ -87,14 +86,14 @@ export function AuthProvider({
children: React.ReactNode;
}): React.JSX.Element {
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(() => {
const stored = sessionStorage.getItem(IS_AUTHENTICATED_KEY);
const stored = sessionStorage.getItem(STORAGE_KEY_AUTHENTICATED);
return stored === "true";
});
const [isValidating, setIsValidating] = useState<boolean>(isAuthenticated);
const navigate = useNavigate();
const handleSessionExpired = useCallback((): void => {
sessionStorage.removeItem(IS_AUTHENTICATED_KEY);
sessionStorage.removeItem(STORAGE_KEY_AUTHENTICATED);
setIsAuthenticated(false);
navigate("/login", { replace: true });
}, [navigate]);
@@ -136,7 +135,7 @@ export function AuthProvider({
const login = useCallback(async (password: string): Promise<void> => {
await authApi.login(password);
sessionStorage.setItem(IS_AUTHENTICATED_KEY, "true");
sessionStorage.setItem(STORAGE_KEY_AUTHENTICATED, "true");
setIsAuthenticated(true);
}, []);
@@ -145,7 +144,7 @@ export function AuthProvider({
await authApi.logout();
} finally {
// Always clear local state even if the API call fails (e.g. expired session).
sessionStorage.removeItem(IS_AUTHENTICATED_KEY);
sessionStorage.removeItem(STORAGE_KEY_AUTHENTICATED);
setIsAuthenticated(false);
}
}, []);

View File

@@ -1,5 +1,6 @@
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import type { ReactNode } from "react";
import { STORAGE_KEY_THEME } from "../utils/constants";
type ThemeMode = "light" | "dark";
@@ -10,12 +11,11 @@ interface ThemeProviderContext {
hasExplicitPreference: boolean;
}
const THEME_STORAGE_KEY = "bangui_theme";
const ThemeModeContext = createContext<ThemeProviderContext | null>(null);
function readSavedTheme(): ThemeMode | null {
try {
const value = localStorage.getItem(THEME_STORAGE_KEY);
const value = localStorage.getItem(STORAGE_KEY_THEME);
if (value === "dark" || value === "light") {
return value;
}
@@ -40,7 +40,7 @@ export function ThemeProvider({ children }: ThemeProviderProps): React.JSX.Eleme
const setColorMode = useCallback((mode: ThemeMode): void => {
try {
localStorage.setItem(THEME_STORAGE_KEY, mode);
localStorage.setItem(STORAGE_KEY_THEME, mode);
} catch {
// Ignore storage failures.
}