Stage 1.5: categories, enrollment expiry, access log, bulk grant, user page
This commit is contained in:
@@ -12,7 +12,7 @@ interface Props {
|
||||
export default async function CourseDetailPage({ params }: Props) {
|
||||
const { courseId } = await params;
|
||||
|
||||
const [course, allStudents] = await Promise.all([
|
||||
const [course, allStudents, categories] = await Promise.all([
|
||||
prisma.course.findUnique({
|
||||
where: { id: courseId },
|
||||
include: {
|
||||
@@ -20,7 +20,17 @@ export default async function CourseDetailPage({ params }: Props) {
|
||||
orderBy: { order: "asc" },
|
||||
include: { _count: { select: { lessons: true } } },
|
||||
},
|
||||
enrollments: { include: { user: { select: { id: true, name: true, email: 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({
|
||||
@@ -28,43 +38,51 @@ export default async function CourseDetailPage({ params }: Props) {
|
||||
select: { id: true, name: true, email: true },
|
||||
orderBy: { name: "asc" },
|
||||
}),
|
||||
prisma.category.findMany({ orderBy: { order: "asc" } }),
|
||||
]);
|
||||
|
||||
if (!course) notFound();
|
||||
|
||||
const enrolledIds = new Set(course.enrollments.map((e) => e.userId));
|
||||
|
||||
return (
|
||||
<div className="p-8 max-w-4xl">
|
||||
{/* Breadcrumb */}
|
||||
<nav className="text-sm text-slate-400 mb-6">
|
||||
<Link href="/admin/courses" className="hover:text-slate-600">Курсы</Link>
|
||||
<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 className="text-slate-700">{course.title}</span>
|
||||
<span style={{ color: "var(--foreground)" }}>{course.title}</span>
|
||||
</nav>
|
||||
|
||||
{/* Course metadata */}
|
||||
<section className="bg-white border border-slate-200 rounded-2xl p-6 mb-6">
|
||||
<h2 className="text-base font-semibold text-slate-700 mb-4">Основная информация</h2>
|
||||
<CourseEditForm course={course} />
|
||||
<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="bg-white border border-slate-200 rounded-2xl p-6 mb-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-base font-semibold text-slate-700">Модули</h2>
|
||||
<span className="text-sm text-slate-400">{course.modules.length} модулей</span>
|
||||
<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="bg-white border border-slate-200 rounded-2xl p-6">
|
||||
<h2 className="text-base font-semibold text-slate-700 mb-4">Доступ к курсу</h2>
|
||||
<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}
|
||||
enrolledIds={[...enrolledIds]}
|
||||
enrollments={course.enrollments}
|
||||
accessLogs={course.accessLogs}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user