feat: save user theme preference

This commit is contained in:
Sonny
2024-11-15 23:16:47 +01:00
parent 01298661a5
commit 2f820bb877
5 changed files with 22 additions and 14 deletions

View File

@@ -1,2 +1,3 @@
export const PREFER_DARK_THEME = 'prefer_dark_theme'; export const KEY_USER_THEME = 'user_theme';
export const DARK_THEME_DEFAULT_VALUE = true; export const THEMES = ['dark', 'light'] as const;
export const DEFAULT_USER_THEME = THEMES.at(0);

View File

@@ -1,12 +1,11 @@
import { PREFER_DARK_THEME } from '#user/constants/theme'; import { KEY_USER_THEME } from '#user/constants/theme';
import { updateThemeValidator } from '#user/validators/update_theme_validator'; import { updateThemeValidator } from '#user/validators/update_theme_validator';
import type { HttpContext } from '@adonisjs/core/http'; import type { HttpContext } from '@adonisjs/core/http';
export default class ThemeController { export default class ThemeController {
async index({ request, session, response }: HttpContext) { async index({ request, session, response }: HttpContext) {
const { preferDarkTheme } = const { theme } = await request.validateUsing(updateThemeValidator);
await request.validateUsing(updateThemeValidator); session.put(KEY_USER_THEME, theme);
session.put(PREFER_DARK_THEME, preferDarkTheme);
return response.ok({ message: 'ok' }); return response.ok({ message: 'ok' });
} }
} }

View File

@@ -1,7 +1,8 @@
import { THEMES } from '#user/constants/theme';
import vine from '@vinejs/vine'; import vine from '@vinejs/vine';
export const updateThemeValidator = vine.compile( export const updateThemeValidator = vine.compile(
vine.object({ vine.object({
preferDarkTheme: vine.boolean(), theme: vine.enum(THEMES),
}) })
); );

View File

@@ -1,8 +1,5 @@
import { isSSREnableForPage } from '#config/ssr'; import { isSSREnableForPage } from '#config/ssr';
import { import { DEFAULT_USER_THEME, KEY_USER_THEME } from '#user/constants/theme';
DARK_THEME_DEFAULT_VALUE,
PREFER_DARK_THEME,
} from '#user/constants/theme';
import logger from '@adonisjs/core/services/logger'; import logger from '@adonisjs/core/services/logger';
import { defineConfig } from '@adonisjs/inertia'; import { defineConfig } from '@adonisjs/inertia';
@@ -17,8 +14,9 @@ export default defineConfig({
*/ */
sharedData: { sharedData: {
errors: (ctx) => ctx.session?.flashMessages.get('errors'), errors: (ctx) => ctx.session?.flashMessages.get('errors'),
preferDarkTheme: (ctx) => user: (ctx) => ({
ctx.session?.get(PREFER_DARK_THEME, DARK_THEME_DEFAULT_VALUE), theme: ctx.session?.get(KEY_USER_THEME, DEFAULT_USER_THEME),
}),
auth: async (ctx) => { auth: async (ctx) => {
await ctx.auth?.check(); await ctx.auth?.check();
return { return {

View File

@@ -1,13 +1,22 @@
import { ActionIcon, useMantineColorScheme } from '@mantine/core'; import { ActionIcon, useMantineColorScheme } from '@mantine/core';
import { TbMoonStars, TbSun } from 'react-icons/tb'; import { TbMoonStars, TbSun } from 'react-icons/tb';
import { makeRequest } from '~/lib/request';
export function MantineThemeSwitcher() { export function MantineThemeSwitcher() {
const { colorScheme, toggleColorScheme } = useMantineColorScheme(); const { colorScheme, toggleColorScheme } = useMantineColorScheme();
const handleThemeChange = () => {
toggleColorScheme();
makeRequest({
url: '/user/theme',
method: 'POST',
body: { theme: colorScheme === 'dark' ? 'light' : 'dark' },
});
};
return ( return (
<ActionIcon <ActionIcon
variant="light" variant="light"
aria-label="Toggle color scheme" aria-label="Toggle color scheme"
onClick={() => toggleColorScheme()} onClick={handleThemeChange}
size="lg" size="lg"
> >
{colorScheme === 'dark' ? <TbSun /> : <TbMoonStars />} {colorScheme === 'dark' ? <TbSun /> : <TbMoonStars />}