115 lines
3.2 KiB
TypeScript
115 lines
3.2 KiB
TypeScript
import useExams from "@/hooks/useExams";
|
|
import useUsers from "@/hooks/useUsers";
|
|
import {Module} from "@/interfaces";
|
|
import {Exam} from "@/interfaces/exam";
|
|
import {Type} from "@/interfaces/user";
|
|
import useExamStore from "@/stores/examStore";
|
|
import {getExamById} from "@/utils/exams";
|
|
import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table";
|
|
import clsx from "clsx";
|
|
import {capitalize} from "lodash";
|
|
import {useRouter} from "next/router";
|
|
import {BsCheck, 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",
|
|
};
|
|
|
|
const columnHelper = createColumnHelper<Exam>();
|
|
|
|
export default function ExamList() {
|
|
const {exams} = useExams();
|
|
|
|
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 defaultColumns = [
|
|
columnHelper.accessor("id", {
|
|
header: "ID",
|
|
cell: (info) => info.getValue(),
|
|
}),
|
|
columnHelper.accessor("module", {
|
|
header: "Module",
|
|
cell: (info) => <span className={CLASSES[info.getValue()]}>{capitalize(info.getValue())}</span>,
|
|
}),
|
|
columnHelper.accessor((x) => x.exercises.length, {
|
|
header: "Exercises",
|
|
cell: (info) => info.getValue(),
|
|
}),
|
|
columnHelper.accessor("minTimer", {
|
|
header: "Timer",
|
|
cell: (info) => <>{info.getValue()} minute(s)</>,
|
|
}),
|
|
{
|
|
header: "",
|
|
id: "actions",
|
|
cell: ({row}: {row: {original: Exam}}) => {
|
|
console.log(row.original);
|
|
return (
|
|
<div
|
|
data-tip="Load exam"
|
|
className="cursor-pointer tooltip"
|
|
onClick={async () => await loadExam(row.original.module, row.original.id)}>
|
|
<BsUpload className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
];
|
|
|
|
const table = useReactTable({
|
|
data: exams,
|
|
columns: defaultColumns,
|
|
getCoreRowModel: getCoreRowModel(),
|
|
});
|
|
|
|
return (
|
|
<table className="rounded-xl bg-mti-purple-ultralight/40 w-full">
|
|
<thead>
|
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
<tr key={headerGroup.id}>
|
|
{headerGroup.headers.map((header) => (
|
|
<th className="py-4" key={header.id}>
|
|
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
|
</th>
|
|
))}
|
|
</tr>
|
|
))}
|
|
</thead>
|
|
<tbody className="px-2">
|
|
{table.getRowModel().rows.map((row) => (
|
|
<tr className="bg-white rounded-lg shadow py-2" key={row.id}>
|
|
{row.getVisibleCells().map((cell) => (
|
|
<td className="px-4 py-2" key={cell.id}>
|
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
</td>
|
|
))}
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
);
|
|
}
|