Set persistent theme on cookies

This commit is contained in:
La macchina desiderante 2024-05-11 17:33:04 +02:00
parent 295fc4dadb
commit 581e5704d4
5 changed files with 65 additions and 29 deletions

View File

@ -0,0 +1,31 @@
'use client'
import React from 'react';
import { AppProgressBar as ProgressBar } from 'next-nprogress-bar';
import { LAYOUT_COLORS_PINK, LAYOUT_COLORS_YELLOW } from '@/constants/colors';
import { Themes } from '@/meta/settings';
interface Props {
theme?: Themes
}
const Body: React.FC<Props & React.PropsWithChildren> = (props) => {
const { theme, children } = props;
return (
<body>
<main className="container">{children}</main>
<ProgressBar
height="4px"
color={theme == Themes.dark ? LAYOUT_COLORS_YELLOW : LAYOUT_COLORS_PINK}
options={{ showSpinner: false }}
shallowRouting
/>
</body>
);
};
export default Body;

View File

@ -1,36 +1,26 @@
'use client'
import React from 'react'; import React from 'react';
import Head from 'next/head'; import Head from 'next/head';
import { AppProgressBar as ProgressBar } from 'next-nprogress-bar';
import { useAppSelector } from '@/store/store';
import { LAYOUT_COLORS_PINK, LAYOUT_COLORS_YELLOW } from '@/constants/colors';
import { Themes } from '@/meta/settings'; import { Themes } from '@/meta/settings';
const Content: React.FC<React.PropsWithChildren> = (props) => { import Body from './Body';
const { children } = props; interface Props {
theme?: Themes
}
const theme = useAppSelector((state) => state.settings.theme); const Content: React.FC<Props & React.PropsWithChildren> = (props) => {
const { theme, children } = props;
return ( return (
<html data-theme={theme} /*lang={locale}*/> <html data-theme={theme}>
<Head> <Head>
<meta charSet="utf-8" /> <meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
</Head> </Head>
<body> <Body theme={theme}>{children}</Body>
<main className="container">{children}</main>
<ProgressBar
height="4px"
color={theme == Themes.dark ? LAYOUT_COLORS_YELLOW : LAYOUT_COLORS_PINK}
options={{ showSpinner: false }}
shallowRouting
/>
</body>
</html> </html>
); );
}; };

View File

@ -3,23 +3,29 @@
import React from 'react'; import React from 'react';
import { TbMoon, TbSun } from 'react-icons/tb'; import { TbMoon, TbSun } from 'react-icons/tb';
import { useAppDispatch, useAppSelector } from '@/store/store'; import { DEFAULT_THEME, Themes } from '@/meta/settings';
import { Themes } from '@/meta/settings';
import { setCurrentTheme } from '@/store/settingsSlice';
import Icon from '../Icon'; import Icon from '../Icon';
import { setCookie } from '@/utils/cookies/write';
import { useCookies } from 'react-cookie';
const Menu: React.FC = () => { const Theme: React.FC = () => {
const theme = useAppSelector((state) => state.settings.theme); const [cookies] = useCookies(['theme']);
const dispatch = useAppDispatch();
const theme = cookies.theme ?? DEFAULT_THEME
const handleClick = async () => {
const newTheme = theme == Themes.dark ? Themes.light : Themes.dark
await setCookie('theme', newTheme)
}
return ( return (
<Icon handleClick={() => dispatch(setCurrentTheme(theme == Themes.dark ? Themes.light : Themes.dark))}> <Icon handleClick={handleClick}>
{theme == Themes.dark && <TbMoon size={24} />} {theme == Themes.dark && <TbMoon size={24} />}
{theme == Themes.light && <TbSun size={24} />} {theme == Themes.light && <TbSun size={24} />}
</Icon> </Icon>
); );
}; };
export default Menu; export default Theme;

View File

@ -1,15 +1,22 @@
import React from 'react'; import React from 'react';
import { cookies } from 'next/headers'
import WithRedux from '@/store/withRedux'; import WithRedux from '@/store/withRedux';
import Content from './Content'; import Content from './Content';
import { DEFAULT_THEME, Themes } from '@/meta/settings';
const Layout: React.FC<React.PropsWithChildren> = (props) => { const Layout: React.FC<React.PropsWithChildren> = (props) => {
const { children } = props; const { children } = props;
const cookieStore = cookies()
const theme = cookieStore.get('theme')
return ( return (
<WithRedux> <WithRedux>
<Content> <Content theme={theme ? theme?.value as Themes : DEFAULT_THEME}>
{children} {children}
</Content> </Content>
</WithRedux> </WithRedux>

View File

@ -5,9 +5,11 @@ export enum Platforms {
export enum Themes { export enum Themes {
light= 'light', light= 'light',
dark= 'dark' dark= 'dark',
} }
export const DEFAULT_THEME = Themes.light
export interface LangOption { export interface LangOption {
label: string; label: string;
code: string; code: string;