From 556f6421120c4361a2e8344f7962fb701c8f23ec Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Wed, 21 Aug 2024 22:19:15 +0100 Subject: [PATCH] ENCOA-86: Added an option to release exam results --- src/dashboards/AssignmentCard.tsx | 9 +++-- src/hooks/useAssignmentRelease.tsx | 42 +++++++++++++++++++++++ src/interfaces/results.ts | 1 + src/pages/api/assignments/[id]/release.ts | 33 ++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/hooks/useAssignmentRelease.tsx create mode 100644 src/pages/api/assignments/[id]/release.ts diff --git a/src/dashboards/AssignmentCard.tsx b/src/dashboards/AssignmentCard.tsx index 06c68e82..6466a335 100644 --- a/src/dashboards/AssignmentCard.tsx +++ b/src/dashboards/AssignmentCard.tsx @@ -10,6 +10,7 @@ import {usePDFDownload} from "@/hooks/usePDFDownload"; import {useAssignmentArchive} from "@/hooks/useAssignmentArchive"; import {uniqBy} from "lodash"; import {useAssignmentUnarchive} from "@/hooks/useAssignmentUnarchive"; +import {useAssignmentRelease} from "@/hooks/useAssignmentRelease"; import {getUserName} from "@/utils/users"; import {User} from "@/interfaces/user"; @@ -40,11 +41,14 @@ export default function AssignmentCard({ allowUnarchive, allowExcelDownload, users, + released, }: Assignment & Props) { const renderPdfIcon = usePDFDownload("assignments"); const renderExcelIcon = usePDFDownload("assignments", "excel"); const renderArchiveIcon = useAssignmentArchive(id, reload); const renderUnarchiveIcon = useAssignmentUnarchive(id, reload); + const renderReleaseIcon = useAssignmentRelease(id, reload); + const calculateAverageModuleScore = (module: Module) => { const resultModuleBandScores = results.map((r) => { @@ -66,10 +70,11 @@ export default function AssignmentCard({

{name}

- {allowDownload && renderPdfIcon(id, "text-mti-gray-dim", "text-mti-gray-dim")} - {allowExcelDownload && renderExcelIcon(id, "text-mti-gray-dim", "text-mti-gray-dim")} + {allowDownload && released && renderPdfIcon(id, "text-mti-gray-dim", "text-mti-gray-dim")} + {allowExcelDownload && released && renderExcelIcon(id, "text-mti-gray-dim", "text-mti-gray-dim")} {allowArchive && !archived && renderArchiveIcon("text-mti-gray-dim", "text-mti-gray-dim")} {allowUnarchive && archived && renderUnarchiveIcon("text-mti-gray-dim", "text-mti-gray-dim")} + {!released && renderReleaseIcon("text-mti-gray-dim", "text-mti-gray-dim")}
{ + const [loading, setLoading] = React.useState(false); + const archive = () => { + // archive assignment + setLoading(true); + axios + .post(`/api/assignments/${assignmentId}/release`) + .then((res) => { + toast.success("Assignment archived!"); + if (reload) reload(); + setLoading(false); + }) + .catch((err) => { + toast.error("Failed to archive the assignment!"); + setLoading(false); + }); + }; + + const renderIcon = (downloadClasses: string, loadingClasses: string) => { + if (loading) { + return ; + } + return ( +
{ + e.stopPropagation(); + archive(); + }}> + +
+ ); + }; + + return renderIcon; +}; diff --git a/src/interfaces/results.ts b/src/interfaces/results.ts index 1f4f4685..76c2cf84 100644 --- a/src/interfaces/results.ts +++ b/src/interfaces/results.ts @@ -25,4 +25,5 @@ export interface Assignment { startDate: Date; endDate: Date; archived?: boolean; + released?: boolean; } diff --git a/src/pages/api/assignments/[id]/release.ts b/src/pages/api/assignments/[id]/release.ts new file mode 100644 index 00000000..894524e4 --- /dev/null +++ b/src/pages/api/assignments/[id]/release.ts @@ -0,0 +1,33 @@ +import type { NextApiRequest, NextApiResponse } from "next"; +import { app } from "@/firebase"; +import { getFirestore, doc, getDoc, setDoc } from "firebase/firestore"; +import { withIronSessionApiRoute } from "iron-session/next"; +import { sessionOptions } from "@/lib/session"; + +const db = getFirestore(app); + +export default withIronSessionApiRoute(handler, sessionOptions); + +async function post(req: NextApiRequest, res: NextApiResponse) { + // verify if it's a logged user that is trying to archive + if (req.session.user) { + const { id } = req.query as { id: string }; + const docSnap = await getDoc(doc(db, "assignments", id)); + + if (!docSnap.exists()) { + res.status(404).json({ ok: false }); + return; + } + + await setDoc(docSnap.ref, { released: true }, { merge: true }); + res.status(200).json({ ok: true }); + return; + } + + res.status(401).json({ ok: false }); +} + +async function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method === "POST") return post(req, res); + res.status(404).json({ ok: false }); +}