add: themes for wishlists and dashboards

This commit is contained in:
rasmusq
2025-11-28 12:45:20 +01:00
parent 7c6ff9458f
commit eb7ccdf7a2
7 changed files with 275 additions and 33 deletions

View File

@@ -43,15 +43,25 @@
items: [] // We don't have item data in localStorage
}));
});
// Description depends on authentication status
const sectionDescription = $derived(() => {
if (isAuthenticated) {
return t.dashboard.localWishlistsAuthDescription || "Wishlists stored in your browser that haven't been claimed yet.";
}
return t.dashboard.localWishlistsDescription || "Wishlists stored in your browser. Sign in to save them permanently.";
});
</script>
{#if localWishlists.length > 0}
<WishlistSection
title={t.dashboard.localWishlists || "Local Wishlists"}
description={t.dashboard.localWishlistsDescription || "Wishlists stored in your browser. Sign in to save them permanently."}
items={transformedWishlists()}
emptyMessage=""
>
<WishlistSection
title={t.dashboard.localWishlists || "Local Wishlists"}
description={sectionDescription()}
items={transformedWishlists()}
emptyMessage={t.dashboard.emptyLocalWishlists || "No local wishlists yet"}
emptyActionLabel={t.dashboard.createLocalWishlist || "Create local wishlist"}
emptyActionHref="/"
showCreateButton={true}
>
{#snippet actions(wishlist, unlocked)}
<div class="flex gap-2 flex-wrap">
<Button
@@ -89,5 +99,4 @@
{/if}
</div>
{/snippet}
</WishlistSection>
{/if}
</WishlistSection>

View File

@@ -10,32 +10,35 @@
let {
userName,
userEmail,
dashboardTheme = 'none'
dashboardTheme = 'none',
isAuthenticated = false,
onThemeUpdate
}: {
userName?: string | null;
userEmail?: string | null;
dashboardTheme?: string;
isAuthenticated?: boolean;
onThemeUpdate?: (theme: string | null) => void;
} = $props();
const t = $derived(languageStore.t);
const isAuthenticated = $derived(!!userName || !!userEmail);
let currentTheme = $state(dashboardTheme);
async function handleThemeChange(theme: string) {
currentTheme = theme;
// Update theme immediately for instant visual feedback
if (onThemeUpdate) {
onThemeUpdate(theme);
}
// Submit form to update theme
const formData = new FormData();
formData.append('theme', theme);
// Only submit to database for authenticated users
if (isAuthenticated) {
const formData = new FormData();
formData.append('theme', theme);
await fetch('?/updateDashboardTheme', {
method: 'POST',
body: formData
});
// Reload to apply new theme
window.location.reload();
await fetch('?/updateDashboardTheme', {
method: 'POST',
body: formData
});
}
}
</script>
@@ -49,9 +52,7 @@
{/if}
</div>
<div class="flex items-center gap-1 sm:gap-2 flex-shrink-0">
{#if isAuthenticated}
<ThemePicker value={currentTheme} onValueChange={handleThemeChange} />
{/if}
<ThemePicker value={dashboardTheme} onValueChange={handleThemeChange} />
<LanguageToggle />
<ThemeToggle />
{#if isAuthenticated}

View File

@@ -17,6 +17,11 @@ export const load: PageServerLoad = async (event) => {
};
}
// Fetch user with theme
const user = await db.query.users.findFirst({
where: eq(users.id, session.user.id)
});
const userWishlists = await db.query.wishlists.findMany({
where: eq(wishlists.userId, session.user.id),
with: {
@@ -57,7 +62,7 @@ export const load: PageServerLoad = async (event) => {
}));
return {
user: session.user,
user: user,
wishlists: userWishlists,
savedWishlists: savedWithAccess,
isAuthenticated: true

View File

@@ -11,6 +11,30 @@
let { data }: { data: PageData } = $props();
// For anonymous users, get theme from localStorage
function getInitialTheme() {
if (data.isAuthenticated) {
return data.user?.dashboardTheme || 'none';
} else {
// Anonymous user - get from localStorage
if (typeof window !== 'undefined') {
return localStorage.getItem('dashboardTheme') || 'none';
}
return 'none';
}
}
let currentTheme = $state(getInitialTheme());
// Save to localStorage when theme changes for anonymous users
function handleThemeUpdate(theme: string | null) {
currentTheme = theme || 'none';
if (!data.isAuthenticated && typeof window !== 'undefined') {
localStorage.setItem('dashboardTheme', currentTheme);
}
}
const t = $derived(languageStore.t);
// Only owned wishlists for "My Wishlists"
@@ -34,11 +58,13 @@
});
</script>
<PageContainer theme={data.user?.dashboardTheme} themeColor="hsl(var(--primary))">
<PageContainer theme={currentTheme} themeColor="#3b82f6">
<DashboardHeader
userName={data.user?.name}
userEmail={data.user?.email}
dashboardTheme={data.user?.dashboardTheme || 'none'}
dashboardTheme={currentTheme}
isAuthenticated={data.isAuthenticated}
onThemeUpdate={handleThemeUpdate}
/>
<!-- Local Wishlists Section (for anonymous and authenticated users) -->

View File

@@ -22,6 +22,7 @@
let addFormElement = $state<HTMLElement | null>(null);
let editFormElement = $state<HTMLElement | null>(null);
let searchQuery = $state("");
let currentTheme = $state(data.wishlist.theme || 'none');
let items = $state<Item[]>([]);
@@ -105,9 +106,14 @@
items = newItems;
await handleReorder(newItems);
}
async function handleThemeUpdate(theme: string | null) {
currentTheme = theme || 'none';
await wishlistUpdates.updateTheme(theme);
}
</script>
<PageContainer maxWidth="4xl" theme={data.wishlist.theme} themeColor={data.wishlist.color}>
<PageContainer maxWidth="4xl" theme={currentTheme} themeColor={data.wishlist.color}>
<Navigation
isAuthenticated={data.isAuthenticated}
showDashboardLink={true}
@@ -119,7 +125,7 @@
onDescriptionUpdate={wishlistUpdates.updateDescription}
onColorUpdate={wishlistUpdates.updateColor}
onEndDateUpdate={wishlistUpdates.updateEndDate}
onThemeUpdate={wishlistUpdates.updateTheme}
onThemeUpdate={handleThemeUpdate}
/>
<ShareLinks
@@ -169,7 +175,7 @@
{rearranging}
onStartEditing={startEditing}
onReorder={handleReorder}
theme={data.wishlist.theme}
theme={currentTheme}
/>
<DangerZone bind:unlocked={rearranging} />