Skip to content

Commit

Permalink
light/dark theme feature done
Browse files Browse the repository at this point in the history
  • Loading branch information
Guillaume_Bernier committed Apr 8, 2024
1 parent 44869ef commit 7162ab4
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 44 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ A user-friendly app for tracking business expenses and revenue, designed to simp

## Features
- [x] Login, registration, reset password, logout
- [ ] Light/Dark theme
- [x] Light/Dark theme
- [ ] Edit user profile
***
Release v0.1
Expand Down
23 changes: 23 additions & 0 deletions app/src/routes/(app)/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { fail } from "@sveltejs/kit";

export async function load({ locals }) {
try {
if (!locals.pb.authStore.model) {
console.log('No authenticated user found.');
return fail(401, { message: 'No authenticated user found.' });
}

const userId = locals.pb.authStore.model.id;

const record = await locals.pb.collection('users').getOne(userId);
const theme: "light" | "dark" = record.theme || 'system';
return {
props: {
theme,
}
};
} catch (err) {
console.log('Error on loading theme: ', err);
return { status: 500, error: new Error('Internal server error') };
}
};
8 changes: 7 additions & 1 deletion app/src/routes/(app)/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import '$lib/app.pcss';
import { ModeWatcher } from 'mode-watcher';
import { ModeWatcher, setMode } from 'mode-watcher';
import { page } from '$app/stores';
import { Button } from '$lib/components/ui/button/index.js';
Expand All @@ -9,6 +9,9 @@
import Menu from 'lucide-svelte/icons/menu';
import CircleUser from 'lucide-svelte/icons/circle-user';
import Book from 'lucide-svelte/icons/book';
import { onMount } from 'svelte';
export let data: any;
let theme: 'light' | 'dark' | 'system' = data.props.theme;
let navItem = [
{
Expand All @@ -24,6 +27,9 @@
url: '/admin/settings'
}
];
onMount(() => {
setMode(theme);
});
</script>

<ModeWatcher />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import type { PageServerLoad } from "./$types.js";
import { formSchema } from "./schema";

export const load: PageServerLoad = async () => {
return {
form: await superValidate(zod(formSchema)),
};
return {
form: await superValidate(zod(formSchema))
};
};

export const actions: Actions = {
Expand All @@ -16,17 +16,17 @@ export const actions: Actions = {
const form = await superValidate(formData, zod(formSchema));

try {
// Check if authStore.model is not null
if (!locals.pb.authStore.model) {
// Check if authStore.model is not null
if (!locals.pb.authStore.model) {
console.log('No authenticated user found.');
return fail(401,{ message: 'No authenticated user found.' });
return fail(401, { message: 'No authenticated user found.' });
}

const userId = locals.pb.authStore.model.id;

const data = {
"theme": form.data.theme
}
const data = {
"theme": form.data.theme
}
const record = await locals.pb.collection('users').update(userId, data);
} catch (err) {
console.log('Error on updating theme: ', err);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<script lang="ts">
import type { PageData } from "./$types.js";
import AppearanceForm from "./appearance-form.svelte";
import { Separator } from "$lib/components/ui/separator";
import type { PageData } from './$types.js';
import AppearanceForm from './appearance-form.svelte';
import { Separator } from '$lib/components/ui/separator';
export let data: PageData;
let formData: any = data.form;
let theme: any = data.props?.theme;
</script>

<div class="space-y-6">
<div>
<h3 class="text-lg font-medium">Appearance</h3>
<p class="text-sm text-muted-foreground">
<p class="text-muted-foreground text-sm">
Customize the appearance of the app. Automatically switch between day and night themes.
</p>
</div>
<Separator />
<AppearanceForm data={data.form} />
</div>
<AppearanceForm data={formData} {theme} />
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { setMode } from 'mode-watcher';
export let data: SuperValidated<Infer<FormSchema>>;
export let theme: any;
const form = superForm(data, {
validators: zodClient(formSchema)
Expand All @@ -22,51 +23,29 @@
</script>

<form method="POST" use:enhance class="space-y-8">
<Form.Field {form} name="font">
<Form.Control let:attrs>
<Form.Label>Font</Form.Label>
<div class="relative w-max">
<select
{...attrs}
class={cn(
buttonVariants({ variant: 'outline' }),
'w-[200px] appearance-none font-normal'
)}
bind:value={$formData.font}
>
<option value="inter">Inter</option>
<option value="manrope">Manrope</option>
<option value="system">System</option>
</select>
<ChevronDown class="absolute right-3 top-2.5 size-4 opacity-50" />
</div>
</Form.Control>
<Form.Description>Set the font you want to use in the dashboard.</Form.Description>
<Form.FieldErrors />
</Form.Field>
<Form.Fieldset {form} name="theme">
<Form.Legend>Theme</Form.Legend>
<Form.Description>Select the theme for the dashboard.</Form.Description>
<Form.FieldErrors />
<RadioGroup.Root
class="grid max-w-md grid-cols-2 gap-8 pt-2"
orientation="horizontal"
bind:value={$formData.theme}
bind:value={theme}
>
<Form.Control let:attrs>
<Label class="[&:has([data-state=checked])>div]:border-primary">
<RadioGroup.Item {...attrs} value="light" class="sr-only" on:click={() => setMode('light')} />
<RadioGroup.Item {...attrs} value="light" class="sr-only" />
<ThemeBlock theme="light" />
</Label>
</Form.Control>
<Form.Control let:attrs>
<Label class="[&:has([data-state=checked])>div]:border-primary">
<RadioGroup.Item {...attrs} value="dark" class="sr-only" on:click={() => setMode('dark')} />
<RadioGroup.Item {...attrs} value="dark" class="sr-only" />
<ThemeBlock theme="dark" />
</Label>
</Form.Control>
<RadioGroup.Input name="theme" />
</RadioGroup.Root>
</Form.Fieldset>
<Form.Button>Update preferences</Form.Button>
<Form.Button on:click={() => setMode(theme)}>Update preferences</Form.Button>
</form>
49 changes: 49 additions & 0 deletions backend/pb_migrations/1712617519_updated_users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/// <reference path="../pb_data/types.d.ts" />
migrate((db) => {
const dao = new Dao(db)
const collection = dao.findCollectionByNameOrId("_pb_users_auth_")

// update
collection.schema.addField(new SchemaField({
"system": false,
"id": "cz5ruofb",
"name": "theme",
"type": "select",
"required": false,
"presentable": false,
"unique": false,
"options": {
"maxSelect": 1,
"values": [
"dark",
"light",
"system"
]
}
}))

return dao.saveCollection(collection)
}, (db) => {
const dao = new Dao(db)
const collection = dao.findCollectionByNameOrId("_pb_users_auth_")

// update
collection.schema.addField(new SchemaField({
"system": false,
"id": "cz5ruofb",
"name": "theme",
"type": "select",
"required": false,
"presentable": false,
"unique": false,
"options": {
"maxSelect": 1,
"values": [
"dark",
"light"
]
}
}))

return dao.saveCollection(collection)
})

0 comments on commit 7162ab4

Please sign in to comment.