From 3564d0af6be0edd088b1eeabb79f81ea76db8b0a Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Mon, 29 Jan 2024 15:40:50 +0000 Subject: [PATCH] Solved the same bug but for the e-mail --- src/pages/api/assignments/index.ts | 270 +++++++++++++++++------------ 1 file changed, 156 insertions(+), 114 deletions(-) diff --git a/src/pages/api/assignments/index.ts b/src/pages/api/assignments/index.ts index 5d454fe1..8e452acb 100644 --- a/src/pages/api/assignments/index.ts +++ b/src/pages/api/assignments/index.ts @@ -1,156 +1,198 @@ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type {NextApiRequest, NextApiResponse} from "next"; -import {app} from "@/firebase"; -import {getFirestore, collection, getDocs, query, where, setDoc, doc, getDoc} from "firebase/firestore"; -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, Variant} from "@/interfaces/exam"; -import {capitalize, flatten} from "lodash"; -import {User} from "@/interfaces/user"; +import type { NextApiRequest, NextApiResponse } from "next"; +import { app } from "@/firebase"; +import { + getFirestore, + collection, + getDocs, + query, + where, + setDoc, + doc, + getDoc, +} from "firebase/firestore"; +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, Variant } from "@/interfaces/exam"; +import { capitalize, flatten, uniqBy } from "lodash"; +import { User } from "@/interfaces/user"; import moment from "moment"; -import {sendEmail} from "@/email"; +import { sendEmail } from "@/email"; const db = getFirestore(app); export default withIronSessionApiRoute(handler, sessionOptions); async function handler(req: NextApiRequest, res: NextApiResponse) { - if (!req.session.user) { - res.status(401).json({ok: false}); - return; - } + if (!req.session.user) { + res.status(401).json({ ok: false }); + return; + } - if (req.method === "GET") return GET(req, res); - if (req.method === "POST") return POST(req, res); + if (req.method === "GET") return GET(req, res); + if (req.method === "POST") return POST(req, res); - res.status(404).json({ok: false}); + res.status(404).json({ ok: false }); } async function GET(req: NextApiRequest, res: NextApiResponse) { - const q = query(collection(db, "assignments")); - const snapshot = await getDocs(q); + const q = query(collection(db, "assignments")); + const snapshot = await getDocs(q); - const docs = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })); + const docs = snapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })); - res.status(200).json(docs); + res.status(200).json(docs); } interface ExamWithUser { - module: Module; - id: string; - assignee: string; + module: Module; + id: string; + assignee: string; } function getRandomIndex(arr: any[]): number { - const randomIndex = Math.floor(Math.random() * arr.length); - return randomIndex; + const randomIndex = Math.floor(Math.random() * arr.length); + return randomIndex; } const generateExams = async ( - generateMultiple: Boolean, - selectedModules: Module[], - assignees: string[], - variant?: Variant, + generateMultiple: Boolean, + selectedModules: Module[], + assignees: string[], + variant?: Variant, ): Promise => { - if (generateMultiple) { - // 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, variant); + if (generateMultiple) { + // for optimization purposes, it would be better to create a new endpoint that returned the answers for all users at once + const allExams = assignees.map(async (assignee) => { + const selectedModulePromises = selectedModules.map( + async (module: Module) => { + try { + const exams: Exam[] = await getExams( + db, + module, + "true", + assignee, + variant, + ); - 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); + 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; - }, []); + return newModules; + }, []); - const exams = flatten(await Promise.all(allExams)).filter((x) => x !== null) as ExamWithUser[]; - return exams; - } + const exams = flatten(await Promise.all(allExams)).filter( + (x) => x !== null, + ) as ExamWithUser[]; + return exams; + } - const selectedModulePromises = await selectedModules.map(async (module: Module) => { - const exams: Exam[] = await getExams(db, module, "false", undefined); - const exam = exams[getRandomIndex(exams)]; + const selectedModulePromises = selectedModules.map(async (module: Module) => { + const exams: Exam[] = await getExams(db, module, "false", undefined); + const exam = exams[getRandomIndex(exams)]; - if (exam) { - return {module: exam.module, id: exam.id}; - } - return null; - }); + if (exam) { + return { module: exam.module, id: exam.id }; + } + return null; + }); - const exams = await Promise.all(selectedModulePromises); - const examesFiltered = exams.filter((x) => x !== null) as ExamWithUser[]; - return flatten(assignees.map((assignee) => examesFiltered.map((exam) => ({...exam, assignee})))); + const exams = await Promise.all(selectedModulePromises); + const examesFiltered = exams.filter((x) => x !== null) as ExamWithUser[]; + return flatten( + assignees.map((assignee) => + examesFiltered.map((exam) => ({ ...exam, assignee })), + ), + ); }; async function POST(req: NextApiRequest, res: NextApiResponse) { - const { - selectedModules, - assignees, - // Generate multiple true would generate an unique exam for each user - // false would generate the same exam for all users - generateMultiple = false, - variant, - ...body - } = req.body as { - selectedModules: Module[]; - assignees: string[]; - generateMultiple: Boolean; - name: string; - startDate: string; - endDate: string; - variant?: Variant; - }; + const { + selectedModules, + assignees, + // Generate multiple true would generate an unique exam for each user + // false would generate the same exam for all users + generateMultiple = false, + variant, + ...body + } = req.body as { + selectedModules: Module[]; + assignees: string[]; + generateMultiple: Boolean; + name: string; + startDate: string; + endDate: string; + variant?: Variant; + }; - const exams: ExamWithUser[] = await generateExams(generateMultiple, selectedModules, assignees, variant); + const exams: ExamWithUser[] = await generateExams( + generateMultiple, + selectedModules, + assignees, + variant, + ); - if (exams.length === 0) { - res.status(400).json({ok: false, error: "No exams found for the selected modules"}); - return; - } + 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, - }); + await setDoc(doc(db, "assignments", uuidv4()), { + assigner: req.session.user?.id, + assignees, + results: [], + exams, + ...body, + }); - res.status(200).json({ok: true}); + res.status(200).json({ ok: true }); - for (const assigneeID of assignees) { - const assigneeSnapshot = await getDoc(doc(db, "users", assigneeID)); - if (!assigneeSnapshot.exists()) continue; + for (const assigneeID of assignees) { + const assigneeSnapshot = await getDoc(doc(db, "users", assigneeID)); + if (!assigneeSnapshot.exists()) continue; - const assignee = {id: assigneeID, ...assigneeSnapshot.data()} as User; - const name = body.name; - const teacher = req.session.user!; - const examModulesLabel = exams.map((x) => capitalize(x.module)).join(", "); - const startDate = moment(body.startDate).format("DD/MM/YYYY - HH:mm"); - const endDate = moment(body.endDate).format("DD/MM/YYYY - HH:mm"); + const assignee = { id: assigneeID, ...assigneeSnapshot.data() } as User; + const name = body.name; + const teacher = req.session.user!; + const examModulesLabel = uniqBy(exams, (x) => x.module) + .map((x) => capitalize(x.module)) + .join(", "); + const startDate = moment(body.startDate).format("DD/MM/YYYY - HH:mm"); + const endDate = moment(body.endDate).format("DD/MM/YYYY - HH:mm"); - await sendEmail( - "assignment", - {user: {name: assignee.name}, assignment: {name, startDate, endDate, modules: examModulesLabel, assigner: teacher.name}}, - [assignee.email], - "EnCoach - New Assignment!", - ); - } + await sendEmail( + "assignment", + { + user: { name: assignee.name }, + assignment: { + name, + startDate, + endDate, + modules: examModulesLabel, + assigner: teacher.name, + }, + }, + [assignee.email], + "EnCoach - New Assignment!", + ); + } }