69 lines
2.3 KiB
TypeScript
69 lines
2.3 KiB
TypeScript
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||
import { ThemeType } from '../../types/theme';
|
||
import {
|
||
LIGHT_THEME,
|
||
DARK_THEME,
|
||
PINK_THEME,
|
||
BLUE_THEME,
|
||
GREEN_THEME,
|
||
PURPLE_THEME,
|
||
THEMES,
|
||
getNextTheme
|
||
} from '../../utils/themes';
|
||
|
||
// Ключ для хранения текущей темы в localStorage
|
||
const THEME_STORAGE_KEY = 'journal-pl-theme';
|
||
|
||
// Получаем сохраненную тему из localStorage или используем светлую тему по умолчанию
|
||
const getSavedTheme = (): ThemeType => {
|
||
if (typeof window !== 'undefined') {
|
||
const savedTheme = localStorage.getItem(THEME_STORAGE_KEY) as ThemeType | null;
|
||
if (savedTheme && THEMES.includes(savedTheme as ThemeType)) {
|
||
return savedTheme as ThemeType;
|
||
}
|
||
}
|
||
// По умолчанию используем светлую тему
|
||
return LIGHT_THEME;
|
||
};
|
||
|
||
interface ThemeState {
|
||
currentTheme: ThemeType;
|
||
}
|
||
|
||
const initialState: ThemeState = {
|
||
currentTheme: getSavedTheme(),
|
||
};
|
||
|
||
export const themeSlice = createSlice({
|
||
name: 'theme',
|
||
initialState,
|
||
reducers: {
|
||
setTheme: (state, action: PayloadAction<ThemeType>) => {
|
||
state.currentTheme = action.payload;
|
||
|
||
// Сохраняем выбранную тему в localStorage
|
||
if (typeof window !== 'undefined') {
|
||
localStorage.setItem(THEME_STORAGE_KEY, action.payload);
|
||
}
|
||
},
|
||
cycleNextTheme: (state) => {
|
||
state.currentTheme = getNextTheme(state.currentTheme);
|
||
|
||
// Сохраняем выбранную тему в localStorage
|
||
if (typeof window !== 'undefined') {
|
||
localStorage.setItem(THEME_STORAGE_KEY, state.currentTheme);
|
||
}
|
||
},
|
||
},
|
||
});
|
||
|
||
export const { setTheme, cycleNextTheme } = themeSlice.actions;
|
||
|
||
// Селекторы для получения информации о текущей теме
|
||
export const selectCurrentTheme = (state: { theme: ThemeState }) => state.theme.currentTheme;
|
||
export const selectIsLightVariant = (state: { theme: ThemeState }) =>
|
||
[LIGHT_THEME, PINK_THEME, BLUE_THEME, GREEN_THEME].includes(state.theme.currentTheme);
|
||
export const selectIsDarkVariant = (state: { theme: ThemeState }) =>
|
||
[DARK_THEME, PURPLE_THEME].includes(state.theme.currentTheme);
|
||
|
||
export default themeSlice.reducer;
|