"use server"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; import { getServerSession } from "next-auth"; import { authOptions } from "@/lib/auth-options"; import { prisma } from "@/lib/prisma"; import { slugify } from "@/lib/slug"; import { BillingInterval } from "@prisma/client"; async function assertAdmin() { const session = await getServerSession(authOptions); if (!session?.user?.id || session.user.role !== "ADMIN") { throw new Error("Keine Berechtigung."); } return session; } function parseBilling(v: FormDataEntryValue | null): BillingInterval { const s = String(v ?? "NONE"); if (s === "MONTH" || s === "QUARTER" || s === "YEAR") return s; return BillingInterval.NONE; } export async function createCourseAction(formData: FormData) { const session = await assertAdmin(); const title = String(formData.get("title") ?? "").trim(); if (!title) redirect("/admin/courses/new?error=title"); let slug = String(formData.get("slug") ?? "").trim(); if (!slug) slug = slugify(title); const exists = await prisma.course.findUnique({ where: { slug } }); if (exists) redirect(`/admin/courses/new?error=slug`); const description = String(formData.get("description") ?? "").trim(); const authorName = String(formData.get("authorName") ?? "").trim() || session.user.name || "Admin"; const published = String(formData.get("published") ?? "") === "on"; const priceEuros = Number(String(formData.get("priceEuros") ?? "0").replace(",", ".")); const priceCents = Number.isFinite(priceEuros) ? Math.max(0, Math.round(priceEuros * 100)) : 0; const course = await prisma.course.create({ data: { slug, title, description, published, priceCents, billingInterval: parseBilling(formData.get("billingInterval")), authorId: session.user.id, authorName, }, }); revalidatePath("/kurse"); revalidatePath("/admin/courses"); redirect(`/admin/courses/${course.id}/edit`); } export async function updateCourseAction(courseId: string, formData: FormData) { const session = await assertAdmin(); const title = String(formData.get("title") ?? "").trim(); if (!title) redirect(`/admin/courses/${courseId}/edit?error=title`); let slug = String(formData.get("slug") ?? "").trim(); if (!slug) slug = slugify(title); const clash = await prisma.course.findFirst({ where: { slug, NOT: { id: courseId } }, }); if (clash) redirect(`/admin/courses/${courseId}/edit?error=slug`); const description = String(formData.get("description") ?? "").trim(); const authorName = String(formData.get("authorName") ?? "").trim() || session.user.name || "Admin"; const published = String(formData.get("published") ?? "") === "on"; const priceEuros = Number(String(formData.get("priceEuros") ?? "0").replace(",", ".")); const priceCents = Number.isFinite(priceEuros) ? Math.max(0, Math.round(priceEuros * 100)) : 0; await prisma.course.update({ where: { id: courseId }, data: { slug, title, description, published, priceCents, billingInterval: parseBilling(formData.get("billingInterval")), authorName, }, }); revalidatePath("/kurse"); revalidatePath("/admin/courses"); revalidatePath(`/kurse/${slug}`); redirect(`/admin/courses/${courseId}/edit?saved=1`); } export async function createModuleAction(courseId: string, formData: FormData) { await assertAdmin(); const title = String(formData.get("title") ?? "").trim(); if (!title) redirect(`/admin/courses/${courseId}/edit?error=module`); const max = await prisma.courseModule.aggregate({ where: { courseId }, _max: { sortOrder: true }, }); const sortOrder = (max._max.sortOrder ?? -1) + 1; await prisma.courseModule.create({ data: { courseId, title, sortOrder }, }); revalidatePath(`/admin/courses/${courseId}/edit`); redirect(`/admin/courses/${courseId}/edit`); } export async function createLessonAction(courseId: string, formData: FormData) { await assertAdmin(); const moduleId = String(formData.get("moduleId") ?? "").trim(); const title = String(formData.get("lessonTitle") ?? "").trim(); if (!moduleId || !title) redirect(`/admin/courses/${courseId}/edit?error=lesson`); const mod = await prisma.courseModule.findFirst({ where: { id: moduleId, courseId }, }); if (!mod) redirect(`/admin/courses/${courseId}/edit?error=lesson`); let slug = String(formData.get("lessonSlug") ?? "").trim(); if (!slug) slug = slugify(title); const contentHtml = String(formData.get("contentHtml") ?? "").trim(); const max = await prisma.lesson.aggregate({ where: { moduleId }, _max: { sortOrder: true }, }); const sortOrder = (max._max.sortOrder ?? -1) + 1; const existing = await prisma.lesson.findUnique({ where: { moduleId_slug: { moduleId, slug } }, }); if (existing) redirect(`/admin/courses/${courseId}/edit?error=lessonSlug`); await prisma.lesson.create({ data: { moduleId, slug, title, contentHtml, sortOrder, published: true }, }); const course = await prisma.course.findUnique({ where: { id: courseId }, select: { slug: true } }); if (course?.slug) revalidatePath(`/kurse/${course.slug}`); revalidatePath(`/admin/courses/${courseId}/edit`); redirect(`/admin/courses/${courseId}/edit`); }