Merge pull request 'this Application is unfinshed and pending works in (UI,Logical Workflows)last git push by Hasan (28/7/2026)' (#19) from hasan_frontend into dev
Reviewed-on: https://gitea.maskantech.in/gitea_admin/productcatalogue_frontend/pulls/19
This commit is contained in:
@@ -4,80 +4,89 @@
|
||||
* Single Responsibility: Orchestrate theme business logic.
|
||||
*
|
||||
* This service is the ONLY layer that knows about both storage and DOM.
|
||||
* It delegates:
|
||||
* - Persistence → theme.storage.ts
|
||||
* - DOM mutation → applyTheme.ts (utils)
|
||||
*
|
||||
* FUTURE API INTEGRATION:
|
||||
* When a backend API is introduced, only this file changes.
|
||||
* The storage layer, DOM utility, context, and hook remain untouched.
|
||||
* Pattern: replace loadTheme() / saveTheme() calls with API calls,
|
||||
* keeping the same method signatures.
|
||||
*
|
||||
* RULES:
|
||||
* - No React imports.
|
||||
* - No JSX.
|
||||
* - No component access.
|
||||
* It delegates persistence to the backend database via REST API.
|
||||
*/
|
||||
|
||||
import type { Theme } from "../types/theme.types";
|
||||
import {
|
||||
loadTheme as storageLoad,
|
||||
saveTheme as storageSave,
|
||||
clearTheme as storageClear,
|
||||
} from "../storage/theme.storage";
|
||||
import apiClient from "../api/axiosInstance";
|
||||
import { applyTheme as applyThemeToDom } from "../utils/applyTheme";
|
||||
import { DEFAULT_THEME, AVAILABLE_THEMES } from "../constants/themes";
|
||||
|
||||
export { DEFAULT_THEME, AVAILABLE_THEMES };
|
||||
|
||||
let currentTheme: Theme = DEFAULT_THEME;
|
||||
|
||||
// Load user theme preference asynchronously during application initialization (module import)
|
||||
try {
|
||||
const token = localStorage.getItem("accessToken");
|
||||
if (token) {
|
||||
const response = await apiClient.get<{ success: boolean; data: { themeCode: string } }>("/api/v1/settings/theme");
|
||||
if (response && response.success && response.data?.themeCode) {
|
||||
const themeCode = response.data.themeCode;
|
||||
const found = AVAILABLE_THEMES.find((t) => t.id === themeCode);
|
||||
if (found) {
|
||||
currentTheme = found;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to load user theme preference asynchronously at startup:", error);
|
||||
}
|
||||
|
||||
// Apply the resolved theme to the DOM immediately prior to React tree mount
|
||||
applyThemeToDom(currentTheme.palette);
|
||||
if (typeof document !== "undefined") {
|
||||
if (currentTheme.mode === "dark") {
|
||||
document.documentElement.classList.add("dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// PUBLIC SERVICE METHODS
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Returns the currently persisted theme from storage.
|
||||
* Falls back to DEFAULT_THEME if nothing is saved or storage fails.
|
||||
* Returns the loaded theme.
|
||||
*/
|
||||
export function getCurrentTheme(): Theme {
|
||||
const saved = storageLoad();
|
||||
if (!saved) return DEFAULT_THEME;
|
||||
// If the saved theme id still exists in the registry, use it.
|
||||
// Otherwise (e.g. default changed), fall back to DEFAULT_THEME.
|
||||
const exists = AVAILABLE_THEMES.some((t) => t.id === saved.id);
|
||||
return exists ? saved : DEFAULT_THEME;
|
||||
return currentTheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all themes available for selection.
|
||||
* Future: merge with API-fetched tenant themes.
|
||||
*/
|
||||
export function getAvailableThemes(): Theme[] {
|
||||
return AVAILABLE_THEMES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists a theme to storage.
|
||||
* Does NOT apply it to the DOM — call applyTheme() separately if needed.
|
||||
* Persists a theme to the backend database.
|
||||
*
|
||||
* @param theme - The theme to persist.
|
||||
*/
|
||||
export function saveTheme(theme: Theme): void {
|
||||
storageSave(theme);
|
||||
currentTheme = theme;
|
||||
const themeCode = (theme as any).code || theme.id;
|
||||
apiClient.put("/api/v1/settings/theme", { themeCode })
|
||||
.catch((err) => {
|
||||
console.error("Failed to save theme preference to DB:", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets to the default theme:
|
||||
* 1. Clears persisted theme from storage.
|
||||
* 2. Removes all runtime CSS variable overrides from the DOM.
|
||||
* The static @theme values in index.css take effect again.
|
||||
* Resets to the default theme.
|
||||
*
|
||||
* @returns The default theme, so the caller can update its state.
|
||||
*/
|
||||
export function resetTheme(): Theme {
|
||||
storageClear();
|
||||
// Apply explicitly so the DOM reflects DEFAULT_THEME (Royal Purple),
|
||||
// matching the static @theme values in index.css.
|
||||
currentTheme = DEFAULT_THEME;
|
||||
apiClient.put("/api/v1/settings/theme", { themeCode: DEFAULT_THEME.id })
|
||||
.catch((err) => {
|
||||
console.error("Failed to reset theme preference on DB:", err);
|
||||
});
|
||||
|
||||
applyThemeToDom(DEFAULT_THEME.palette);
|
||||
if (typeof document !== "undefined") {
|
||||
document.documentElement.classList.remove("dark");
|
||||
|
||||
Reference in New Issue
Block a user