81 lines
2.9 KiB
TypeScript
81 lines
2.9 KiB
TypeScript
'use client';
|
|
|
|
import { ThemeConfig, defaultTheme } from '@/types/theme';
|
|
import { createContext, useContext, useEffect, useState } from 'react';
|
|
import { themeApi } from '@/lib/api/theme';
|
|
|
|
interface DynamicThemeContextType {
|
|
theme: ThemeConfig;
|
|
setTheme: (theme: ThemeConfig) => void;
|
|
}
|
|
|
|
const DynamicThemeContext = createContext<DynamicThemeContextType>({
|
|
theme: defaultTheme,
|
|
setTheme: () => { },
|
|
});
|
|
|
|
export const useDynamicTheme = () => useContext(DynamicThemeContext);
|
|
|
|
interface DynamicThemeProviderProps {
|
|
children: React.ReactNode;
|
|
initialTheme?: ThemeConfig;
|
|
}
|
|
|
|
export function DynamicThemeProvider({ children, initialTheme }: DynamicThemeProviderProps) {
|
|
const [theme, setTheme] = useState<ThemeConfig>(initialTheme || defaultTheme);
|
|
|
|
// Fetch theme on mount
|
|
useEffect(() => {
|
|
const fetchTheme = async () => {
|
|
try {
|
|
const response = await themeApi.getTheme();
|
|
// @ts-ignore - The API response wrapper might be generic, assuming response.data is the payload if wrapped, or response if not.
|
|
// Based on standard axios + nestjs wrapper: response.data.data or response is the data.
|
|
// Let's assume our client unwraps it or we check.
|
|
// If createApiClient returns axios instance, .get returns AxiosResponse.
|
|
// api-service.ts unwraps response.data.
|
|
// BUT theme.ts calls client.get directly.
|
|
// Let's fix theme.ts to use apiRequest or handle .data
|
|
|
|
// Correction: theme.ts uses client.get. client is axios instance.
|
|
// So response is AxiosResponse. response.data is the body ({ success, data: theme }).
|
|
if (response.data && response.data.success && response.data.data) {
|
|
setTheme(response.data.data);
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to fetch theme:', error);
|
|
}
|
|
};
|
|
fetchTheme();
|
|
}, []);
|
|
|
|
// Apply theme to CSS variables
|
|
useEffect(() => {
|
|
if (!theme) return;
|
|
|
|
const root = document.documentElement;
|
|
|
|
root.style.setProperty('--chakra-colors-primary-500', theme.primaryColor);
|
|
// ... rest of logic
|
|
root.style.setProperty('--chakra-colors-primary-600', theme.secondaryColor);
|
|
|
|
// Backgrounds for the app
|
|
if (theme.backgroundColor) {
|
|
root.style.setProperty('--app-background', theme.backgroundColor);
|
|
}
|
|
|
|
if (theme.backgroundImage) {
|
|
root.style.setProperty('--app-background-image', `url(${theme.backgroundImage})`);
|
|
} else {
|
|
root.style.removeProperty('--app-background-image');
|
|
}
|
|
|
|
}, [theme]);
|
|
|
|
return (
|
|
<DynamicThemeContext.Provider value={{ theme, setTheme }}>
|
|
{children}
|
|
</DynamicThemeContext.Provider>
|
|
);
|
|
}
|