feat(shopping): Footer-Actions (Erledigte entfernen, Liste leeren)
Some checks failed
Build & Publish Docker Image / build-and-push (push) Has been cancelled
Some checks failed
Build & Publish Docker Image / build-and-push (push) Has been cancelled
This commit is contained in:
@@ -6,9 +6,11 @@
|
|||||||
import ShoppingCartChip from '$lib/components/ShoppingCartChip.svelte';
|
import ShoppingCartChip from '$lib/components/ShoppingCartChip.svelte';
|
||||||
import type { ShoppingListRow as Row } from '$lib/server/shopping/repository';
|
import type { ShoppingListRow as Row } from '$lib/server/shopping/repository';
|
||||||
import { shoppingCartStore } from '$lib/client/shopping-cart.svelte';
|
import { shoppingCartStore } from '$lib/client/shopping-cart.svelte';
|
||||||
|
import { confirmAction } from '$lib/client/confirm.svelte';
|
||||||
|
|
||||||
let snapshot = $state<ShoppingListSnapshot>({ recipes: [], rows: [], uncheckedCount: 0 });
|
let snapshot = $state<ShoppingListSnapshot>({ recipes: [], rows: [], uncheckedCount: 0 });
|
||||||
let loading = $state(true);
|
let loading = $state(true);
|
||||||
|
const hasChecked = $derived(snapshot.rows.some((r) => r.checked === 1));
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
loading = true;
|
loading = true;
|
||||||
@@ -47,6 +49,25 @@
|
|||||||
void shoppingCartStore.refresh();
|
void shoppingCartStore.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function clearChecked() {
|
||||||
|
await fetch('/api/shopping-list/checked', { method: 'DELETE' });
|
||||||
|
await load();
|
||||||
|
void shoppingCartStore.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function clearAll() {
|
||||||
|
const ok = await confirmAction({
|
||||||
|
title: 'Einkaufsliste leeren?',
|
||||||
|
message: 'Alle Rezepte und abgehakten Zutaten werden entfernt. Das lässt sich nicht rückgängig machen.',
|
||||||
|
confirmLabel: 'Leeren',
|
||||||
|
destructive: true
|
||||||
|
});
|
||||||
|
if (!ok) return;
|
||||||
|
await fetch('/api/shopping-list', { method: 'DELETE' });
|
||||||
|
await load();
|
||||||
|
void shoppingCartStore.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
onMount(load);
|
onMount(load);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -80,6 +101,12 @@
|
|||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="footer">
|
||||||
|
{#if hasChecked}
|
||||||
|
<button class="btn secondary" onclick={clearChecked}>Erledigte entfernen</button>
|
||||||
|
{/if}
|
||||||
|
<button class="btn destructive" onclick={clearAll}>Liste leeren</button>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -106,4 +133,28 @@
|
|||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
.footer {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
background: #f4f8f5;
|
||||||
|
padding: 0.75rem 0;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 1rem;
|
||||||
|
border-top: 1px solid #e4eae7;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #cfd9d1;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
min-height: 44px;
|
||||||
|
}
|
||||||
|
.btn.secondary { color: #2b6a3d; border-color: #b7d6c2; }
|
||||||
|
.btn.destructive { color: #c53030; border-color: #f1b4b4; }
|
||||||
|
.btn.destructive:hover { background: #fdf3f3; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user