feat: clear a meal-plan day or the whole week in one action

New bulk-delete route for the owner's own weekStart-scoped plan
(mirrors recipes/bulk's DELETE), plus ?ids= support added to the
existing shared-plan DELETE route (kept ?entryId= working
unchanged). UI: hover-reveal trash icon per day header, "Clear week"
button in the toolbar, one shared confirm dialog for both.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Arnaud
2026-07-13 22:07:12 +02:00
parent a144052e46
commit aa67868b96
9 changed files with 151 additions and 11 deletions
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { db, mealPlanEntries, recipes, eq, and, or, ne } from "@epicure/db";
import { db, mealPlanEntries, recipes, eq, and, or, ne, inArray } from "@epicure/db";
import { requireSession } from "@/lib/api-auth";
import { getMealPlanAccessById, canWriteMealPlan } from "@/lib/meal-plan-access";
import { dispatchWebhook } from "@/lib/webhooks";
@@ -70,11 +70,15 @@ export async function DELETE(req: NextRequest, { params }: Params) {
if (!access) return NextResponse.json({ error: "Not found" }, { status: 404 });
if (!canWriteMealPlan(access.role)) return NextResponse.json({ error: "Forbidden" }, { status: 403 });
// ?entryId=x for a single delete (existing behavior), or ?ids=a,b,c for a
// "clear this day"/"clear this week" bulk delete — same access check either way.
const entryId = req.nextUrl.searchParams.get("entryId");
if (!entryId) return NextResponse.json({ error: "entryId required" }, { status: 400 });
const idsParam = req.nextUrl.searchParams.get("ids");
const ids = idsParam ? idsParam.split(",").filter(Boolean) : entryId ? [entryId] : [];
if (ids.length === 0) return NextResponse.json({ error: "entryId or ids required" }, { status: 400 });
await db.delete(mealPlanEntries).where(
and(eq(mealPlanEntries.id, entryId), eq(mealPlanEntries.mealPlanId, mealPlanId))
and(inArray(mealPlanEntries.id, ids), eq(mealPlanEntries.mealPlanId, mealPlanId))
);
return new NextResponse(null, { status: 204 });