diff --git a/frontend/src/lib/planner/DayMealCard.svelte b/frontend/src/lib/planner/DayMealCard.svelte
index fb03bdf..26eae34 100644
--- a/frontend/src/lib/planner/DayMealCard.svelte
+++ b/frontend/src/lib/planner/DayMealCard.svelte
@@ -17,15 +17,19 @@
isToday = false,
isSelected = false,
readonly = false,
- onaddrecipe
+ onaddrecipe,
+ onactionsheet
}: {
slot: Slot;
isToday?: boolean;
isSelected?: boolean;
readonly?: boolean;
onaddrecipe?: () => void;
+ onactionsheet?: () => void;
} = $props();
+ let actionSheetMode = $derived(!!onactionsheet && !!slot.recipe);
+
let metadata = $derived(
[
slot.recipe?.cookTimeMin != null ? `${slot.recipe.cookTimeMin} Min` : null,
@@ -44,49 +48,67 @@
);
-
- {#if slot.recipe}
+{#if actionSheetMode}
+
+{:else}
+
+ {#if slot.recipe}
+
+ {slot.recipe.name}
+
+ {#if metadata}
+
{metadata}
+ {/if}
- {#if !readonly}
-
+ Jetzt kochen
+
+ {#if onaddrecipe}
+
+ {/if}
+
+ {/if}
+ {:else}
+
Kein Gericht geplant
+ {#if !readonly && onaddrecipe}
+
+ {/if}
{/if}
- {:else}
-
Kein Gericht geplant
- {#if !readonly && onaddrecipe}
-
- {/if}
- {/if}
-
+
+{/if}
diff --git a/frontend/src/lib/planner/DayMealCard.test.ts b/frontend/src/lib/planner/DayMealCard.test.ts
index cafa53a..c8f2ac0 100644
--- a/frontend/src/lib/planner/DayMealCard.test.ts
+++ b/frontend/src/lib/planner/DayMealCard.test.ts
@@ -81,4 +81,38 @@ describe('DayMealCard', () => {
render(DayMealCard, { props: { slot: { id: 's2', slotDate: '2026-03-31', recipe: null }, isToday: false, readonly: false } });
expect(screen.queryByRole('button', { name: /Gericht hinzufügen/i })).toBeNull();
});
+
+ describe('onactionsheet prop (mobile full-card tap target)', () => {
+ it('card renders as a button when onactionsheet provided and recipe exists', () => {
+ render(DayMealCard, { props: { slot, onactionsheet: vi.fn() } });
+ const card = screen.getByRole('button', { name: /Pasta Bolognese/i });
+ expect(card).toBeTruthy();
+ });
+
+ it('clicking card calls onactionsheet', async () => {
+ const onactionsheet = vi.fn();
+ const user = userEvent.setup();
+ render(DayMealCard, { props: { slot, onactionsheet } });
+ await user.click(screen.getByRole('button', { name: /Pasta Bolognese/i }));
+ expect(onactionsheet).toHaveBeenCalledOnce();
+ });
+
+ it('inline Jetzt kochen and Tauschen buttons are hidden when onactionsheet provided', () => {
+ render(DayMealCard, { props: { slot, onactionsheet: vi.fn() } });
+ expect(screen.queryByRole('link', { name: /Jetzt kochen/i })).toBeNull();
+ expect(screen.queryByRole('button', { name: /Tauschen/i })).toBeNull();
+ });
+
+ it('falls back to normal rendering when onactionsheet not provided', () => {
+ render(DayMealCard, { props: { slot, readonly: false, onaddrecipe: vi.fn() } });
+ expect(screen.queryByRole('button', { name: /Pasta Bolognese/i })).toBeNull();
+ expect(screen.getByRole('link', { name: /Jetzt kochen/i })).toBeTruthy();
+ });
+
+ it('empty slot does not render card as button even when onactionsheet provided', () => {
+ const emptySlot = { id: 's2', slotDate: '2026-03-31', recipe: null };
+ render(DayMealCard, { props: { slot: emptySlot, onactionsheet: vi.fn(), onaddrecipe: vi.fn() } });
+ expect(screen.queryByRole('button', { name: /Pasta Bolognese/i })).toBeNull();
+ });
+ });
});