/* eslint-disable @next/next/no-img-element */ import AssignmentCard from "@/components/High/AssignmentCard"; import Button from "@/components/Low/Button"; import Separator from "@/components/Low/Separator"; import ProfileSummary from "@/components/ProfileSummary"; import { Session } from "@/hooks/useSessions"; import { Grading, Module } from "@/interfaces"; import { EntityWithRoles } from "@/interfaces/entity"; import { Exam } from "@/interfaces/exam"; import { InviteWithEntity } from "@/interfaces/invite"; import { Assignment } from "@/interfaces/results"; import { Stat, User } from "@/interfaces/user"; import { sessionOptions } from "@/lib/session"; import useExamStore from "@/stores/exam"; import { findBy, mapBy, redirect, serialize } from "@/utils"; import { requestUser } from "@/utils/api"; import { activeAssignmentFilter, futureAssignmentFilter, } from "@/utils/assignments"; import { getAssignmentsByAssignee } from "@/utils/assignments.be"; import { getExamsByIds } from "@/utils/exams.be"; import { sortByModule } from "@/utils/moduleUtils"; import { checkAccess } from "@/utils/permissions"; import { getSessionsByUser } from "@/utils/sessions.be"; import axios from "axios"; import clsx from "clsx"; import { withIronSessionSsr } from "iron-session/next"; import { uniqBy } from "lodash"; import Head from "next/head"; import { useRouter } from "next/router"; import { useMemo, useState } from "react"; import { BsArrowRepeat } from "react-icons/bs"; import { ToastContainer } from "react-toastify"; interface Props { user: User; entities: EntityWithRoles[]; assignments: Assignment[]; stats: Stat[]; exams: Exam[]; sessions: Session[]; invites: InviteWithEntity[]; grading: Grading; } export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res); const destination = Buffer.from(req.url || "/").toString("base64"); if (!user) return redirect(`/login?destination=${destination}`); if (!checkAccess(user, ["admin", "developer", "student"])) return redirect("/"); const assignments = (await getAssignmentsByAssignee( user.id, { archived: { $ne: true }, }, { _id: 0, id: 1, name: 1, startDate: 1, endDate: 1, exams: 1, results: 1, }, { sort: { startDate: 1 }, } )) as Assignment[]; const sessions = await getSessionsByUser( user.id, 0, { "assignment.id": { $in: mapBy(assignments, "id") }, }, { _id: 0, id: 1, assignment: 1, } ); const examIDs = uniqBy( assignments.reduce<{ module: Module; id: string; key: string }[]>( (acc, a) => { a.exams.forEach((e) => { if (e.assignee === user.id) acc.push({ module: e.module, id: e.id, key: `${e.module}_${e.id}`, }); }); return acc; }, [] ), "key" ); const exams = await getExamsByIds(examIDs); return { props: serialize({ user, assignments, exams, sessions }) }; }, sessionOptions); const destination = Buffer.from("/official-exam").toString("base64"); export default function OfficialExam({ user, entities, assignments, sessions, exams, }: Props) { const [isLoading, setIsLoading] = useState(false); const router = useRouter(); const dispatch = useExamStore((state) => state.dispatch); const reload = () => { setIsLoading(true); router.replace(router.asPath); setTimeout(() => setIsLoading(false), 500); }; const startAssignment = (assignment: Assignment) => { const assignmentExams = exams.filter((e) => { const exam = findBy(assignment.exams, "id", e.id); return !!exam && exam.module === e.module; }); if (assignmentExams.every((x) => !!x)) { const sortedAssignmentExams = assignmentExams.sort(sortByModule); dispatch({ type: "INIT_EXAM", payload: { exams: sortedAssignmentExams, modules: mapBy(sortedAssignmentExams, "module"), assignment, }, }); router.push( `/exam?assignment=${assignment.id}&destination=${destination}` ); } }; const loadSession = async (session: Session) => { dispatch({ type: "SET_SESSION", payload: { session } }); router.push( `/exam?assignment=${session.assignment?.id}&destination=${destination}` ); }; const logout = async () => { axios.post("/api/logout").finally(() => { setTimeout(() => router.reload(), 500); }); }; const studentAssignments = useMemo( () => [ ...assignments.filter(activeAssignmentFilter), ...assignments.filter(futureAssignmentFilter), ], [assignments] ); const assignmentSessions = useMemo(() => { const studentAssignmentsIDs = mapBy(studentAssignments, "id"); return sessions.filter((s) => studentAssignmentsIDs.includes(s.assignment?.id || "") ); }, [sessions, studentAssignments]); const entityLabels = useMemo( () => mapBy(entities, "label")?.join(","), [entities] ); return ( <> EnCoach <> {entities.length > 0 && (
{entityLabels}
)} {/* Assignments */}
Assignments
{studentAssignments.length === 0 && "Assignments will appear here. It seems that for now there are no assignments for you."} {studentAssignments.map((a) => ( s.assignment?.id === a.id )} startAssignment={startAssignment} resumeAssignment={loadSession} /> ))}
); }