Files
ACVE/app/(protected)/courses/[slug]/learn/page.tsx
2026-02-17 00:07:00 +00:00

131 lines
3.3 KiB
TypeScript
Executable File

import { notFound, redirect } from "next/navigation";
import { db } from "@/lib/prisma";
import { requireUser } from "@/lib/auth/requireUser";
import StudentClassroomClient from "@/components/courses/StudentClassroomClient";
function getText(value: unknown): string {
if (!value) return "";
if (typeof value === "string") return value;
if (typeof value === "object") {
const record = value as Record<string, unknown>;
if (typeof record.es === "string") return record.es;
if (typeof record.en === "string") return record.en;
}
return "";
}
type PageProps = {
params: Promise<{ slug: string }>;
searchParams: Promise<{ lesson?: string }>;
};
export default async function CourseLearnPage({ params, searchParams }: PageProps) {
const { slug } = await params;
const { lesson: requestedLessonId } = await searchParams;
const user = await requireUser();
if (!user?.id) {
redirect(`/courses/${slug}`);
}
const course = await db.course.findUnique({
where: { slug },
select: {
id: true,
slug: true,
title: true,
price: true,
modules: {
orderBy: { orderIndex: "asc" },
select: {
id: true,
title: true,
lessons: {
orderBy: { orderIndex: "asc" },
select: {
id: true,
title: true,
description: true,
videoUrl: true,
estimatedDuration: true,
},
},
},
},
},
});
if (!course) {
notFound();
}
let enrollment = await db.enrollment.findUnique({
where: {
userId_courseId: {
userId: user.id,
courseId: course.id,
},
},
select: { id: true },
});
if (!enrollment) {
const isFree = Number(course.price) === 0;
if (isFree) {
enrollment = await db.enrollment.create({
data: {
userId: user.id,
courseId: course.id,
amountPaid: 0,
},
select: { id: true },
});
} else {
redirect(`/courses/${slug}`);
}
}
const completedProgress = await db.userProgress.findMany({
where: {
userId: user.id,
isCompleted: true,
lesson: {
module: {
courseId: course.id,
},
},
},
select: {
lessonId: true,
},
});
const modules = course.modules.map((module) => ({
id: module.id,
title: getText(module.title) || "Untitled module",
lessons: module.lessons.map((lesson) => ({
id: lesson.id,
title: getText(lesson.title) || "Untitled lesson",
description: getText(lesson.description),
videoUrl: lesson.videoUrl,
estimatedDuration: lesson.estimatedDuration,
})),
}));
const flattenedLessonIds = modules.flatMap((module) => module.lessons.map((lesson) => lesson.id));
const initialSelectedLessonId =
requestedLessonId && flattenedLessonIds.includes(requestedLessonId)
? requestedLessonId
: flattenedLessonIds[0] ?? "";
return (
<StudentClassroomClient
courseSlug={course.slug}
courseTitle={getText(course.title) || "Untitled course"}
modules={modules}
initialSelectedLessonId={initialSelectedLessonId}
initialCompletedLessonIds={completedProgress.map((progress) => progress.lessonId)}
/>
);
}