91 lines
3.0 KiB
TypeScript
91 lines
3.0 KiB
TypeScript
import { prisma } from "@/lib/prisma";
|
||
import { notFound } from "next/navigation";
|
||
import Link from "next/link";
|
||
import { CourseEditForm } from "@/components/admin/course-edit-form";
|
||
import { SortableModules } from "@/components/admin/sortable-modules";
|
||
import { EnrollmentManager } from "@/components/admin/enrollment-manager";
|
||
|
||
interface Props {
|
||
params: Promise<{ courseId: string }>;
|
||
}
|
||
|
||
export default async function CourseDetailPage({ params }: Props) {
|
||
const { courseId } = await params;
|
||
|
||
const [course, allStudents, categories] = await Promise.all([
|
||
prisma.course.findUnique({
|
||
where: { id: courseId },
|
||
include: {
|
||
modules: {
|
||
orderBy: { order: "asc" },
|
||
include: { _count: { select: { lessons: true } } },
|
||
},
|
||
enrollments: {
|
||
select: { userId: true, expiresAt: true },
|
||
},
|
||
accessLogs: {
|
||
orderBy: { createdAt: "desc" },
|
||
take: 50,
|
||
include: {
|
||
user: { select: { name: true } },
|
||
grantedBy: { select: { name: true } },
|
||
},
|
||
},
|
||
},
|
||
}),
|
||
prisma.user.findMany({
|
||
where: { role: "student" },
|
||
select: { id: true, name: true, email: true },
|
||
orderBy: { name: "asc" },
|
||
}),
|
||
prisma.category.findMany({ orderBy: { order: "asc" } }),
|
||
]);
|
||
|
||
if (!course) notFound();
|
||
|
||
return (
|
||
<div className="p-8 max-w-4xl">
|
||
{/* Breadcrumb */}
|
||
<nav className="text-xs mb-6 uppercase tracking-widest" style={{ color: "var(--muted-foreground)" }}>
|
||
<Link href="/admin/courses" className="hover:underline">Курсы</Link>
|
||
<span className="mx-2">/</span>
|
||
<span style={{ color: "var(--foreground)" }}>{course.title}</span>
|
||
</nav>
|
||
|
||
{/* Course metadata */}
|
||
<section className="card-aubade p-6 mb-6">
|
||
<p className="text-xs font-bold uppercase tracking-widest mb-5" style={{ color: "var(--muted-foreground)" }}>
|
||
Основная информация
|
||
</p>
|
||
<CourseEditForm course={course} categories={categories} />
|
||
</section>
|
||
|
||
{/* Modules */}
|
||
<section className="card-aubade p-6 mb-6">
|
||
<div className="flex items-center justify-between mb-5">
|
||
<p className="text-xs font-bold uppercase tracking-widest" style={{ color: "var(--muted-foreground)" }}>
|
||
Модули
|
||
</p>
|
||
<span className="text-xs" style={{ color: "var(--muted-foreground)" }}>
|
||
{course.modules.length} модулей
|
||
</span>
|
||
</div>
|
||
<SortableModules courseId={courseId} modules={course.modules} />
|
||
</section>
|
||
|
||
{/* Access management */}
|
||
<section className="card-aubade p-6">
|
||
<p className="text-xs font-bold uppercase tracking-widest mb-5" style={{ color: "var(--muted-foreground)" }}>
|
||
Управление доступом
|
||
</p>
|
||
<EnrollmentManager
|
||
courseId={courseId}
|
||
allStudents={allStudents}
|
||
enrollments={course.enrollments}
|
||
accessLogs={course.accessLogs}
|
||
/>
|
||
</section>
|
||
</div>
|
||
);
|
||
}
|