Solved the same bug but for the e-mail

This commit is contained in:
Tiago Ribeiro
2024-01-29 15:40:50 +00:00
parent 8bff64dd13
commit 3564d0af6b

View File

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