feat(shopping): Einkaufslisten-Seite mit Empty-State
Some checks failed
Build & Publish Docker Image / build-and-push (push) Has been cancelled

This commit is contained in:
hsiegeln
2026-04-21 23:40:52 +02:00
parent 7fa1079125
commit 943a645095

View File

@@ -0,0 +1,49 @@
<script lang="ts">
import { onMount } from 'svelte';
import { ShoppingCart } from 'lucide-svelte';
import type { ShoppingListSnapshot } from '$lib/server/shopping/repository';
let snapshot = $state<ShoppingListSnapshot>({ recipes: [], rows: [], uncheckedCount: 0 });
let loading = $state(true);
async function load() {
loading = true;
try {
const res = await fetch('/api/shopping-list');
snapshot = await res.json();
} finally {
loading = false;
}
}
onMount(load);
</script>
<header class="head">
<h1>Einkaufsliste</h1>
{#if snapshot.recipes.length > 0}
<p class="sub">
{snapshot.uncheckedCount} noch zu besorgen · {snapshot.recipes.length} Rezept{snapshot.recipes.length === 1 ? '' : 'e'} im Wagen
</p>
{/if}
</header>
{#if loading}
<p class="muted">Lädt …</p>
{:else if snapshot.recipes.length === 0}
<section class="empty">
<div class="big"><ShoppingCart size={48} strokeWidth={1.5} /></div>
<p>Einkaufswagen ist leer.</p>
<p class="hint">Lege Rezepte auf der Wunschliste in den Wagen, um sie hier zu sehen.</p>
</section>
{/if}
<style>
.head { padding: 1.25rem 0 0.5rem; }
.head h1 { margin: 0; font-size: 1.6rem; color: #2b6a3d; }
.sub { margin: 0.2rem 0 0; color: #666; }
.muted { color: #888; text-align: center; padding: 2rem 0; }
.empty { text-align: center; padding: 3rem 1rem; }
.big { color: #8fb097; display: inline-flex; margin: 0 0 0.5rem; }
.hint { color: #888; font-size: 0.9rem; }
</style>