"use server"; import { revalidatePath } from "next/cache"; import { prisma } from "@/lib/db"; import { requireUserId } from "@/lib/auth-helpers"; import { projectAccessFilter } from "@/lib/access"; import { ProjectTitleSchema } from "@/lib/validation/project"; import type { ProjectDTO } from "@/types/project"; export async function createProject(title: string): Promise { const userId = await requireUserId(); const parsedTitle = ProjectTitleSchema.parse(title); const project = await prisma.project.create({ data: { title: parsedTitle, ownerId: userId }, }); revalidatePath("/projects"); return { id: project.id, title: project.title }; } export async function renameProject(projectId: string, title: string): Promise { const userId = await requireUserId(); const parsedTitle = ProjectTitleSchema.parse(title); const { count } = await prisma.project.updateMany({ where: { id: projectId, ...projectAccessFilter(userId) }, data: { title: parsedTitle }, }); if (count === 0) throw new Error("Project not found"); revalidatePath("/projects"); revalidatePath(`/projects/${projectId}`); } export type DeleteProjectResult = { error?: string }; /** * Deletes a project and everything in it -- its categories, groups, and * to-dos all cascade away with it (unlike deleting a single Category, * which refuses if it still has groups). The confirmation dialog on the * client carries the "this can't be undone" warning; this action doesn't * re-check emptiness. */ export async function deleteProject(projectId: string): Promise { const userId = await requireUserId(); const { count } = await prisma.project.deleteMany({ where: { id: projectId, ...projectAccessFilter(userId) }, }); if (count === 0) return { error: "Project not found." }; revalidatePath("/projects"); return {}; }