// ** React Imports import { createContext, useState, ReactNode, useEffect } from 'react' // ** MUI Imports import { Direction } from '@mui/material' // ** ThemeConfig Import import themeConfig from 'src/configs/themeConfig' // ** Types Import import { Skin, Mode, AppBar, Footer, ThemeColor, ContentWidth, VerticalNavToggle } from 'src/@core/layouts/types' export type Settings = { skin: Skin mode: Mode appBar?: AppBar footer?: Footer navHidden?: boolean // navigation menu appBarBlur: boolean direction: Direction navCollapsed: boolean themeColor: ThemeColor contentWidth: ContentWidth layout?: 'vertical' | 'horizontal' lastLayout?: 'vertical' | 'horizontal' verticalNavToggleType: VerticalNavToggle toastPosition?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' } export type PageSpecificSettings = { skin?: Skin mode?: Mode appBar?: AppBar footer?: Footer navHidden?: boolean // navigation menu appBarBlur?: boolean direction?: Direction navCollapsed?: boolean themeColor?: ThemeColor contentWidth?: ContentWidth layout?: 'vertical' | 'horizontal' lastLayout?: 'vertical' | 'horizontal' verticalNavToggleType?: VerticalNavToggle toastPosition?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' } export type SettingsContextValue = { settings: Settings saveSettings: (updatedSettings: Settings) => void } interface SettingsProviderProps { children: ReactNode pageSettings?: PageSpecificSettings | void } const initialSettings: Settings = { themeColor: 'primary', mode: themeConfig.mode, skin: themeConfig.skin, footer: themeConfig.footer, layout: themeConfig.layout, lastLayout: themeConfig.layout, direction: themeConfig.direction, navHidden: themeConfig.navHidden, appBarBlur: themeConfig.appBarBlur, navCollapsed: themeConfig.navCollapsed, contentWidth: themeConfig.contentWidth, toastPosition: themeConfig.toastPosition, verticalNavToggleType: themeConfig.verticalNavToggleType, appBar: themeConfig.layout === 'horizontal' && themeConfig.appBar === 'hidden' ? 'fixed' : themeConfig.appBar } const staticSettings = { appBar: initialSettings.appBar, footer: initialSettings.footer, layout: initialSettings.layout, navHidden: initialSettings.navHidden, lastLayout: initialSettings.lastLayout, toastPosition: initialSettings.toastPosition } const restoreSettings = (): Settings | null => { let settings = null try { const storedData: string | null = window.localStorage.getItem('settings') if (storedData) { settings = { ...JSON.parse(storedData), ...staticSettings } } else { settings = initialSettings } } catch (err) { console.error(err) } return settings } // set settings in localStorage const storeSettings = (settings: Settings) => { const initSettings = Object.assign({}, settings) delete initSettings.appBar delete initSettings.footer delete initSettings.layout delete initSettings.navHidden delete initSettings.lastLayout delete initSettings.toastPosition window.localStorage.setItem('settings', JSON.stringify(initSettings)) } // ** Create Context export const SettingsContext = createContext({ saveSettings: () => null, settings: initialSettings }) export const SettingsProvider = ({ children, pageSettings }: SettingsProviderProps) => { // ** State const [settings, setSettings] = useState({ ...initialSettings }) useEffect(() => { const restoredSettings = restoreSettings() if (restoredSettings) { setSettings({ ...restoredSettings }) } if (pageSettings) { setSettings({ ...settings, ...pageSettings }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [pageSettings]) useEffect(() => { if (settings.layout === 'horizontal' && settings.mode === 'semi-dark') { saveSettings({ ...settings, mode: 'light' }) } if (settings.layout === 'horizontal' && settings.appBar === 'hidden') { saveSettings({ ...settings, appBar: 'fixed' }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [settings.layout]) const saveSettings = (updatedSettings: Settings) => { storeSettings(updatedSettings) setSettings(updatedSettings) } return {children} } export const SettingsConsumer = SettingsContext.Consumer