import { getTranslations } from "next-intl/server"; import { notFound } from "next/navigation"; import Link from "next/link"; import { db } from "@/lib/db"; import { auth } from "@/auth"; import { ProgressBar } from "@/components/ProgressBar"; import { EnrollButton } from "./EnrollButton"; export const dynamic = "force-dynamic"; const levelLabels: Record> = { fr: { BEGINNER: "Débutant", INTERMEDIATE: "Intermédiaire", ADVANCED: "Avancé" }, en: { BEGINNER: "Beginner", INTERMEDIATE: "Intermediate", ADVANCED: "Advanced" }, es: { BEGINNER: "Principiante", INTERMEDIATE: "Intermedio", ADVANCED: "Avanzado" }, }; function getLocaleText( obj: Record, locale: string, keys: { fr: string; en: string; es: string } ) { if (locale === "en") return (obj as any)[keys.en] || (obj as any)[keys.fr]; if (locale === "es") return (obj as any)[keys.es] || (obj as any)[keys.fr]; return (obj as any)[keys.fr]; } export default async function CourseDetailPage({ params, }: { params: Promise<{ locale: string; slug: string }>; }) { const { locale, slug } = await params; const t = await getTranslations({ locale, namespace: "course" }); const course = await db.course.findUnique({ where: { slug }, include: { modules: { orderBy: { order: "asc" }, include: { lessons: { orderBy: { order: "asc" } }, quiz: { select: { id: true } }, }, }, }, }); if (!course || !course.published) { notFound(); } const session = await auth(); let enrollment = null; let progress = 0; let firstLessonId: string | null = null; if (session?.user) { const userId = (session.user as any).id; enrollment = await db.enrollment.findUnique({ where: { userId_courseId: { userId, courseId: course.id } }, }); // Calculate progress const allLessons = course.modules.flatMap((m) => m.lessons); firstLessonId = allLessons[0]?.id ?? null; if (allLessons.length > 0) { const completedCount = await db.lessonProgress.count({ where: { userId, lessonId: { in: allLessons.map((l) => l.id) }, }, }); progress = Math.round((completedCount / allLessons.length) * 100); } } const title = getLocaleText(course as any, locale, { fr: "titleFr", en: "titleEn", es: "titleEs" }); const desc = getLocaleText(course as any, locale, { fr: "descFr", en: "descEn", es: "descEs" }); const lvlLabel = (levelLabels[locale] ?? levelLabels.fr)[course.level]; const totalLessons = course.modules.reduce((s, m) => s + m.lessons.length, 0); return (
{/* Breadcrumb */}
Formations {" "} / {title}
{/* Main content */}
{/* Course header */}
{course.category} {lvlLabel}

{title}

{desc}

{/* Thumbnail */} {course.thumbnailUrl && (
{title}
)} {/* Module list */}

{t("modules")} ({course.modules.length})

{course.modules.map((module, mIndex) => { const moduleTitle = getLocaleText(module as any, locale, { fr: "titleFr", en: "titleEn", es: "titleEs", }); return (
{mIndex + 1}
{moduleTitle}
{module.lessons.length} {t("lessons")} {module.quiz && ( {t("quiz")} )}
{module.lessons.length > 0 && (
{module.lessons.map((lesson) => { const lessonTitle = getLocaleText(lesson as any, locale, { fr: "titleFr", en: "titleEn", es: "titleEs", }); return (
{lesson.type === "VIDEO" ? "▶" : "📄"} {lessonTitle} {lesson.duration && ( {Math.floor(lesson.duration / 60)}min )}
); })}
)}
); })}
{/* Sidebar */}
{/* Stats */}
{course.modules.length}
{t("modules")}
{totalLessons}
{t("lessons")}
{/* Progress if enrolled */} {enrollment && (
Progression {progress}%
{enrollment.completedAt && (

✓ Formation complétée

)}
)} {/* CTA */} {enrollment ? ( {progress > 0 ? t("continue") : t("start")} → ) : session ? ( ) : ( {t("enroll")} )}

Accès illimité · Certificat inclus

); }