diff --git a/src/dashboards/AssignmentView.tsx b/src/dashboards/AssignmentView.tsx index 42a68a7f..daa330de 100644 --- a/src/dashboards/AssignmentView.tsx +++ b/src/dashboards/AssignmentView.tsx @@ -1,354 +1,307 @@ +import Button from "@/components/Low/Button"; import ProgressBar from "@/components/Low/ProgressBar"; import Modal from "@/components/Modal"; import useUsers from "@/hooks/useUsers"; -import { Module } from "@/interfaces"; -import { Assignment } from "@/interfaces/results"; -import { Stat, User } from "@/interfaces/user"; +import {Module} from "@/interfaces"; +import {Assignment} from "@/interfaces/results"; +import {Stat, User} from "@/interfaces/user"; import useExamStore from "@/stores/examStore"; -import { getExamById } from "@/utils/exams"; -import { sortByModule } from "@/utils/moduleUtils"; -import { calculateBandScore } from "@/utils/score"; -import { convertToUserSolutions } from "@/utils/stats"; +import {getExamById} from "@/utils/exams"; +import {sortByModule} from "@/utils/moduleUtils"; +import {calculateBandScore} from "@/utils/score"; +import {convertToUserSolutions} from "@/utils/stats"; +import axios from "axios"; import clsx from "clsx"; -import { capitalize, uniqBy } from "lodash"; +import {capitalize, uniqBy} from "lodash"; import moment from "moment"; -import { useRouter } from "next/router"; -import { - BsBook, - BsClipboard, - BsHeadphones, - BsMegaphone, - BsPen, -} from "react-icons/bs"; +import {useRouter} from "next/router"; +import {BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs"; +import {toast} from "react-toastify"; interface Props { - isOpen: boolean; - assignment?: Assignment; - onClose: () => void; + isOpen: boolean; + assignment?: Assignment; + onClose: () => void; } -export default function AssignmentView({ isOpen, assignment, onClose }: Props) { - const { users } = useUsers(); - const router = useRouter(); +export default function AssignmentView({isOpen, assignment, onClose}: Props) { + const {users} = useUsers(); + const router = useRouter(); - const setExams = useExamStore((state) => state.setExams); - const setShowSolutions = useExamStore((state) => state.setShowSolutions); - const setUserSolutions = useExamStore((state) => state.setUserSolutions); - const setSelectedModules = useExamStore((state) => state.setSelectedModules); + const setExams = useExamStore((state) => state.setExams); + const setShowSolutions = useExamStore((state) => state.setShowSolutions); + const setUserSolutions = useExamStore((state) => state.setUserSolutions); + const setSelectedModules = useExamStore((state) => state.setSelectedModules); - const formatTimestamp = (timestamp: string) => { - const date = moment(parseInt(timestamp)); - const formatter = "YYYY/MM/DD - HH:mm"; + const deleteAssignment = async () => { + if (!confirm("Are you sure you want to delete this assignment?")) return; - return date.format(formatter); - }; + axios + .delete(`/api/assignments/${assignment?.id}`) + .then(() => toast.success(`Successfully deleted the assignment "${assignment?.name}".`)) + .catch(() => toast.error("Something went wrong, please try again later.")) + .finally(onClose); + }; - const calculateAverageModuleScore = (module: Module) => { - if (!assignment) return -1; + const formatTimestamp = (timestamp: string) => { + const date = moment(parseInt(timestamp)); + const formatter = "YYYY/MM/DD - HH:mm"; - const resultModuleBandScores = assignment.results.map((r) => { - const moduleStats = r.stats.filter((s) => s.module === module); + return date.format(formatter); + }; - const correct = moduleStats.reduce( - (acc, curr) => acc + curr.score.correct, - 0, - ); - const total = moduleStats.reduce( - (acc, curr) => acc + curr.score.total, - 0, - ); - return calculateBandScore(correct, total, module, r.type); - }); + const calculateAverageModuleScore = (module: Module) => { + if (!assignment) return -1; - return resultModuleBandScores.length === 0 - ? -1 - : resultModuleBandScores.reduce((acc, curr) => acc + curr, 0) / - assignment.results.length; - }; + const resultModuleBandScores = assignment.results.map((r) => { + const moduleStats = r.stats.filter((s) => s.module === module); - const aggregateScoresByModule = ( - stats: Stat[], - ): { module: Module; total: number; missing: number; correct: number }[] => { - const scores: { - [key in Module]: { total: number; missing: number; correct: number }; - } = { - reading: { - total: 0, - correct: 0, - missing: 0, - }, - listening: { - total: 0, - correct: 0, - missing: 0, - }, - writing: { - total: 0, - correct: 0, - missing: 0, - }, - speaking: { - total: 0, - correct: 0, - missing: 0, - }, - level: { - total: 0, - correct: 0, - missing: 0, - }, - }; + const correct = moduleStats.reduce((acc, curr) => acc + curr.score.correct, 0); + const total = moduleStats.reduce((acc, curr) => acc + curr.score.total, 0); + return calculateBandScore(correct, total, module, r.type); + }); - stats.forEach((x) => { - scores[x.module!] = { - total: scores[x.module!].total + x.score.total, - correct: scores[x.module!].correct + x.score.correct, - missing: scores[x.module!].missing + x.score.missing, - }; - }); + return resultModuleBandScores.length === 0 ? -1 : resultModuleBandScores.reduce((acc, curr) => acc + curr, 0) / assignment.results.length; + }; - return Object.keys(scores) - .filter((x) => scores[x as Module].total > 0) - .map((x) => ({ module: x as Module, ...scores[x as Module] })); - }; + const aggregateScoresByModule = (stats: Stat[]): {module: Module; total: number; missing: number; correct: number}[] => { + const scores: { + [key in Module]: {total: number; missing: number; correct: number}; + } = { + reading: { + total: 0, + correct: 0, + missing: 0, + }, + listening: { + total: 0, + correct: 0, + missing: 0, + }, + writing: { + total: 0, + correct: 0, + missing: 0, + }, + speaking: { + total: 0, + correct: 0, + missing: 0, + }, + level: { + total: 0, + correct: 0, + missing: 0, + }, + }; - const customContent = ( - stats: Stat[], - user: string, - focus: "academic" | "general", - ) => { - const correct = stats.reduce( - (accumulator, current) => accumulator + current.score.correct, - 0, - ); - const total = stats.reduce( - (accumulator, current) => accumulator + current.score.total, - 0, - ); - const aggregatedScores = aggregateScoresByModule(stats).filter( - (x) => x.total > 0, - ); + stats.forEach((x) => { + scores[x.module!] = { + total: scores[x.module!].total + x.score.total, + correct: scores[x.module!].correct + x.score.correct, + missing: scores[x.module!].missing + x.score.missing, + }; + }); - const aggregatedLevels = aggregatedScores.map((x) => ({ - module: x.module, - level: calculateBandScore(x.correct, x.total, x.module, focus), - })); + return Object.keys(scores) + .filter((x) => scores[x as Module].total > 0) + .map((x) => ({module: x as Module, ...scores[x as Module]})); + }; - const timeSpent = stats[0].timeSpent; + const customContent = (stats: Stat[], user: string, focus: "academic" | "general") => { + const correct = stats.reduce((accumulator, current) => accumulator + current.score.correct, 0); + const total = stats.reduce((accumulator, current) => accumulator + current.score.total, 0); + const aggregatedScores = aggregateScoresByModule(stats).filter((x) => x.total > 0); - const selectExam = () => { - const examPromises = uniqBy(stats, "exam").map((stat) => - getExamById(stat.module, stat.exam), - ); + const aggregatedLevels = aggregatedScores.map((x) => ({ + module: x.module, + level: calculateBandScore(x.correct, x.total, x.module, focus), + })); - Promise.all(examPromises).then((exams) => { - if (exams.every((x) => !!x)) { - setUserSolutions(convertToUserSolutions(stats)); - setShowSolutions(true); - setExams(exams.map((x) => x!).sort(sortByModule)); - setSelectedModules( - exams - .map((x) => x!) - .sort(sortByModule) - .map((x) => x!.module), - ); - router.push("/exercises"); - } - }); - }; + const timeSpent = stats[0].timeSpent; - const content = ( - <> -