78d0599ffc
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>
59 lines
2.1 KiB
TypeScript
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>
|
|
);
|
|
}
|