feat: bulk tag editing, bulk export, and move recipes between collections
Extends the existing bulk-select infra: recipes list gets tag add/remove and multi-recipe Markdown export; collection pages get a select mode to move recipes to another collection or remove them from the current one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,8 @@ const BulkDeleteSchema = z.object({
|
||||
const BulkUpdateSchema = z.object({
|
||||
ids: z.array(z.string()).min(1).max(100),
|
||||
visibility: z.enum(["private", "unlisted", "public"]).optional(),
|
||||
addTags: z.array(z.string().min(1).max(40)).max(20).optional(),
|
||||
removeTags: z.array(z.string().min(1).max(40)).max(20).optional(),
|
||||
});
|
||||
|
||||
export async function DELETE(req: NextRequest) {
|
||||
@@ -33,13 +35,33 @@ export async function PATCH(req: NextRequest) {
|
||||
const body = BulkUpdateSchema.safeParse(await req.json());
|
||||
if (!body.success) return NextResponse.json({ error: "Invalid request" }, { status: 400 });
|
||||
|
||||
const { ids, visibility } = body.data;
|
||||
if (!visibility) return NextResponse.json({ error: "Nothing to update" }, { status: 400 });
|
||||
const { ids, visibility, addTags, removeTags } = body.data;
|
||||
if (!visibility && !addTags?.length && !removeTags?.length) {
|
||||
return NextResponse.json({ error: "Nothing to update" }, { status: 400 });
|
||||
}
|
||||
|
||||
await db
|
||||
.update(recipes)
|
||||
.set({ visibility, updatedAt: new Date() })
|
||||
.where(and(inArray(recipes.id, ids), eq(recipes.authorId, session!.user.id)));
|
||||
if (visibility) {
|
||||
await db
|
||||
.update(recipes)
|
||||
.set({ visibility, updatedAt: new Date() })
|
||||
.where(and(inArray(recipes.id, ids), eq(recipes.authorId, session!.user.id)));
|
||||
}
|
||||
|
||||
if (addTags?.length || removeTags?.length) {
|
||||
const owned = await db.query.recipes.findMany({
|
||||
where: and(inArray(recipes.id, ids), eq(recipes.authorId, session!.user.id)),
|
||||
columns: { id: true, tags: true },
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
owned.map((r) => {
|
||||
let nextTags = r.tags;
|
||||
if (addTags?.length) nextTags = [...new Set([...nextTags, ...addTags])];
|
||||
if (removeTags?.length) nextTags = nextTags.filter((tag) => !removeTags.includes(tag));
|
||||
return db.update(recipes).set({ tags: nextTags, updatedAt: new Date() }).where(eq(recipes.id, r.id));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user