Add homework system (admin, student, curator)
Admin: - HomeworkEditor in lesson page: create/update/delete assignment description Student: - HomeworkSection in lesson page: view assignment, submit text + files - Resubmission allowed until curator gives feedback - Shows feedback from curator with date and name Curator: - New layout with Second Brain dark sidebar (replaces green theme) - /curator/dashboard: stats cards (pending, total, reviewed this week) - /curator/homework: list of all submissions, pending highlighted - /curator/homework/[id]: review submission, write feedback, redirect after send Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,43 +1,57 @@
|
||||
import { headers } from "next/headers";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { redirect } from "next/navigation";
|
||||
import { LogoutButton } from "@/components/layout/logout-button";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import Link from "next/link";
|
||||
|
||||
export default async function CuratorDashboard() {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
|
||||
if (!session) redirect("/login");
|
||||
if (session.user.role !== "curator" && session.user.role !== "admin") {
|
||||
redirect("/dashboard");
|
||||
}
|
||||
|
||||
const [pending, total, recentFeedbacks] = await Promise.all([
|
||||
prisma.homeworkSubmission.count({ where: { feedbacks: { none: {} } } }),
|
||||
prisma.homeworkSubmission.count(),
|
||||
prisma.homeworkFeedback.count({
|
||||
where: {
|
||||
createdAt: { gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) },
|
||||
curatorId: session.user.id,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-green-50">
|
||||
<header className="bg-white border-b border-green-100 px-6 py-4 flex items-center justify-between">
|
||||
<h1 className="text-xl font-bold text-green-900">Second Brain — Куратор</h1>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm text-gray-600">{session.user.name}</span>
|
||||
<LogoutButton />
|
||||
<div className="p-8 max-w-3xl">
|
||||
<h1 className="text-2xl font-bold mb-1">Обзор</h1>
|
||||
<p className="text-sm mb-8" style={{ color: "var(--muted-foreground)" }}>Панель куратора</p>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4 mb-8">
|
||||
<StatCard label="Ожидают проверки" value={pending} accent={pending > 0} />
|
||||
<StatCard label="Всего сдано" value={total} />
|
||||
<StatCard label="Проверено за 7 дней" value={recentFeedbacks} />
|
||||
</div>
|
||||
|
||||
{pending > 0 ? (
|
||||
<Link href="/curator/homework" className="btn-aubade btn-aubade-accent inline-flex items-center gap-2 px-5 py-2.5 text-sm">
|
||||
Перейти к проверке ({pending}) →
|
||||
</Link>
|
||||
) : (
|
||||
<div className="card-aubade p-8 text-center">
|
||||
<p className="text-3xl mb-2">✓</p>
|
||||
<p className="font-bold">Все работы проверены</p>
|
||||
<p className="text-sm mt-1" style={{ color: "var(--muted-foreground)" }}>Новых заданий нет</p>
|
||||
</div>
|
||||
</header>
|
||||
<main className="max-w-4xl mx-auto px-6 py-10">
|
||||
<h2 className="text-2xl font-semibold text-gray-800 mb-2">
|
||||
Панель куратора
|
||||
</h2>
|
||||
<p className="text-gray-500 mb-8">Здесь будут домашние задания на проверку.</p>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="bg-white rounded-2xl border border-green-100 p-6">
|
||||
<p className="text-3xl mb-2">📝</p>
|
||||
<p className="font-medium text-gray-800">Домашние задания</p>
|
||||
<p className="text-sm text-gray-400 mt-1">Новых заданий нет</p>
|
||||
</div>
|
||||
<div className="bg-white rounded-2xl border border-green-100 p-6">
|
||||
<p className="text-3xl mb-2">👥</p>
|
||||
<p className="font-medium text-gray-800">Мои ученики</p>
|
||||
<p className="text-sm text-gray-400 mt-1">Откроется в Этапе 3</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function StatCard({ label, value, accent }: { label: string; value: number; accent?: boolean }) {
|
||||
return (
|
||||
<div className="card-aubade p-4">
|
||||
<p className="text-3xl font-bold" style={{ color: accent ? "oklch(0.577 0.245 27.325)" : "var(--foreground)" }}>
|
||||
{value}
|
||||
</p>
|
||||
<p className="text-xs mt-1 uppercase tracking-widest" style={{ color: "var(--muted-foreground)" }}>{label}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user