Updated the assignments to work with the level exams

This commit is contained in:
Tiago Ribeiro
2023-11-18 00:19:26 +00:00
parent 19b3bbe139
commit 13c8459d4b
4 changed files with 84 additions and 50 deletions

View File

@@ -7,7 +7,7 @@ import {calculateBandScore} from "@/utils/score";
import clsx from "clsx"; import clsx from "clsx";
import moment from "moment"; import moment from "moment";
import {useState} from "react"; import {useState} from "react";
import {BsBook, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs"; import {BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs";
interface Props { interface Props {
onClick?: () => void; onClick?: () => void;
@@ -57,11 +57,13 @@ export default function AssignmentCard({id, name, assigner, startDate, endDate,
module === "listening" && "bg-ielts-listening", module === "listening" && "bg-ielts-listening",
module === "writing" && "bg-ielts-writing", module === "writing" && "bg-ielts-writing",
module === "speaking" && "bg-ielts-speaking", module === "speaking" && "bg-ielts-speaking",
module === "level" && "bg-ielts-level",
)}> )}>
{module === "reading" && <BsBook className="w-4 h-4" />} {module === "reading" && <BsBook className="w-4 h-4" />}
{module === "listening" && <BsHeadphones className="w-4 h-4" />} {module === "listening" && <BsHeadphones className="w-4 h-4" />}
{module === "writing" && <BsPen className="w-4 h-4" />} {module === "writing" && <BsPen className="w-4 h-4" />}
{module === "speaking" && <BsMegaphone className="w-4 h-4" />} {module === "speaking" && <BsMegaphone className="w-4 h-4" />}
{module === "level" && <BsClipboard className="w-4 h-4" />}
{calculateAverageModuleScore(module) > -1 && ( {calculateAverageModuleScore(module) > -1 && (
<span className="text-sm">{calculateAverageModuleScore(module).toFixed(1)}</span> <span className="text-sm">{calculateAverageModuleScore(module).toFixed(1)}</span>
)} )}

View File

@@ -3,7 +3,7 @@ import Modal from "@/components/Modal";
import {Module} from "@/interfaces"; import {Module} from "@/interfaces";
import clsx from "clsx"; import clsx from "clsx";
import {useState} from "react"; import {useState} from "react";
import {BsBook, BsCheckCircle, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs"; import {BsBook, BsCheckCircle, BsClipboard, BsHeadphones, BsMegaphone, BsPen, BsXCircle} from "react-icons/bs";
import {generate} from "random-words"; import {generate} from "random-words";
import {capitalize} from "lodash"; import {capitalize} from "lodash";
import useUsers from "@/hooks/useUsers"; import useUsers from "@/hooks/useUsers";
@@ -99,59 +99,96 @@ export default function AssignmentCreator({isCreating, assignment, assigner, gro
return ( return (
<Modal isOpen={isCreating} onClose={cancelCreation} title="New Assignment"> <Modal isOpen={isCreating} onClose={cancelCreation} title="New Assignment">
<div className="w-full flex flex-col gap-4"> <div className="w-full flex flex-col gap-4">
<section className="w-full grid -md:grid-cols-1 md:grid-cols-2 place-items-center lg:grid-cols-4 -md:flex-col -md:items-center -md:gap-12 justify-between gap-8 mt-8 px-8"> <section className="w-full grid -md:grid-cols-1 md:grid-cols-2 place-items-center lg:grid-cols-6 -md:flex-col -md:items-center -md:gap-12 justify-between gap-8 mt-8 px-8">
<div <div
onClick={() => toggleModule("reading")} onClick={!selectedModules.includes("level") ? () => toggleModule("reading") : undefined}
className={clsx( className={clsx(
"w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer",
"lg:col-span-2",
selectedModules.includes("reading") ? "border-mti-purple-light" : "border-mti-gray-platinum", selectedModules.includes("reading") ? "border-mti-purple-light" : "border-mti-gray-platinum",
)}> )}>
<div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-reading top-1/2 -translate-y-1/2 left-0 -translate-x-1/2"> <div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-reading top-1/2 -translate-y-1/2 left-0 -translate-x-1/2">
<BsBook className="text-white w-7 h-7" /> <BsBook className="text-white w-7 h-7" />
</div> </div>
<span className="ml-8 font-semibold">Reading</span> <span className="ml-8 font-semibold">Reading</span>
{!selectedModules.includes("reading") && <div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />} {!selectedModules.includes("reading") && !selectedModules.includes("level") && (
<div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />
)}
{selectedModules.includes("level") && <BsXCircle className="text-mti-red-light w-8 h-8" />}
{selectedModules.includes("reading") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />} {selectedModules.includes("reading") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />}
</div> </div>
<div <div
onClick={() => toggleModule("listening")} onClick={!selectedModules.includes("level") ? () => toggleModule("listening") : undefined}
className={clsx( className={clsx(
"w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer",
"lg:col-span-2",
selectedModules.includes("listening") ? "border-mti-purple-light" : "border-mti-gray-platinum", selectedModules.includes("listening") ? "border-mti-purple-light" : "border-mti-gray-platinum",
)}> )}>
<div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-listening top-1/2 -translate-y-1/2 left-0 -translate-x-1/2"> <div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-listening top-1/2 -translate-y-1/2 left-0 -translate-x-1/2">
<BsHeadphones className="text-white w-7 h-7" /> <BsHeadphones className="text-white w-7 h-7" />
</div> </div>
<span className="ml-8 font-semibold">Listening</span> <span className="ml-8 font-semibold">Listening</span>
{!selectedModules.includes("listening") && <div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />} {!selectedModules.includes("listening") && !selectedModules.includes("level") && (
<div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />
)}
{selectedModules.includes("level") && <BsXCircle className="text-mti-red-light w-8 h-8" />}
{selectedModules.includes("listening") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />} {selectedModules.includes("listening") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />}
</div> </div>
<div <div
onClick={() => toggleModule("writing")} onClick={!selectedModules.includes("level") ? () => toggleModule("writing") : undefined}
className={clsx( className={clsx(
"w-52 relative max-w-xs flex lg:flex-row-reverse items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer",
"lg:col-span-2",
selectedModules.includes("writing") ? "border-mti-purple-light" : "border-mti-gray-platinum", selectedModules.includes("writing") ? "border-mti-purple-light" : "border-mti-gray-platinum",
)}> )}>
<div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-writing top-1/2 -translate-y-1/2 -lg:left-0 -lg:-translate-x-1/2 lg:right-0 lg:translate-x-1/2"> <div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-writing top-1/2 -translate-y-1/2 left-0 -translate-x-1/2">
<BsPen className="text-white w-7 h-7" /> <BsPen className="text-white w-7 h-7" />
</div> </div>
<span className="lg:mr-8 -lg:ml-8 font-semibold">Writing</span> <span className="ml-8 font-semibold">Writing</span>
{!selectedModules.includes("writing") && <div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />} {!selectedModules.includes("writing") && !selectedModules.includes("level") && (
<div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />
)}
{selectedModules.includes("level") && <BsXCircle className="text-mti-red-light w-8 h-8" />}
{selectedModules.includes("writing") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />} {selectedModules.includes("writing") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />}
</div> </div>
<div <div
onClick={() => toggleModule("speaking")} onClick={!selectedModules.includes("level") ? () => toggleModule("speaking") : undefined}
className={clsx( className={clsx(
"w-52 relative max-w-xs flex lg:flex-row-reverse items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer", "w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer",
"lg:col-span-3",
selectedModules.includes("speaking") ? "border-mti-purple-light" : "border-mti-gray-platinum", selectedModules.includes("speaking") ? "border-mti-purple-light" : "border-mti-gray-platinum",
)}> )}>
<div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-speaking top-1/2 -translate-y-1/2 -lg:left-0 -lg:-translate-x-1/2 lg:right-0 lg:translate-x-1/2"> <div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-speaking top-1/2 -translate-y-1/2 left-0 -translate-x-1/2">
<BsMegaphone className="text-white w-7 h-7 lg:-scale-x-100" /> <BsMegaphone className="text-white w-7 h-7" />
</div> </div>
<span className="lg:mr-8 -lg:ml-8 font-semibold">Speaking</span> <span className="ml-8 font-semibold">Speaking</span>
{!selectedModules.includes("speaking") && <div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />} {!selectedModules.includes("speaking") && !selectedModules.includes("level") && (
<div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />
)}
{selectedModules.includes("level") && <BsXCircle className="text-mti-red-light w-8 h-8" />}
{selectedModules.includes("speaking") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />} {selectedModules.includes("speaking") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />}
</div> </div>
<div
onClick={
(!selectedModules.includes("level") && selectedModules.length === 0) || selectedModules.includes("level")
? () => toggleModule("level")
: undefined
}
className={clsx(
"w-52 relative max-w-xs flex items-center bg-mti-white-alt transition duration-300 ease-in-out border p-5 rounded-xl gap-8 cursor-pointer",
"lg:col-span-3",
selectedModules.includes("level") ? "border-mti-purple-light" : "border-mti-gray-platinum",
)}>
<div className="absolute w-16 h-16 flex items-center justify-center rounded-full bg-ielts-level top-1/2 -translate-y-1/2 left-0 -translate-x-1/2">
<BsClipboard className="text-white w-7 h-7" />
</div>
<span className="ml-8 font-semibold">Level</span>
{!selectedModules.includes("level") && selectedModules.length === 0 && (
<div className="border border-mti-gray-platinum w-8 h-8 rounded-full" />
)}
{!selectedModules.includes("level") && selectedModules.length > 0 && <BsXCircle className="text-mti-red-light w-8 h-8" />}
{selectedModules.includes("level") && <BsCheckCircle className="text-mti-purple-light w-8 h-8" />}
</div>
</section> </section>
<Input type="text" name="name" onChange={(e) => setName(e)} defaultValue={name} label="Assignment Name" required /> <Input type="text" name="name" onChange={(e) => setName(e)} defaultValue={name} label="Assignment Name" required />

View File

@@ -10,7 +10,7 @@ import {sortByModule} from "@/utils/moduleUtils";
import {calculateBandScore} from "@/utils/score"; import {calculateBandScore} from "@/utils/score";
import {convertToUserSolutions} from "@/utils/stats"; import {convertToUserSolutions} from "@/utils/stats";
import clsx from "clsx"; import clsx from "clsx";
import {uniqBy} from "lodash"; import {capitalize, uniqBy} from "lodash";
import moment from "moment"; import moment from "moment";
import {useRouter} from "next/router"; import {useRouter} from "next/router";
import {BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs"; import {BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs";
@@ -239,9 +239,10 @@ export default function AssignmentView({isOpen, assignment, onClose}: Props) {
<div className="grid grid-cols-4 gap-2 place-items-start w-full -md:mt-2"> <div className="grid grid-cols-4 gap-2 place-items-start w-full -md:mt-2">
{assignment?.exams.map(({module}) => ( {assignment?.exams.map(({module}) => (
<div <div
data-tip={capitalize(module)}
key={module} key={module}
className={clsx( className={clsx(
"flex gap-2 items-center w-fit text-white -md:px-4 xl:px-4 md:px-2 py-2 rounded-xl", "flex gap-2 items-center w-fit text-white -md:px-4 xl:px-4 md:px-2 py-2 rounded-xl tooltip",
module === "reading" && "bg-ielts-reading", module === "reading" && "bg-ielts-reading",
module === "listening" && "bg-ielts-listening", module === "listening" && "bg-ielts-listening",
module === "writing" && "bg-ielts-writing", module === "writing" && "bg-ielts-writing",

View File

@@ -7,14 +7,14 @@ import {Assignment} from "@/interfaces/results";
import {User} from "@/interfaces/user"; import {User} from "@/interfaces/user";
import useExamStore from "@/stores/examStore"; import useExamStore from "@/stores/examStore";
import {getExamById} from "@/utils/exams"; import {getExamById} from "@/utils/exams";
import {MODULE_ARRAY, sortByModule} from "@/utils/moduleUtils"; import {MODULE_ARRAY, sortByModule, sortByModuleName} from "@/utils/moduleUtils";
import {averageScore, groupBySession} from "@/utils/stats"; import {averageScore, groupBySession} from "@/utils/stats";
import clsx from "clsx"; import clsx from "clsx";
import {capitalize} from "lodash"; import {capitalize} from "lodash";
import moment from "moment"; import moment from "moment";
import Link from "next/link"; import Link from "next/link";
import {useRouter} from "next/router"; import {useRouter} from "next/router";
import {BsArrowRepeat, BsBook, BsFileEarmarkText, BsHeadphones, BsMegaphone, BsPen, BsPencil, BsStar} from "react-icons/bs"; import {BsArrowRepeat, BsBook, BsClipboard, BsFileEarmarkText, BsHeadphones, BsMegaphone, BsPen, BsPencil, BsStar} from "react-icons/bs";
interface Props { interface Props {
user: User; user: User;
@@ -115,32 +115,26 @@ export default function StudentDashboard({user}: Props) {
</div> </div>
<div className="flex justify-between w-full items-center"> <div className="flex justify-between w-full items-center">
<div className="grid grid-cols-2 gap-2 place-items-center justify-center w-fit min-w-[104px] -md:mt-2"> <div className="grid grid-cols-2 gap-2 place-items-center justify-center w-fit min-w-[104px] -md:mt-2">
{MODULE_ARRAY.map((module) => ( {assignment.exams
.map((e) => e.module)
.sort(sortByModuleName)
.map((module) => (
<div <div
key={module} key={module}
data-tip={capitalize(module)}
className={clsx( className={clsx(
"flex gap-2 items-center w-fit text-white -md:px-4 xl:px-4 md:px-2 py-2 rounded-xl", "flex gap-2 items-center w-fit text-white -md:px-4 xl:px-4 md:px-2 py-2 rounded-xl tooltip",
module === "reading" && module === "reading" && "bg-ielts-reading",
(assignment.exams.map((e) => e.module).includes("reading") module === "listening" && "bg-ielts-listening",
? "bg-ielts-reading" module === "writing" && "bg-ielts-writing",
: "bg-mti-black/40"), module === "speaking" && "bg-ielts-speaking",
module === "listening" && module === "level" && "bg-ielts-level",
(assignment.exams.map((e) => e.module).includes("listening")
? "bg-ielts-listening"
: "bg-mti-black/40"),
module === "writing" &&
(assignment.exams.map((e) => e.module).includes("writing")
? "bg-ielts-writing"
: "bg-mti-black/40"),
module === "speaking" &&
(assignment.exams.map((e) => e.module).includes("speaking")
? "bg-ielts-speaking"
: "bg-mti-black/40"),
)}> )}>
{module === "reading" && <BsBook className="w-4 h-4" />} {module === "reading" && <BsBook className="w-4 h-4" />}
{module === "listening" && <BsHeadphones className="w-4 h-4" />} {module === "listening" && <BsHeadphones className="w-4 h-4" />}
{module === "writing" && <BsPen className="w-4 h-4" />} {module === "writing" && <BsPen className="w-4 h-4" />}
{module === "speaking" && <BsMegaphone className="w-4 h-4" />} {module === "speaking" && <BsMegaphone className="w-4 h-4" />}
{module === "level" && <BsClipboard className="w-4 h-4" />}
</div> </div>
))} ))}
</div> </div>