Solved a bug on the assignments because of the multiple exams
This commit is contained in:
@@ -1,79 +1,115 @@
|
||||
import ProgressBar from "@/components/Low/ProgressBar";
|
||||
import useUsers from "@/hooks/useUsers";
|
||||
import {Module} from "@/interfaces";
|
||||
import {Assignment} from "@/interfaces/results";
|
||||
import {calculateBandScore} from "@/utils/score";
|
||||
import { Module } from "@/interfaces";
|
||||
import { Assignment } from "@/interfaces/results";
|
||||
import { calculateBandScore } from "@/utils/score";
|
||||
import clsx from "clsx";
|
||||
import moment from "moment";
|
||||
import {BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs";
|
||||
import {
|
||||
BsBook,
|
||||
BsClipboard,
|
||||
BsHeadphones,
|
||||
BsMegaphone,
|
||||
BsPen,
|
||||
} from "react-icons/bs";
|
||||
import { usePDFDownload } from "@/hooks/usePDFDownload";
|
||||
import { uniqBy } from "lodash";
|
||||
|
||||
interface Props {
|
||||
onClick?: () => void;
|
||||
allowDownload?: boolean;
|
||||
onClick?: () => void;
|
||||
allowDownload?: boolean;
|
||||
}
|
||||
|
||||
export default function AssignmentCard({id, name, assigner, startDate, endDate, assignees, results, exams, onClick, allowDownload}: Assignment & Props) {
|
||||
const {users} = useUsers();
|
||||
const renderPdfIcon = usePDFDownload("assignments");
|
||||
export default function AssignmentCard({
|
||||
id,
|
||||
name,
|
||||
assigner,
|
||||
startDate,
|
||||
endDate,
|
||||
assignees,
|
||||
results,
|
||||
exams,
|
||||
onClick,
|
||||
allowDownload,
|
||||
}: Assignment & Props) {
|
||||
const { users } = useUsers();
|
||||
const renderPdfIcon = usePDFDownload("assignments");
|
||||
|
||||
const calculateAverageModuleScore = (module: Module) => {
|
||||
const resultModuleBandScores = results.map((r) => {
|
||||
const moduleStats = r.stats.filter((s) => s.module === module);
|
||||
const calculateAverageModuleScore = (module: Module) => {
|
||||
const resultModuleBandScores = results.map((r) => {
|
||||
const moduleStats = r.stats.filter((s) => s.module === module);
|
||||
|
||||
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 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);
|
||||
});
|
||||
|
||||
return resultModuleBandScores.length === 0 ? -1 : resultModuleBandScores.reduce((acc, curr) => acc + curr, 0) / results.length;
|
||||
};
|
||||
return resultModuleBandScores.length === 0
|
||||
? -1
|
||||
: resultModuleBandScores.reduce((acc, curr) => acc + curr, 0) /
|
||||
results.length;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={onClick}
|
||||
className="w-[350px] h-fit flex flex-col gap-6 bg-white border border-mti-gray-platinum hover:drop-shadow p-4 cursor-pointer rounded-xl transition ease-in-out duration-300">
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-row justify-between">
|
||||
<h3 className="font-semibold text-xl">{name}</h3>
|
||||
{allowDownload && renderPdfIcon(id, "text-mti-gray-dim", "text-mti-gray-dim")}
|
||||
</div>
|
||||
<ProgressBar
|
||||
color={results.length / assignees.length < 0.5 ? "red" : "purple"}
|
||||
percentage={(results.length / assignees.length) * 100}
|
||||
label={`${results.length}/${assignees.length}`}
|
||||
className="h-5"
|
||||
textClassName={results.length / assignees.length < 0.5 ? "!text-mti-gray-dim font-light" : "text-white"}
|
||||
/>
|
||||
</div>
|
||||
<span className="flex gap-1 justify-between">
|
||||
<span>{moment(startDate).format("DD/MM/YY, HH:mm")}</span>
|
||||
<span>-</span>
|
||||
<span>{moment(endDate).format("DD/MM/YY, HH:mm")}</span>
|
||||
</span>
|
||||
<div className="grid grid-cols-4 gap-2 place-items-start w-full -md:mt-2">
|
||||
{exams.map(({module}) => (
|
||||
<div
|
||||
key={module}
|
||||
className={clsx(
|
||||
"flex gap-2 items-center w-fit text-white -md:px-4 xl:px-4 md:px-2 py-2 rounded-xl",
|
||||
module === "reading" && "bg-ielts-reading",
|
||||
module === "listening" && "bg-ielts-listening",
|
||||
module === "writing" && "bg-ielts-writing",
|
||||
module === "speaking" && "bg-ielts-speaking",
|
||||
module === "level" && "bg-ielts-level",
|
||||
)}>
|
||||
{module === "reading" && <BsBook className="w-4 h-4" />}
|
||||
{module === "listening" && <BsHeadphones className="w-4 h-4" />}
|
||||
{module === "writing" && <BsPen className="w-4 h-4" />}
|
||||
{module === "speaking" && <BsMegaphone className="w-4 h-4" />}
|
||||
{module === "level" && <BsClipboard className="w-4 h-4" />}
|
||||
{calculateAverageModuleScore(module) > -1 && (
|
||||
<span className="text-sm">{calculateAverageModuleScore(module).toFixed(1)}</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div
|
||||
onClick={onClick}
|
||||
className="border-mti-gray-platinum flex h-fit w-[350px] cursor-pointer flex-col gap-6 rounded-xl border bg-white p-4 transition duration-300 ease-in-out hover:drop-shadow"
|
||||
>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-row justify-between">
|
||||
<h3 className="text-xl font-semibold">{name}</h3>
|
||||
{allowDownload &&
|
||||
renderPdfIcon(id, "text-mti-gray-dim", "text-mti-gray-dim")}
|
||||
</div>
|
||||
<ProgressBar
|
||||
color={results.length / assignees.length < 0.5 ? "red" : "purple"}
|
||||
percentage={(results.length / assignees.length) * 100}
|
||||
label={`${results.length}/${assignees.length}`}
|
||||
className="h-5"
|
||||
textClassName={
|
||||
results.length / assignees.length < 0.5
|
||||
? "!text-mti-gray-dim font-light"
|
||||
: "text-white"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<span className="flex justify-between gap-1">
|
||||
<span>{moment(startDate).format("DD/MM/YY, HH:mm")}</span>
|
||||
<span>-</span>
|
||||
<span>{moment(endDate).format("DD/MM/YY, HH:mm")}</span>
|
||||
</span>
|
||||
<div className="-md:mt-2 grid w-full grid-cols-4 place-items-start gap-2">
|
||||
{uniqBy(exams, (x) => x.module).map(({ module }) => (
|
||||
<div
|
||||
key={module}
|
||||
className={clsx(
|
||||
"-md:px-4 flex w-fit items-center gap-2 rounded-xl py-2 text-white md:px-2 xl:px-4",
|
||||
module === "reading" && "bg-ielts-reading",
|
||||
module === "listening" && "bg-ielts-listening",
|
||||
module === "writing" && "bg-ielts-writing",
|
||||
module === "speaking" && "bg-ielts-speaking",
|
||||
module === "level" && "bg-ielts-level",
|
||||
)}
|
||||
>
|
||||
{module === "reading" && <BsBook className="h-4 w-4" />}
|
||||
{module === "listening" && <BsHeadphones className="h-4 w-4" />}
|
||||
{module === "writing" && <BsPen className="h-4 w-4" />}
|
||||
{module === "speaking" && <BsMegaphone className="h-4 w-4" />}
|
||||
{module === "level" && <BsClipboard className="h-4 w-4" />}
|
||||
{calculateAverageModuleScore(module) > -1 && (
|
||||
<span className="text-sm">
|
||||
{calculateAverageModuleScore(module).toFixed(1)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user