Files
mealprep/frontend/src/lib/planner/MealActionSheet.svelte
Marcel Raddatz f55d938b32 feat(planner): add onremove prop and Entfernen button to MealActionSheet
Button only renders when onremove callback is provided, keeping the
component usable in read-only contexts without the destructive action.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 12:25:22 +02:00

123 lines
4.2 KiB
Svelte

<script lang="ts">
interface SlotRecipe {
id: string;
name: string;
effort?: string;
cookTimeMin?: number;
}
interface Slot {
id?: string;
slotDate?: string;
recipe: SlotRecipe | null;
}
interface Props {
open: boolean;
slot: Slot;
onswap: () => void;
oncancel: () => void;
onremove?: () => void;
}
let { open, slot, onswap, oncancel, onremove }: Props = $props();
const meta = $derived.by(() => {
const parts: string[] = [];
if (slot.recipe?.cookTimeMin != null) parts.push(`${slot.recipe.cookTimeMin} min`);
if (slot.recipe?.effort) parts.push(slot.recipe.effort);
return parts.join(' · ');
});
$effect(() => {
if (!open) return;
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Escape') oncancel();
}
window.addEventListener('keydown', handleKeydown);
return () => window.removeEventListener('keydown', handleKeydown);
});
</script>
{#if open}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<div
role="presentation"
data-testid="sheet-backdrop"
style="position:fixed;inset:0;z-index:50;background:rgba(28,28,24,0.4)"
onclick={oncancel}
>
<div
role="dialog"
aria-modal="true"
tabindex="-1"
style="position:absolute;bottom:0;left:0;right:0;background:var(--color-page);border-radius:var(--radius-xl) var(--radius-xl) 0 0;box-shadow:var(--shadow-overlay)"
onclick={(e) => e.stopPropagation()}
>
<!-- Drag handle -->
<div style="display:flex;justify-content:center;margin-top:12px">
<div style="width:32px;height:4px;background:var(--color-border);border-radius:9999px"></div>
</div>
<!-- Meal title -->
<p style="font-family:var(--font-display);font-size:15px;font-weight:500;color:var(--color-text);padding:0 16px;margin:12px 0 4px">
{slot.recipe?.name ?? ''}
</p>
<!-- Metadata -->
{#if meta}
<p style="font-family:var(--font-sans);font-size:11px;color:var(--color-text-muted);padding:0 16px 12px;margin:0">
{meta}
</p>
{/if}
<!-- Actions -->
<div style="padding:0 16px 16px;display:flex;flex-direction:column;gap:6px">
<button
type="button"
style="width:100%;background:var(--orange-tint);border:1px solid #FBCDA4;color:var(--orange-dark);font-family:var(--font-sans);font-size:13px;font-weight:500;border-radius:var(--radius-lg);padding:12px;text-align:center;cursor:pointer"
onclick={onswap}
>
↻ Gericht tauschen
</button>
{#if onremove}
<button
type="button"
style="width:100%;background:var(--color-error, #d9534f);border:1px solid var(--color-error, #d9534f);color:#fff;font-family:var(--font-sans);font-size:13px;font-weight:500;border-radius:var(--radius-lg);padding:12px;text-align:center;cursor:pointer"
onclick={onremove}
>
✕ Gericht entfernen
</button>
{/if}
{#if slot.recipe}
<a
href="/recipes/{slot.recipe.id}/cook"
style="display:block;width:100%;background:var(--green-tint);border:1px solid var(--green-light);color:var(--green-dark);font-family:var(--font-sans);font-size:13px;font-weight:500;border-radius:var(--radius-lg);padding:12px;text-align:center;box-sizing:border-box;text-decoration:none"
>
🍳 Jetzt kochen
</a>
<a
href="/recipes/{slot.recipe.id}"
style="display:block;width:100%;background:var(--color-subtle);border:1px solid var(--color-border);color:var(--color-text-muted);font-family:var(--font-sans);font-size:13px;font-weight:500;border-radius:var(--radius-lg);padding:12px;text-align:center;box-sizing:border-box;text-decoration:none"
>
👁 Rezept ansehen
</a>
{/if}
<button
type="button"
style="width:100%;background:none;border:none;color:var(--color-text-muted);font-family:var(--font-sans);font-size:13px;text-align:center;cursor:pointer;padding:12px"
onclick={oncancel}
>
Abbrechen
</button>
</div>
</div>
</div>
{/if}