Diese Woche
navigateWeek('prev')} aria-label="Vorherige Woche" class="flex min-h-[40px] min-w-[40px] items-center justify-center rounded-[var(--radius-md)] border border-[var(--color-border)] text-[var(--color-text)] hover:bg-[var(--color-surface)]" > ‹
navigateWeek('next')} aria-label="Nächste Woche" class="flex min-h-[40px] min-w-[40px] items-center justify-center rounded-[var(--radius-md)] border border-[var(--color-border)] text-[var(--color-text)] hover:bg-[var(--color-surface)]" > ›
{#if isPlanner}
(pickerOpen = true)} class="rounded-[var(--radius-md)] bg-[var(--green-dark)] px-3 py-1.5 text-[13px] font-medium tracking-[0.04em] font-[var(--font-sans)] text-white" > + Gericht
{/if}
{#if varietyScore}
{/if}
{formatDayLabel(selectedDay)}
(actionSheetOpen = true) : undefined} onaddrecipe={isPlanner && !selectedSlot.recipe ? () => (pickerOpen = true) : undefined} />
{#if remainingSlotsWithMeal.length > 0}
Restliche Woche
{#each remainingSlotsWithMeal as slot (slot.slotDate)}
handleSelectDay(slot.slotDate)} class="flex w-full items-center gap-3 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-2 text-left hover:border-[var(--green-light)]" >
{formatDayLabel(slot.slotDate).split(',')[0]}
{slot.recipe?.name}
{#if isPlanner}
→
{/if}
{/each}
{/if} {#if !weekPlan}
Noch kein Wochenplan für diese Woche.
{#if isPlanner}
Wochenplan erstellen
{/if}
{/if}
(pickerOpen = false)}>
{ actionSheetOpen = false; swapSheetOpen = true; }} oncancel={() => (actionSheetOpen = false)} />
(swapSheetOpen = false)} height="70vh"> {@const replacingMeta = [ selectedSlot.recipe?.cookTimeMin ? `${selectedSlot.recipe.cookTimeMin} Min` : null, selectedSlot.recipe?.effort ?? null ].filter(Boolean).join(' · ')}
(swapSheetOpen = false)} />
Wochenplaner
navigateWeek('prev')} aria-label="Vorherige Woche" class="flex min-h-[40px] min-w-[40px] items-center justify-center rounded-[var(--radius-md)] border border-[var(--color-border)] text-[13px] font-medium tracking-[0.04em] font-[var(--font-sans)] text-[var(--color-text)] hover:bg-[var(--color-surface)]" > ‹
{weekRange}
navigateWeek('next')} aria-label="Nächste Woche" class="flex min-h-[40px] min-w-[40px] items-center justify-center rounded-[var(--radius-md)] border border-[var(--color-border)] text-[13px] font-medium tracking-[0.04em] font-[var(--font-sans)] text-[var(--color-text)] hover:bg-[var(--color-surface)]" > ›
navigateWeek('today')} class="flex min-h-[40px] items-center rounded-[var(--radius-md)] border border-[var(--color-border)] px-3 text-[13px] font-medium tracking-[0.04em] font-[var(--font-sans)] text-[var(--color-text)] hover:bg-[var(--color-surface)]" > Heute
{#if isPlanner}
(panelState = { kind: 'recipe-picker', date: selectedDay })} class="ml-auto rounded-[var(--radius-md)] bg-[var(--green-dark)] px-4 py-2 text-[13px] font-medium tracking-[0.04em] font-[var(--font-sans)] text-white" > + Gericht hinzufügen
{/if}
{#if !weekPlan}
Noch kein Wochenplan für diese Woche.
{#if isPlanner}
Wochenplan erstellen
{/if}
{:else}
{#each days as day (day)} {@const slot = slotMap[day] ?? { id: null, slotDate: day, recipe: null }} {@const isTodayDay = day === today} {@const isSelectedDay = day === selectedDay} {@const dateNum = day.slice(-2).replace(/^0/, '')} {@const dayAbbr = formatDayAbbr(day, 'narrow')}
{dayAbbr}
{dateNum}
{ handleSelectDay(day); if (!slot.recipe && isPlanner) { panelState = { kind: 'recipe-picker', date: day }; } }} aria-label={slot.recipe ? slot.recipe.name : `Gericht wählen für ${formatDayLabel(day)}`} class="flex flex-1 flex-col rounded-[var(--radius-lg)] border p-2 text-left shadow-[var(--shadow-card)] transition-all hover:border-[var(--green-light)] hover:shadow-[var(--shadow-raised)] {slot.recipe && !isTodayDay && !isSelectedDay ? 'border-[var(--color-border)] bg-[var(--color-surface)]' : ''} {isTodayDay && slot.recipe ? 'border-2 border-[var(--yellow)] bg-[var(--yellow-tint)]' : ''} {isSelectedDay && !isTodayDay && slot.recipe ? 'border-2 border-[var(--green)] bg-[var(--green-tint)]' : ''} {!slot.recipe ? 'border-dashed border-[var(--color-border)] bg-transparent' : ''}" > {#if slot.recipe}
{slot.recipe.name}
{:else}
+
Gericht wählen
{/if}
{/each}
{/if}
{ formData.set('planId', addPlanId); formData.set('slotDate', addSlotDate); formData.set('recipeId', addRecipeId); return async ({ result, update }) => { if (result.type === 'success' && result.data?.success) { delPlanId = addPlanId; delSlotId = (result.data as any)?.slot?.id ?? ''; undoMessage = `${addRecipeName} hinzugefügt`; undoVisible = true; } await update({ reset: false }); await invalidateAll(); }; }} >
{ formData.set('planId', updPlanId); formData.set('slotId', updSlotId); formData.set('recipeId', updRecipeId); return async ({ result, update }) => { if (result.type === 'success' && result.data?.success) { delPlanId = updPlanId; delSlotId = (result.data as any)?.slot?.id ?? ''; undoMessage = `${updRecipeName} eingetragen`; undoVisible = true; } await update({ reset: false }); await invalidateAll(); }; }} >
{ formData.set('planId', delPlanId); formData.set('slotId', delSlotId); return async ({ update }) => { await update({ reset: false }); await invalidateAll(); }; }} >
(undoVisible = false)} />