From 5eaa0ac26949618be8ccd911b42a421d4b9aabba Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Thu, 7 Dec 2023 18:23:00 +0000 Subject: [PATCH] Assignments now generate unique list of exams for each user --- src/dashboards/AssignmentCreator.tsx | 54 ++++++++++------------ src/interfaces/results.ts | 2 +- src/pages/api/assignments/index.ts | 69 ++++++++++++++++++++++++++-- 3 files changed, 91 insertions(+), 34 deletions(-) diff --git a/src/dashboards/AssignmentCreator.tsx b/src/dashboards/AssignmentCreator.tsx index 08b29b90..e55faa60 100644 --- a/src/dashboards/AssignmentCreator.tsx +++ b/src/dashboards/AssignmentCreator.tsx @@ -46,36 +46,32 @@ export default function AssignmentCreator({isCreating, assignment, assigner, gro }; const createAssignment = () => { - setIsLoading(true); + setIsLoading(true); - const examPromises = selectedModules.map(async (module) => getExam(module, false)); - Promise.all(examPromises) - .then((exams) => { - (assignment ? axios.patch : axios.post)(`/api/assignments${assignment ? `/${assignment.id}` : ""}`, { - assigner, - assignees, - name, - startDate, - endDate, - results: [], - exams: exams.map((e) => ({module: e?.module, id: e?.id})), - }) - .then(() => { - toast.success(`The assignment "${name}" has been ${assignment ? "updated" : "created"} successfully!`); - cancelCreation(); - }) - .catch((e) => { - console.log(e); - toast.error("Something went wrong, please try again later!"); - }) - .finally(() => setIsLoading(false)); - }) - .catch((e) => { - console.log(e); - toast.error("Something went wrong, please try again later!"); - setIsLoading(false); - }); - }; + (assignment ? axios.patch : axios.post)( + `/api/assignments${assignment ? `/${assignment.id}` : ""}`, + { + assignees, + name, + startDate, + endDate, + selectedModules + } + ) + .then(() => { + toast.success( + `The assignment "${name}" has been ${ + assignment ? "updated" : "created" + } successfully!` + ); + cancelCreation(); + }) + .catch((e) => { + console.log(e); + toast.error("Something went wrong, please try again later!"); + }) + .finally(() => setIsLoading(false)); + }; const deleteAssignment = () => { if (assignment) { diff --git a/src/interfaces/results.ts b/src/interfaces/results.ts index 1acadec3..b3e6d9e3 100644 --- a/src/interfaces/results.ts +++ b/src/interfaces/results.ts @@ -19,7 +19,7 @@ export interface Assignment { type: "academic" | "general"; stats: Stat[]; }[]; - exams: {id: string; module: Module}[]; + exams: {id: string; module: Module, assignee: string}[]; startDate: Date; endDate: Date; } diff --git a/src/pages/api/assignments/index.ts b/src/pages/api/assignments/index.ts index eb59649e..37ee47a1 100644 --- a/src/pages/api/assignments/index.ts +++ b/src/pages/api/assignments/index.ts @@ -5,6 +5,10 @@ import {getFirestore, collection, getDocs, query, where, setDoc, doc} from "fire import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {uuidv4} from "@firebase/util"; +import { Module } from "@/interfaces"; +import { getExams } from "@/utils/exams.be"; +import { Exam } from "@/interfaces/exam"; +import { flatten } from "lodash"; const db = getFirestore(app); @@ -34,8 +38,65 @@ async function GET(req: NextApiRequest, res: NextApiResponse) { res.status(200).json(docs); } -async function POST(req: NextApiRequest, res: NextApiResponse) { - await setDoc(doc(db, "assignments", uuidv4()), {assigner: req.session.user?.id, ...req.body}); - - res.status(200).json({ok: true}); +interface ExamWithUser { + module: Module; + id: string; + assignee: string; +} + +function getRandomIndex(arr: any[]): number { + const randomIndex = Math.floor(Math.random() * arr.length); + return randomIndex; +} + +async function POST(req: NextApiRequest, res: NextApiResponse) { + const { selectedModules, assignees, ...body } = req.body as { + selectedModules: Module[]; + assignees: string[]; + }; + + // for optimization purposes, it would be better to create a new endpoint that returned the answers for all users at once + const allExams = await assignees.map(async (assignee) => { + const selectedModulePromises = await selectedModules.map( + async (module: Module) => { + try { + const exams: Exam[] = await getExams(db, module, "true", assignee); + + const exam = exams[getRandomIndex(exams)]; + if (exam) { + return { module: exam.module, id: exam.id, assignee }; + } + return null; + } catch (e) { + console.error(e); + return null; + } + }, + [] + ); + const newModules = await Promise.all(selectedModulePromises); + + return newModules; + }, []); + + const exams = flatten(await Promise.all(allExams)).filter( + (x) => x !== null + ) as ExamWithUser[]; + + if (exams.length === 0) { + res + .status(400) + .json({ ok: false, error: "No exams found for the selected modules" }); + return; + } + + await setDoc(doc(db, "assignments", uuidv4()), { + assigner: req.session.user?.id, + assignees, + results: [], + exams, + ...body, + }); + + res.status(200).json({ ok: true }); }