Files
Epicure/apps/web/components/recipe/batch-cooking-page-content.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

72 lines
2.6 KiB
TypeScript

"use client";
import { useState } from "react";
import Link from "next/link";
import { useTranslations, useLocale } from "next-intl";
import { ChefHat, PlusCircle, Utensils } from "lucide-react";
import { Button } from "@/components/ui/button";
import { BatchCookGenerateDialog } from "@/components/recipe/batch-cook-generate-dialog";
type Session = {
id: string;
title: string;
description: string | null;
baseServings: number;
createdAt: string;
dishCount: number;
};
export function BatchCookingPageContent({ sessions }: { sessions: Session[] }) {
const t = useTranslations("batchCooking");
const locale = useLocale();
const [open, setOpen] = useState(false);
return (
<div className="space-y-6">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight">{t("title")}</h1>
<p className="text-muted-foreground mt-1">{t("subtitle")}</p>
</div>
<Button size="sm" onClick={() => setOpen(true)}>
<PlusCircle className="h-4 w-4" />
{t("newSession")}
</Button>
</div>
{sessions.length === 0 ? (
<div className="flex flex-col items-center justify-center h-64 border-2 border-dashed rounded-xl gap-4">
<ChefHat className="h-12 w-12 text-muted-foreground/40" />
<p className="text-muted-foreground text-sm">{t("empty")}</p>
<Button size="sm" onClick={() => setOpen(true)}>
<PlusCircle className="h-4 w-4" />
{t("newSession")}
</Button>
</div>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
{sessions.map((s) => (
<Link
key={s.id}
href={`/recipes/${s.id}`}
className="group rounded-xl border p-4 hover:shadow-sm transition-shadow space-y-2"
>
<h2 className="font-semibold group-hover:text-primary transition-colors line-clamp-1">{s.title}</h2>
{s.description && <p className="text-sm text-muted-foreground line-clamp-2">{s.description}</p>}
<div className="flex items-center gap-3 text-xs text-muted-foreground pt-1">
<span className="flex items-center gap-1">
<Utensils className="h-3.5 w-3.5" />
{t("dishCount", { count: s.dishCount })}
</span>
<span>{new Date(s.createdAt).toLocaleDateString(locale)}</span>
</div>
</Link>
))}
</div>
)}
<BatchCookGenerateDialog open={open} onOpenChange={setOpen} />
</div>
);
}