Files
ACVE/app/(public)/courses/[slug]/learn/actions.ts
2026-03-15 13:52:11 +00:00

108 lines
2.6 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { requireUser } from "@/lib/auth/requireUser";
import { db } from "@/lib/prisma";
import { issueCertificateIfEligible } from "@/lib/certificates";
import { refreshStudyRecommendations } from "@/lib/recommendations";
type ToggleLessonCompleteInput = {
courseSlug: string;
lessonId: string;
};
export async function toggleLessonComplete({ courseSlug, lessonId }: ToggleLessonCompleteInput) {
const user = await requireUser();
if (!user?.id) {
return { success: false, error: "Unauthorized" };
}
const lesson = await db.lesson.findUnique({
where: { id: lessonId },
select: {
id: true,
module: {
select: {
courseId: true,
course: {
select: {
slug: true,
},
},
},
},
},
});
if (!lesson || lesson.module.course.slug !== courseSlug) {
return { success: false, error: "Lesson not found" };
}
const enrollment = await db.enrollment.findUnique({
where: {
userId_courseId: {
userId: user.id,
courseId: lesson.module.courseId,
},
},
select: { id: true },
});
if (!enrollment) {
return { success: false, error: "Not enrolled in this course" };
}
const existingProgress = await db.userProgress.findUnique({
where: {
userId_lessonId: {
userId: user.id,
lessonId,
},
},
select: {
id: true,
isCompleted: true,
},
});
const nextCompleted = !existingProgress?.isCompleted;
if (existingProgress) {
await db.userProgress.update({
where: { id: existingProgress.id },
data: {
isCompleted: nextCompleted,
finishedAt: nextCompleted ? new Date() : null,
lastPlayedAt: new Date(),
},
});
} else {
await db.userProgress.create({
data: {
userId: user.id,
lessonId,
isCompleted: true,
finishedAt: new Date(),
},
});
}
const certificateResult = nextCompleted
? await issueCertificateIfEligible(user.id, lesson.module.courseId)
: { certificateId: null, certificateNumber: null, newlyIssued: false };
revalidatePath(`/courses/${courseSlug}/learn`);
revalidatePath("/my-courses");
revalidatePath("/profile");
await refreshStudyRecommendations(user.id);
return {
success: true,
isCompleted: nextCompleted,
certificateId: certificateResult.certificateId,
certificateNumber: certificateResult.certificateNumber,
newlyIssuedCertificate: certificateResult.newlyIssued,
};
}