Files
FL-Akademie/app/admin/courses/actions.ts

154 lines
5.2 KiB
TypeScript

"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`);
}