feat(core): full database soft-delete, live sidebar counts and robust subtask undo/restore across all modes
Build and Push Docker Image / build-and-push (push) Successful in 10m12s
Build and Push Docker Image / build-and-push (push) Successful in 10m12s
This commit is contained in:
@@ -12,19 +12,52 @@ export async function GET(req: NextRequest) {
|
||||
const listId = searchParams.get("listId");
|
||||
const showCompleted = searchParams.get("showCompleted") === "true";
|
||||
const tagName = searchParams.get("tag");
|
||||
const isTrash = searchParams.get("isTrash") === "true";
|
||||
const countTrash = searchParams.get("countTrash") === "true";
|
||||
|
||||
if (countTrash) {
|
||||
const trashCount = await prisma.task.count({
|
||||
where: { userId: session.user.id, isDeleted: true } as any,
|
||||
});
|
||||
return NextResponse.json({ count: trashCount });
|
||||
}
|
||||
|
||||
if (isTrash) {
|
||||
// Return all deleted tasks (top-level or subtasks)
|
||||
const trashTasks = await prisma.task.findMany({
|
||||
where: { userId: session.user.id, isDeleted: true } as any,
|
||||
orderBy: [{ deletedAt: "desc" } as any, { createdAt: "desc" }],
|
||||
include: {
|
||||
children: {
|
||||
orderBy: [{ sortOrder: "asc" }],
|
||||
include: { tags: { include: { tag: true } } },
|
||||
},
|
||||
tags: { include: { tag: true } },
|
||||
},
|
||||
});
|
||||
return NextResponse.json(trashTasks);
|
||||
}
|
||||
|
||||
const where: Record<string, unknown> = {
|
||||
userId: session.user.id,
|
||||
isDeleted: false,
|
||||
...(listId ? { listId, parentId: null } : tagName ? {} : { parentId: null }),
|
||||
...(showCompleted ? {} : { completed: false }),
|
||||
...(tagName ? { tags: { some: { tag: { name: tagName } } } } : {}),
|
||||
};
|
||||
|
||||
const tasks = await prisma.task.findMany({
|
||||
where,
|
||||
where: where as any,
|
||||
orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
|
||||
include: {
|
||||
children: { orderBy: [{ sortOrder: "asc" }] },
|
||||
children: {
|
||||
where: { isDeleted: false } as any,
|
||||
orderBy: [{ sortOrder: "asc" }],
|
||||
include: {
|
||||
children: { where: { isDeleted: false } as any, orderBy: [{ sortOrder: "asc" }] },
|
||||
tags: { include: { tag: true } },
|
||||
},
|
||||
},
|
||||
tags: { include: { tag: true } },
|
||||
},
|
||||
});
|
||||
@@ -35,6 +68,29 @@ export async function GET(req: NextRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(req: NextRequest) {
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
const trash = searchParams.get("trash") === "true";
|
||||
|
||||
if (trash) {
|
||||
// Empty all trash permanently
|
||||
await prisma.task.deleteMany({
|
||||
where: { userId: session.user.id, isDeleted: true } as any,
|
||||
});
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
return NextResponse.json({ error: "Invalid delete request" }, { status: 400 });
|
||||
} catch (err) {
|
||||
console.error("[tasks:DELETE_BATCH]", err);
|
||||
return NextResponse.json({ error: "Failed to empty trash" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
|
||||
Reference in New Issue
Block a user