From 960673bbc667b36545f3cd3da3ffbf5efb800087 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Fri, 11 Sep 2026 12:49:46 -0500 Subject: [PATCH] Add a site-wide dark mode --- src/app.html | 13 ++ src/lib/components/DashboardSection.svelte | 4 +- src/lib/components/DataTable.svelte | 24 ++- src/lib/components/admin/AdminModal.svelte | 10 +- src/lib/components/admin/Toast.svelte | 6 +- src/lib/components/containers/Window.svelte | 4 +- .../(protected)/(user)/dashboard/+page.svelte | 66 +++++-- .../(protected)/(user)/profile/+page.svelte | 129 ++++++++----- .../(user)/profile/setup/+page.svelte | 24 ++- src/routes/(protected)/+layout.svelte | 2 +- .../(protected)/admin/audit-log/+page.svelte | 120 +++++++----- .../admin/license-keys/+page.svelte | 29 +-- .../proclamation-categories/+page.svelte | 17 +- .../admin/proclamation-groups/+page.svelte | 17 +- .../admin/proclamations/+page.svelte | 66 ++++--- .../admin/profiles/+page.server.ts | 10 +- .../admin/profiles/CreateProfileModal.svelte | 8 +- .../admin/profiles/EditProfileModal.svelte | 67 ++++--- .../admin/profiles/ProfileFields.svelte | 36 ++-- .../admin/solfeggio-frequencies/+page.svelte | 26 ++- .../(protected)/admin/users/+page.svelte | 35 ++-- src/routes/+layout.svelte | 178 +++++++++++++++--- src/routes/+page.svelte | 6 +- src/routes/forgot-password/+page.svelte | 23 ++- src/routes/layout.css | 25 +++ src/routes/login/+page.svelte | 52 +++-- src/routes/register/+page.svelte | 69 ++++--- src/routes/reset-password/+page.svelte | 19 +- 28 files changed, 745 insertions(+), 340 deletions(-) diff --git a/src/app.html b/src/app.html index 78500ec..0891571 100644 --- a/src/app.html +++ b/src/app.html @@ -3,6 +3,19 @@ + %sveltekit.head% diff --git a/src/lib/components/DashboardSection.svelte b/src/lib/components/DashboardSection.svelte index f176d8f..d168f5e 100644 --- a/src/lib/components/DashboardSection.svelte +++ b/src/lib/components/DashboardSection.svelte @@ -14,9 +14,9 @@
-

{title}

+

{title}

{#if description} -

{description}

+

{description}

{/if}
diff --git a/src/lib/components/DataTable.svelte b/src/lib/components/DataTable.svelte index 5e146cb..4361947 100644 --- a/src/lib/components/DataTable.svelte +++ b/src/lib/components/DataTable.svelte @@ -95,14 +95,14 @@
-

{title}

+

{title}

{#if onNew}
-
- +
+
{#if draggable} @@ -145,8 +147,10 @@ {#each rows as record, i (rowKey(record, i))} handleDragStart(e, i)} @@ -158,7 +162,7 @@ {#if draggable} @@ -175,7 +179,7 @@ copyValue(column.value(record)); }} title="Copy to clipboard" - class="ml-1 inline-flex text-slate-400 transition hover:text-indigo-600" + class="ml-1 inline-flex text-slate-400 transition hover:text-indigo-600 dark:text-slate-500 dark:hover:text-indigo-400" > No results found. diff --git a/src/lib/components/admin/AdminModal.svelte b/src/lib/components/admin/AdminModal.svelte index 430dbc8..28a28a9 100644 --- a/src/lib/components/admin/AdminModal.svelte +++ b/src/lib/components/admin/AdminModal.svelte @@ -53,18 +53,18 @@ role="dialog" aria-modal="true" aria-label={title} - class="relative z-10 flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-xl" + class="relative z-10 flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-xl dark:border-slate-800 dark:bg-slate-900" >
-

{title}

+

{title}

{#if canDelete && recordId} @@ -73,7 +73,7 @@ type="button" onclick={onClose} aria-label="Close" - class="rounded-md p-1.5 text-2xl leading-none text-slate-400 transition hover:bg-slate-100 hover:text-red-600" + class="rounded-md p-1.5 text-2xl leading-none text-slate-400 transition hover:bg-slate-100 hover:text-red-600 dark:text-slate-500 dark:hover:bg-slate-800" > × diff --git a/src/lib/components/admin/Toast.svelte b/src/lib/components/admin/Toast.svelte index 74dc054..7c3ce2a 100644 --- a/src/lib/components/admin/Toast.svelte +++ b/src/lib/components/admin/Toast.svelte @@ -26,15 +26,15 @@ {#if visible}
e.stopPropagation()} aria-hidden="true"> ⠿
@@ -46,19 +52,27 @@ {#each data.licenseKeys as key (key.key)} - - + + - - + @@ -71,19 +85,29 @@ {#each data.licenseKeys as key (key.key)}
  • - {key.key} + {key.key} {#if key.active} - ☑ + ☑ {:else} - ☐☐ {/if}
    - Created {formatDate(key.createdAt)} - + Created {formatDate(key.createdAt)} + Last verified {key.lastValidatedAt ? formatDate(key.lastValidatedAt) : 'Never'}
  • @@ -91,8 +115,12 @@ {:else} -
    -

    You don't have any license keys yet.

    +
    +

    + You don't have any license keys yet. +

    {/if} diff --git a/src/routes/(protected)/(user)/profile/+page.svelte b/src/routes/(protected)/(user)/profile/+page.svelte index 55b4fd5..8f3c007 100644 --- a/src/routes/(protected)/(user)/profile/+page.svelte +++ b/src/routes/(protected)/(user)/profile/+page.svelte @@ -62,26 +62,40 @@
    -

    Profile

    -

    Manage your account details and addresses.

    +

    + Profile +

    +

    + Manage your account details and addresses. +

    -
    -

    Email

    -

    {data.user.email}

    +
    +

    Email

    +

    {data.user.email}

    -
    -

    Profile

    +
    +

    Profile

    {#if form?.action === 'updateProfile' && form?.success} -
    +
    Profile updated successfully.
    {/if} {#if form?.action === 'updateProfile' && form?.error} -
    -
    +
    -

    Addresses

    +

    Addresses

    {#if form?.action === 'addAddress' && form?.success} -
    +
    Address added successfully.
    {/if} {#if form?.action === 'updateAddress' && form?.success} -
    +
    Address updated successfully.
    {/if} {#if form?.action === 'deleteAddress' && form?.success} -
    +
    Address deleted successfully.
    {/if} - {#if (form?.action === 'addAddress' || - form?.action === 'updateAddress' || - form?.action === 'deleteAddress') && - form?.error} -
    diff --git a/src/routes/(protected)/(user)/profile/setup/+page.svelte b/src/routes/(protected)/(user)/profile/setup/+page.svelte index 4441afc..e81759d 100644 --- a/src/routes/(protected)/(user)/profile/setup/+page.svelte +++ b/src/routes/(protected)/(user)/profile/setup/+page.svelte @@ -43,7 +43,7 @@ -

    +

    Please finish setting up your profile

    @@ -55,44 +55,50 @@ /> {:else}
    {data.user?.name?.charAt(0)?.toUpperCase() ?? '?'}
    {/if} -

    {data.user?.email}

    +

    {data.user?.email}

    - +
    - +
    - +
    diff --git a/src/routes/(protected)/+layout.svelte b/src/routes/(protected)/+layout.svelte index af9dc36..a1f06ed 100644 --- a/src/routes/(protected)/+layout.svelte +++ b/src/routes/(protected)/+layout.svelte @@ -4,7 +4,7 @@ let { children }: { children: Snippet } = $props(); -
    +
    {@render children()}
    diff --git a/src/routes/(protected)/admin/audit-log/+page.svelte b/src/routes/(protected)/admin/audit-log/+page.svelte index bd59d84..853dcf2 100644 --- a/src/routes/(protected)/admin/audit-log/+page.svelte +++ b/src/routes/(protected)/admin/audit-log/+page.svelte @@ -24,19 +24,26 @@
    -

    Audit Log

    -

    +

    + Audit Log +

    +

    Every database change, newest first. You can see activity from roles beneath your own.

    -

    {first}–{last} of {data.total}

    +

    {first}–{last} of {data.total}

    - +
    -
    - {#each data.actionOptions as action (action)} @@ -84,14 +95,16 @@
    -
    -
    - To
    -
    +
    +
    @@ -191,44 +215,47 @@ {#each data.records as record (record.id)} - - + - - + - + - {:else} - + {/each} @@ -262,7 +292,9 @@ {#if data.totalPages > 1}
    -

    Page {data.page} of {data.totalPages}

    +

    + Page {data.page} of {data.totalPages} +

    {#if data.filters.q}{/if} {#if data.filters.role}{/if} @@ -285,7 +317,7 @@ type="submit" name="p" value={data.page - 1} - class="rounded-lg border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50" + class="rounded-lg border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300 dark:hover:bg-slate-800" > Previous @@ -295,7 +327,7 @@ type="submit" name="p" value={data.page + 1} - class="rounded-lg border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50" + class="rounded-lg border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300 dark:hover:bg-slate-800" > Next diff --git a/src/routes/(protected)/admin/license-keys/+page.svelte b/src/routes/(protected)/admin/license-keys/+page.svelte index 57d6321..e79d2b1 100644 --- a/src/routes/(protected)/admin/license-keys/+page.svelte +++ b/src/routes/(protected)/admin/license-keys/+page.svelte @@ -133,20 +133,25 @@ {#if createSuccess}
    {createSuccess}
    {/if} {#if createError} -
    +
    {createError}
    {/if}
    - + -

    +

    If no account exists for this email yet, the key will be attached when they register.

    @@ -165,7 +170,7 @@ @@ -182,23 +187,25 @@ {#if replaceSuccess}
    {replaceSuccess}
    {/if} {#if replaceError} -
    +
    {replaceError}
    {/if} {#if replaceRecord}
    -

    +

    Generate a new key to replace {String(replaceRecord.key)}?

    -

    +

    The existing key will be deleted and a new one will be created.

    @@ -208,7 +215,7 @@ diff --git a/src/routes/(protected)/admin/proclamation-categories/+page.svelte b/src/routes/(protected)/admin/proclamation-categories/+page.svelte index 6a39a4c..9784164 100644 --- a/src/routes/(protected)/admin/proclamation-categories/+page.svelte +++ b/src/routes/(protected)/admin/proclamation-categories/+page.svelte @@ -116,13 +116,15 @@ > {#if successMessage}
    {successMessage}
    {/if} {#if formError} -
    +
    {formError}
    {/if} @@ -133,17 +135,20 @@ {/if}
    - + {#if fieldErrors.name} -

    {fieldErrors.name}

    +

    {fieldErrors.name}

    {/if}
    @@ -151,7 +156,7 @@ diff --git a/src/routes/(protected)/admin/proclamation-groups/+page.svelte b/src/routes/(protected)/admin/proclamation-groups/+page.svelte index 959633c..8ac036c 100644 --- a/src/routes/(protected)/admin/proclamation-groups/+page.svelte +++ b/src/routes/(protected)/admin/proclamation-groups/+page.svelte @@ -116,13 +116,15 @@ > {#if successMessage}
    {successMessage}
    {/if} {#if formError} -
    +
    {formError}
    {/if} @@ -133,17 +135,20 @@ {/if}
    - + {#if fieldErrors.name} -

    {fieldErrors.name}

    +

    {fieldErrors.name}

    {/if}
    @@ -151,7 +156,7 @@ diff --git a/src/routes/(protected)/admin/proclamations/+page.svelte b/src/routes/(protected)/admin/proclamations/+page.svelte index 1832394..938f1bf 100644 --- a/src/routes/(protected)/admin/proclamations/+page.svelte +++ b/src/routes/(protected)/admin/proclamations/+page.svelte @@ -192,13 +192,15 @@ > {#if successMessage}
    {successMessage}
    {/if} {#if formError} -
    +
    {formError}
    {/if} @@ -209,31 +211,34 @@ {/if}
    - + {#if fieldErrors.name} -

    {fieldErrors.name}

    +

    {fieldErrors.name}

    {/if}
    Frequency {#if fieldErrors.solfeggioFrequencyId} -

    {fieldErrors.solfeggioFrequencyId}

    +

    + {fieldErrors.solfeggioFrequencyId} +

    {/if}
    - Category {#if fieldErrors.categoryId} -

    {fieldErrors.categoryId}

    +

    {fieldErrors.categoryId}

    {/if}
    - Group {#if fieldErrors.groupId} -

    {fieldErrors.groupId}

    +

    {fieldErrors.groupId}

    {/if}
    - Content -
    -
    +
    +
    @@ -329,13 +341,13 @@ role="textbox" tabindex="0" contenteditable="true" - class="px-3 py-2 text-sm text-slate-900 focus:outline-none" + class="px-3 py-2 text-sm text-slate-900 focus:outline-none dark:text-slate-100" >
    {/key}
    {#if fieldErrors.content} -

    {fieldErrors.content}

    +

    {fieldErrors.content}

    {/if}
    @@ -343,7 +355,7 @@ diff --git a/src/routes/(protected)/admin/profiles/+page.server.ts b/src/routes/(protected)/admin/profiles/+page.server.ts index 80fca67..0c26733 100644 --- a/src/routes/(protected)/admin/profiles/+page.server.ts +++ b/src/routes/(protected)/admin/profiles/+page.server.ts @@ -148,14 +148,8 @@ export const actions = { }; } - const { - id, - profileId, - isDefaultMailing, - isDefaultBilling, - isDefaultShipping, - ...addressData - } = form.data; + const { id, profileId, isDefaultMailing, isDefaultBilling, isDefaultShipping, ...addressData } = + form.data; if (!profileId) { return { success: false, action: 'upsertAddress', addressError: 'Missing profile ID' }; diff --git a/src/routes/(protected)/admin/profiles/CreateProfileModal.svelte b/src/routes/(protected)/admin/profiles/CreateProfileModal.svelte index e70b8e3..116d83c 100644 --- a/src/routes/(protected)/admin/profiles/CreateProfileModal.svelte +++ b/src/routes/(protected)/admin/profiles/CreateProfileModal.svelte @@ -71,13 +71,15 @@ {#if successMessage}
    {successMessage}
    {/if} {#if formError} -
    +
    {formError}
    {/if} @@ -89,7 +91,7 @@ diff --git a/src/routes/(protected)/admin/profiles/EditProfileModal.svelte b/src/routes/(protected)/admin/profiles/EditProfileModal.svelte index 44d766c..ca37a4e 100644 --- a/src/routes/(protected)/admin/profiles/EditProfileModal.svelte +++ b/src/routes/(protected)/admin/profiles/EditProfileModal.svelte @@ -156,13 +156,15 @@ {#if successMessage}
    {successMessage}
    {/if} {#if formError} -
    +
    {formError}
    {/if} @@ -176,7 +178,7 @@ @@ -189,13 +191,13 @@
    -
    +
    -

    Addresses

    +

    Addresses

    @@ -208,13 +210,17 @@ {/if} {#if addressError} -
    +
    {addressError}
    {/if}
    -
    - City
    - State
    -
    -
    -
    +
    When User
    +
    {formatWhen(record.createdAt)} + {record.userId ?? '—'} {record.email ?? '—'}{record.email ?? '—'} {record.roleName ?? (record.roleId != null ? `Role ${record.roleId}` : 'System')} {record.page}{record.page} {record.action} - {record.entity ?? '—'}{#if record.entityId}#{record.entityId} + {record.entity ?? '—'}{#if record.entityId}#{record.entityId}{/if} {#if record.before == null} - — + — {:else}
    - view
    {formatJson(
    +										class="mt-2 max-h-64 overflow-auto rounded-md bg-slate-50 p-2 text-xs whitespace-pre-wrap text-slate-700 dark:bg-slate-950 dark:text-slate-300">{formatJson(
     											record.before
     										)}
    @@ -236,14 +263,15 @@
    {#if record.after == null} - — + — {:else}
    - view
    {formatJson(
    +										class="mt-2 max-h-64 overflow-auto rounded-md bg-slate-50 p-2 text-xs whitespace-pre-wrap text-slate-700 dark:bg-slate-950 dark:text-slate-300">{formatJson(
     											record.after
     										)}
    @@ -252,7 +280,9 @@
    No events found.No events found.
    +
    +
    @@ -323,7 +336,7 @@ {#each addresses as addr, i (String(addr.id ?? i))} - + @@ -337,7 +350,7 @@ @@ -345,7 +358,7 @@ @@ -358,7 +371,7 @@
    Street City
    {addr.street as string} {addr.city as string} {addr.state as string}
    {:else} -

    No addresses on file.

    +

    No addresses on file.

    {/if}
    diff --git a/src/routes/(protected)/admin/profiles/ProfileFields.svelte b/src/routes/(protected)/admin/profiles/ProfileFields.svelte index 3374e8e..4cc9e53 100644 --- a/src/routes/(protected)/admin/profiles/ProfileFields.svelte +++ b/src/routes/(protected)/admin/profiles/ProfileFields.svelte @@ -24,7 +24,10 @@
    - + {#if fieldErrors.email} -

    {fieldErrors.email}

    +

    {fieldErrors.email}

    {/if}
    - First Name {#if fieldErrors.firstName} -

    {fieldErrors.firstName}

    +

    {fieldErrors.firstName}

    {/if}
    - Last Name {#if fieldErrors.lastName} -

    {fieldErrors.lastName}

    +

    {fieldErrors.lastName}

    {/if}
    -
    diff --git a/src/routes/(protected)/admin/solfeggio-frequencies/+page.svelte b/src/routes/(protected)/admin/solfeggio-frequencies/+page.svelte index 4c304a0..06d54e9 100644 --- a/src/routes/(protected)/admin/solfeggio-frequencies/+page.svelte +++ b/src/routes/(protected)/admin/solfeggio-frequencies/+page.svelte @@ -112,13 +112,15 @@ > {#if successMessage}
    {successMessage}
    {/if} {#if formError} -
    +
    {formError}
    {/if} @@ -129,22 +131,28 @@ {/if}
    - + {#if fieldErrors.name} -

    {fieldErrors.name}

    +

    {fieldErrors.name}

    {/if}
    - + {#if fieldErrors.value} -

    {fieldErrors.value}

    +

    {fieldErrors.value}

    {/if}
    @@ -164,7 +172,7 @@ diff --git a/src/routes/(protected)/admin/users/+page.svelte b/src/routes/(protected)/admin/users/+page.svelte index 5585598..4e253d3 100644 --- a/src/routes/(protected)/admin/users/+page.svelte +++ b/src/routes/(protected)/admin/users/+page.svelte @@ -131,13 +131,15 @@ > {#if successMessage}
    {successMessage}
    {/if} {#if formError} -
    +
    {formError}
    {/if} @@ -148,43 +150,52 @@ {/if}
    - + {#if fieldErrors.name} -

    {fieldErrors.name}

    +

    {fieldErrors.name}

    {/if}
    - + {#if fieldErrors.email} -

    {fieldErrors.email}

    +

    {fieldErrors.email}

    {/if}
    - + {#if fieldErrors.roleId} -

    {fieldErrors.roleId}

    +

    {fieldErrors.roleId}

    {/if}
    @@ -200,7 +211,7 @@ diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 07f1b60..55e2185 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -3,6 +3,7 @@ import favicon from '$lib/assets/favicon.svg'; import { page } from '$app/state'; import { resolve } from '$app/paths'; + import { onMount } from 'svelte'; import type { Snippet } from 'svelte'; import type { LayoutData } from './$types'; import './layout.css'; @@ -12,6 +13,17 @@ let menuOpen = $state(false); let adminOpen = $state(false); + let dark = $state(false); + + onMount(() => { + dark = document.documentElement.classList.contains('dark'); + }); + + function toggleTheme() { + dark = !dark; + document.documentElement.classList.toggle('dark', dark); + localStorage.setItem('theme', dark ? 'dark' : 'light'); + } const isAdmin = $derived((data.userRoleId ?? 4) <= 3); const adminModels = [ @@ -49,8 +61,8 @@ function activeClass(path: string) { return isActive(path) - ? 'bg-indigo-50 text-indigo-700' - : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900'; + ? 'bg-indigo-50 text-indigo-700 dark:bg-indigo-950 dark:text-indigo-300' + : 'text-slate-600 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-slate-100'; } function closeMenu() { @@ -75,7 +87,9 @@ -
    +
    - Radiant Wave + Radiant Wave {#if $session.data?.user} @@ -128,8 +144,8 @@ onclick={() => (adminOpen = !adminOpen)} class={`flex items-center gap-1 rounded-md px-3 py-2 text-sm font-medium transition ${ isActive('/admin') - ? 'bg-indigo-50 text-indigo-700' - : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' + ? 'bg-indigo-50 text-indigo-700 dark:bg-indigo-950 dark:text-indigo-300' + : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-slate-100' }`} > Admin @@ -150,7 +166,7 @@ {#if adminOpen} {/if} - + + @@ -193,15 +245,87 @@ > Sign In + {/if} + @@ -341,21 +465,31 @@
    {/if} -
    +
    {@render children()}
    -