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 });
+}