"use client"; import { useState, useTransition } from "react"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { grantAccess, revokeAccess } from "@/app/admin/courses/[courseId]/actions"; interface Student { id: string; name: string; email: string; } interface Enrollment { userId: string; expiresAt: Date | null; } interface LogEntry { id: string; action: string; createdAt: Date; note: string | null; user: { name: string }; grantedBy: { name: string } | null; } interface Props { courseId: string; allStudents: Student[]; enrollments: Enrollment[]; accessLogs: LogEntry[]; } export function EnrollmentManager({ courseId, allStudents, enrollments, accessLogs }: Props) { const [enrolledMap, setEnrolledMap] = useState>( () => new Map(enrollments.map((e) => [e.userId, e.expiresAt])) ); const [search, setSearch] = useState(""); const [expiryDate, setExpiryDate] = useState(""); const [note, setNote] = useState(""); const [showLog, setShowLog] = useState(false); const [pending, startTransition] = useTransition(); const filtered = allStudents.filter( (s) => s.name.toLowerCase().includes(search.toLowerCase()) || s.email.toLowerCase().includes(search.toLowerCase()) ); function handleGrant(userId: string) { const newMap = new Map(enrolledMap); newMap.set(userId, expiryDate ? new Date(expiryDate) : null); setEnrolledMap(newMap); startTransition(() => grantAccess(courseId, userId, expiryDate || null, note || undefined)); } function handleRevoke(userId: string) { const newMap = new Map(enrolledMap); newMap.delete(userId); setEnrolledMap(newMap); startTransition(() => revokeAccess(courseId, userId, note || undefined)); } const enrolledStudents = allStudents.filter((s) => enrolledMap.has(s.id)); function formatExpiry(date: Date | null) { if (!date) return "Бессрочно"; const d = new Date(date); const now = new Date(); const expired = d < now; return ( {expired ? "Истёк " : "До "} {d.toLocaleDateString("ru-RU")} ); } return (
{/* Enrolled list */} {enrolledStudents.length > 0 && (

Доступ открыт — {enrolledStudents.length}

{enrolledStudents.map((s) => (

{s.name}

{s.email}

{formatExpiry(enrolledMap.get(s.id) ?? null)}
))}
)} {/* Grant form */}

Добавить ученика

setSearch(e.target.value)} />
setExpiryDate(e.target.value)} className="w-44" />
setNote(e.target.value)} />
{filtered.map((student) => { const enrolled = enrolledMap.has(student.id); return (

{student.name}

{student.email}

{enrolled ? ( ) : ( )}
); })} {filtered.length === 0 && (

Студентов не найдено

)}
{/* Access log */} {accessLogs.length > 0 && (
{showLog && (
{accessLogs.map((log) => (
{log.action === "granted" ? "▲ Выдан" : "▼ Отозван"} {log.user.name} {log.grantedBy?.name ?? "—"} {log.note && {log.note}} {new Date(log.createdAt).toLocaleString("ru-RU", { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit" })}
))}
)}
)}
); }