initial production version
This commit is contained in:
45
src/lib/components/dashboard/WishlistCard.svelte
Normal file
45
src/lib/components/dashboard/WishlistCard.svelte
Normal file
@@ -0,0 +1,45 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '$lib/components/ui/card';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { getCardStyle } from '$lib/utils/colors';
|
||||
|
||||
let {
|
||||
title,
|
||||
description,
|
||||
itemCount,
|
||||
color = null,
|
||||
children
|
||||
}: {
|
||||
title: string;
|
||||
description?: string | null;
|
||||
itemCount: number;
|
||||
color?: string | null;
|
||||
children?: Snippet;
|
||||
} = $props();
|
||||
|
||||
const cardStyle = $derived(getCardStyle(color));
|
||||
</script>
|
||||
|
||||
<Card style={cardStyle} class="h-full flex flex-col">
|
||||
<CardHeader class="flex-shrink-0">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<CardTitle class="text-lg flex items-center gap-2 flex-1 min-w-0">
|
||||
<span class="truncate">{title}</span>
|
||||
</CardTitle>
|
||||
<span class="text-sm text-muted-foreground flex-shrink-0">
|
||||
{itemCount} item{itemCount === 1 ? '' : 's'}
|
||||
</span>
|
||||
</div>
|
||||
{#if description}
|
||||
<CardDescription class="line-clamp-3 whitespace-pre-line">{description}</CardDescription>
|
||||
{/if}
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-2 flex-1 flex flex-col justify-end">
|
||||
{#if children}
|
||||
<div>
|
||||
{@render children()}
|
||||
</div>
|
||||
{/if}
|
||||
</CardContent>
|
||||
</Card>
|
||||
79
src/lib/components/dashboard/WishlistGrid.svelte
Normal file
79
src/lib/components/dashboard/WishlistGrid.svelte
Normal file
@@ -0,0 +1,79 @@
|
||||
<script lang="ts">
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '$lib/components/ui/card';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import EmptyState from '$lib/components/layout/EmptyState.svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { flip } from 'svelte/animate';
|
||||
|
||||
let {
|
||||
title,
|
||||
description,
|
||||
items,
|
||||
emptyMessage,
|
||||
emptyDescription,
|
||||
emptyActionLabel,
|
||||
emptyActionHref,
|
||||
headerAction,
|
||||
children
|
||||
}: {
|
||||
title: string;
|
||||
description: string;
|
||||
items: any[];
|
||||
emptyMessage: string;
|
||||
emptyDescription?: string;
|
||||
emptyActionLabel?: string;
|
||||
emptyActionHref?: string;
|
||||
headerAction?: Snippet;
|
||||
children: Snippet<[any]>;
|
||||
} = $props();
|
||||
|
||||
let scrollContainer: HTMLElement | null = null;
|
||||
|
||||
function handleWheel(event: WheelEvent) {
|
||||
if (!scrollContainer) return;
|
||||
|
||||
// Check if we have horizontal overflow
|
||||
const hasHorizontalScroll = scrollContainer.scrollWidth > scrollContainer.clientWidth;
|
||||
|
||||
if (hasHorizontalScroll && event.deltaY !== 0) {
|
||||
event.preventDefault();
|
||||
scrollContainer.scrollLeft += event.deltaY;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<CardTitle>{title}</CardTitle>
|
||||
<CardDescription>{description}</CardDescription>
|
||||
</div>
|
||||
{#if headerAction}
|
||||
{@render headerAction()}
|
||||
{/if}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{#if items && items.length > 0}
|
||||
<div
|
||||
bind:this={scrollContainer}
|
||||
onwheel={handleWheel}
|
||||
class="flex overflow-x-auto gap-4 pb-4 -mx-6 px-6"
|
||||
>
|
||||
{#each items as item (item.id)}
|
||||
<div class="flex-shrink-0 w-80" animate:flip={{ duration: 300 }}>
|
||||
{@render children(item)}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<EmptyState
|
||||
message={emptyMessage}
|
||||
description={emptyDescription}
|
||||
actionLabel={emptyActionLabel}
|
||||
actionHref={emptyActionHref}
|
||||
/>
|
||||
{/if}
|
||||
</CardContent>
|
||||
</Card>
|
||||
Reference in New Issue
Block a user