64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
"use server";
|
||
|
||
import { prisma } from "@/lib/prisma";
|
||
import { headers } from "next/headers";
|
||
import { auth } from "@/lib/auth";
|
||
import { redirect } from "next/navigation";
|
||
import { revalidatePath } from "next/cache";
|
||
|
||
async function requireAdmin() {
|
||
const session = await auth.api.getSession({ headers: await headers() });
|
||
if (!session || session.user.role !== "admin") throw new Error("Forbidden");
|
||
}
|
||
|
||
function slugify(str: string): string {
|
||
const map: Record<string, string> = {
|
||
а:"a",б:"b",в:"v",г:"g",д:"d",е:"e",ё:"yo",ж:"zh",з:"z",и:"i",й:"y",
|
||
к:"k",л:"l",м:"m",н:"n",о:"o",п:"p",р:"r",с:"s",т:"t",у:"u",ф:"f",
|
||
х:"kh",ц:"ts",ч:"ch",ш:"sh",щ:"shch",ъ:"",ы:"y",ь:"",э:"e",ю:"yu",я:"ya",
|
||
};
|
||
return str.toLowerCase()
|
||
.replace(/[а-яё]/g, (c) => map[c] ?? c)
|
||
.replace(/[^a-z0-9]+/g, "-")
|
||
.replace(/^-|-$/g, "");
|
||
}
|
||
|
||
export async function createCourse(formData: FormData) {
|
||
await requireAdmin();
|
||
const title = formData.get("title") as string;
|
||
const slug = (formData.get("slug") as string).trim() || slugify(title);
|
||
const description = (formData.get("description") as string) || null;
|
||
|
||
const course = await prisma.course.create({
|
||
data: { title, slug, description },
|
||
});
|
||
|
||
revalidatePath("/admin/courses");
|
||
redirect(`/admin/courses/${course.id}`);
|
||
}
|
||
|
||
export async function updateCourse(courseId: string, formData: FormData) {
|
||
await requireAdmin();
|
||
const title = formData.get("title") as string;
|
||
const slug = formData.get("slug") as string;
|
||
const description = (formData.get("description") as string) || null;
|
||
const published = formData.get("published") === "true";
|
||
const coverImage = (formData.get("coverImage") as string) || null;
|
||
const categoryId = (formData.get("categoryId") as string) || null;
|
||
|
||
await prisma.course.update({
|
||
where: { id: courseId },
|
||
data: { title, slug, description, published, coverImage, categoryId },
|
||
});
|
||
|
||
revalidatePath("/admin/courses");
|
||
revalidatePath(`/admin/courses/${courseId}`);
|
||
}
|
||
|
||
export async function deleteCourse(courseId: string) {
|
||
await requireAdmin();
|
||
await prisma.course.delete({ where: { id: courseId } });
|
||
revalidatePath("/admin/courses");
|
||
redirect("/admin/courses");
|
||
}
|