import { prisma } from "@/lib/prisma"; import Link from "next/link"; export default async function AdminDashboard() { const now = new Date(); const dayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); const [ totalStudents, newStudentsMonth, totalCourses, publishedCourses, activeEnrollments, expiringWeek, homeworkPending, homeworkTotal, progressTotal, balanceAggregate, activeLast24h, ] = await Promise.all([ prisma.user.count({ where: { role: "student" } }), prisma.user.count({ where: { role: "student", createdAt: { gte: monthAgo } } }), prisma.course.count(), prisma.course.count({ where: { published: true } }), prisma.courseEnrollment.count({ where: { OR: [{ expiresAt: null }, { expiresAt: { gt: now } }] }, }), prisma.courseEnrollment.count({ where: { expiresAt: { gt: now, lte: new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000) } }, }), prisma.homeworkSubmission.count({ where: { status: { in: ["PENDING", "REVIEWING"] } } }), prisma.homeworkSubmission.count(), prisma.lessonProgress.count(), prisma.balanceTransaction.aggregate({ _sum: { amount: true } }), prisma.session.findMany({ where: { createdAt: { gte: dayAgo } }, select: { userId: true }, distinct: ["userId"], }).then((rows) => rows.length), ]); const totalBalance = Number(balanceAggregate._sum.amount ?? 0); // Recent enrollments const recentEnrollments = await prisma.courseEnrollment.findMany({ orderBy: { enrolledAt: "desc" }, take: 8, include: { user: { select: { name: true, email: true } }, course: { select: { title: true } }, }, }); // Most active courses (by enrollment count) const topCourses = await prisma.course.findMany({ where: { published: true }, include: { _count: { select: { enrollments: true, modules: true } } }, orderBy: { enrollments: { _count: "desc" } }, take: 5, }); return (

Обзор

Платформа Second Brain · {now.toLocaleDateString("ru-RU", { day: "numeric", month: "long", year: "numeric" })}

{/* Stats grid */}
0 ? `${expiringWeek} истекает на неделе` : "нет истекающих"} subAccent={expiringWeek > 0} href="/admin/courses" /> 0} href="/curator/homework?status=pending" />
{/* Recent enrollments */}

Последние зачисления

Все →
{recentEnrollments.length === 0 ? (

Нет зачислений

) : (
{recentEnrollments.map((e) => (

{e.user.name}

{e.course.title}

{new Date(e.enrolledAt).toLocaleDateString("ru-RU")}
))}
)}
{/* Top courses + progress stat */}

Популярные курсы

Все →
{topCourses.length === 0 ? (

Нет курсов

) : (
{topCourses.map((c) => (

{c.title}

{c._count.modules} модулей

{c._count.enrollments}

студентов

))}
)}

Активность

{progressTotal}

уроков пройдено

{homeworkTotal}

работ сдано

На балансах

{totalBalance.toLocaleString("ru-RU", { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ₽

сумма по всем пользователям

Авторизации за 24 часа

{activeLast24h}

уникальных пользователей

); } function StatCard({ label, value, sub, subAccent, href, }: { label: string; value: number | string; sub?: string; subAccent?: boolean; href?: string; }) { const content = (

{value}

{label}

{sub && (

{sub}

)}
); return href ? {content} : content; }