Files
Epicure/apps/web/components/recipe/batch-cook-dishes.tsx
T
Arnaud 78d0599ffc feat: add batch-cooking sessions (single "mega recipe" with dish sections)
New AI-generated batch-cooking flow: pick N dinners/lunches + servings,
get one unified recipe covering a full prep session — merged shopping
list, steps tagged per-dish (a step can advance several dishes at once,
e.g. a shared oven bake), and per-dish storage (fridge/freezer) + exact
day-of reheat/finishing instructions.

Schema: recipes.isBatchCook, recipeSteps.appliesTo (dish names), new
recipeBatchDishes table. Batch recipes are excluded from the normal
/recipes list and live under their own /batch-cooking section.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 01:23:37 +02:00

59 lines
2.1 KiB
TypeScript

"use client";
import { useTranslations } from "next-intl";
import { Snowflake, Refrigerator, ChefHat } from "lucide-react";
type Dish = {
id: string;
name: string;
description: string | null;
fridgeDays: number;
freezerFriendly: boolean;
freezerNote: string | null;
dayOfInstructions: string;
};
export function BatchCookDishes({ dishes }: { dishes: Dish[] }) {
const t = useTranslations("recipe");
return (
<div className="space-y-4">
<h2 className="text-xl font-semibold">{t("batchCookDishesTitle")}</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{dishes.map((dish) => (
<div key={dish.id} className="rounded-xl border p-4 space-y-3">
<div>
<h3 className="font-semibold">{dish.name}</h3>
{dish.description && <p className="text-sm text-muted-foreground mt-0.5">{dish.description}</p>}
</div>
<div className="flex flex-wrap gap-2 text-xs">
<span className="inline-flex items-center gap-1 rounded-full bg-muted px-2.5 py-1">
<Refrigerator className="h-3.5 w-3.5" />
{t("batchCookFridgeDays", { days: dish.fridgeDays })}
</span>
{dish.freezerFriendly && (
<span className="inline-flex items-center gap-1 rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 px-2.5 py-1">
<Snowflake className="h-3.5 w-3.5" />
{t("batchCookFreezerFriendly")}
</span>
)}
</div>
{dish.freezerNote && (
<p className="text-xs text-muted-foreground">{dish.freezerNote}</p>
)}
<div className="flex gap-2 rounded-lg bg-muted/50 p-3">
<ChefHat className="h-4 w-4 text-primary shrink-0 mt-0.5" />
<div>
<p className="text-xs font-medium">{t("batchCookDayOf")}</p>
<p className="text-sm text-muted-foreground mt-0.5">{dish.dayOfInstructions}</p>
</div>
</div>
</div>
))}
</div>
</div>
);
}