Files
falah-mobile/src/app/api/learn/courses/[slug]/route.ts
T

121 lines
3.3 KiB
TypeScript
Raw Normal View History

import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireAuth } from "@/lib/auth";
// GET /api/learn/courses/[slug] — course detail with modules and user progress
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ slug: string }> }
) {
try {
const auth = await requireAuth(request);
if (!auth) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const { slug } = await params;
const course = await prisma.learnCourse.findUnique({
where: { slug },
include: {
modules: {
orderBy: { order: "asc" },
},
},
});
if (!course) {
return NextResponse.json(
{ error: "Course not found" },
{ status: 404 }
);
}
// Fetch user's enrollment for this course (if any)
let enrollment = await prisma.learnEnrollment.findUnique({
where: {
userId_courseId: {
userId: auth.userId,
courseId: course.id,
},
},
});
// Auto-enroll premium users (check local user record, not JWT claims)
// The JWT's licenseTier may not match the local user's isPremium flag
if (!enrollment) {
const localUser = await prisma.user.findUnique({
where: { id: auth.userId },
select: { isPremium: true },
});
if (localUser?.isPremium) {
enrollment = await prisma.learnEnrollment.create({
data: {
userId: auth.userId,
courseId: course.id,
purchaseType: "free",
},
});
}
}
// Fetch module progress for this enrollment (if enrolled)
let moduleProgressMap: Record<string, { completed: boolean; score: number | null; listened: boolean }> = {};
if (enrollment) {
const progresses = await prisma.learnModuleProgress.findMany({
where: { enrollmentId: enrollment.id },
});
for (const p of progresses) {
moduleProgressMap[p.moduleId] = {
completed: p.completed,
score: p.score,
listened: p.listened,
};
}
}
// Build response
const modules = course.modules.map((mod) => ({
id: mod.id,
order: mod.order,
title: mod.title,
slug: mod.slug,
keyTakeaway: mod.keyTakeaway,
duration: mod.duration,
content: mod.content,
quizData: mod.quizData ? JSON.parse(mod.quizData) : null,
progress: moduleProgressMap[mod.id] ?? null,
}));
return NextResponse.json({
course: {
id: course.id,
slug: course.slug,
title: course.title,
author: course.author,
description: course.description,
imageUrl: course.imageUrl,
moduleCount: course.moduleCount,
totalMinutes: course.totalMinutes,
difficulty: course.difficulty,
giteaPath: course.giteaPath,
},
modules,
enrollment: enrollment
? {
id: enrollment.id,
purchaseType: enrollment.purchaseType,
completed: enrollment.completed,
progress: enrollment.progress,
}
: null,
});
} catch (error) {
console.error("GET /api/learn/courses/[slug] error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}