import { useMemo } from "react"; import { PERMISSIONS } from "@/constants/userPermissions"; import useExams from "@/hooks/useExams"; import useUsers from "@/hooks/useUsers"; import { Module } from "@/interfaces"; import { Exam } from "@/interfaces/exam"; import { Type, User } from "@/interfaces/user"; import useExamStore from "@/stores/examStore"; import { getExamById } from "@/utils/exams"; import { countExercises } from "@/utils/moduleUtils"; import { createColumnHelper, flexRender, getCoreRowModel, useReactTable, } from "@tanstack/react-table"; import axios from "axios"; import clsx from "clsx"; import { capitalize } from "lodash"; import { useRouter } from "next/router"; import { BsCheck, BsTrash, BsUpload } from "react-icons/bs"; import { toast } from "react-toastify"; const CLASSES: { [key in Module]: string } = { reading: "text-ielts-reading", listening: "text-ielts-listening", speaking: "text-ielts-speaking", writing: "text-ielts-writing", level: "text-ielts-level", }; const columnHelper = createColumnHelper(); export default function ExamList({ user }: { user: User }) { const { exams, reload } = useExams(); const { users } = useUsers(); const parsedExams = useMemo(() => { return exams.map((exam) => { if (exam.createdBy) { const user = users.find((u) => u.id === exam.createdBy); if (!user) return exam; return { ...exam, createdBy: user.type === "developer" ? "system" : user.name, }; } return exam; }); }, [exams, users]); const setExams = useExamStore((state) => state.setExams); const setSelectedModules = useExamStore((state) => state.setSelectedModules); const router = useRouter(); const loadExam = async (module: Module, examId: string) => { const exam = await getExamById(module, examId.trim()); if (!exam) { toast.error( "Unknown Exam ID! Please make sure you selected the right module and entered the right exam ID", { toastId: "invalid-exam-id", } ); return; } setExams([exam]); setSelectedModules([module]); router.push("/exercises"); }; const deleteExam = async (exam: Exam) => { if ( !confirm( `Are you sure you want to delete this ${capitalize(exam.module)} exam?` ) ) return; axios .delete(`/api/exam/${exam.module}/${exam.id}`) .then(() => toast.success(`Deleted the "${exam.id}" exam`)) .catch((reason) => { if (reason.response.status === 404) { toast.error("Exam not found!"); return; } if (reason.response.status === 403) { toast.error("You do not have permission to delete this exam!"); return; } toast.error("Something went wrong, please try again later."); }) .finally(reload); }; const getTotalExercises = (exam: Exam) => { if ( exam.module === "reading" || exam.module === "listening" || exam.module === "level" ) { return countExercises(exam.parts.flatMap((x) => x.exercises)); } return countExercises(exam.exercises); }; const defaultColumns = [ columnHelper.accessor("id", { header: "ID", cell: (info) => info.getValue(), }), columnHelper.accessor("module", { header: "Module", cell: (info) => ( {capitalize(info.getValue())} ), }), columnHelper.accessor((x) => getTotalExercises(x), { header: "Exercises", cell: (info) => info.getValue(), }), columnHelper.accessor("minTimer", { header: "Timer", cell: (info) => <>{info.getValue()} minute(s), }), columnHelper.accessor("createdAt", { header: "Created At", cell: (info) => { const value = info.getValue(); if (value) { return new Date(value).toLocaleDateString(); } return null; }, }), columnHelper.accessor("createdBy", { header: "Created By", cell: (info) => info.getValue(), }), { header: "", id: "actions", cell: ({ row }: { row: { original: Exam } }) => { return (
await loadExam(row.original.module, row.original.id) } >
{PERMISSIONS.examManagement.delete.includes(user.type) && (
deleteExam(row.original)} >
)}
); }, }, ]; const table = useReactTable({ data: parsedExams, columns: defaultColumns, getCoreRowModel: getCoreRowModel(), }); return ( {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( ))} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( ))} ))}
{header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
); }