From 74a53f55fd170cdcceb87869c34de9e89d4d9dca Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Sat, 24 Aug 2024 17:38:57 +0100 Subject: [PATCH] Added option to start exam which serves as an alternative to start date for the exam --- src/dashboards/AssignmentCreator.tsx | 918 ++++++++++------ src/dashboards/Corporate.tsx | 1346 +++++++++++++---------- src/dashboards/MasterCorporate.tsx | 51 +- src/dashboards/Student.tsx | 4 +- src/dashboards/Teacher.tsx | 810 ++++++++------ src/interfaces/results.ts | 3 + src/pages/api/assignments/[id]/start.ts | 46 + src/utils/assignments.ts | 18 + 8 files changed, 1850 insertions(+), 1346 deletions(-) create mode 100644 src/pages/api/assignments/[id]/start.ts create mode 100644 src/utils/assignments.ts diff --git a/src/dashboards/AssignmentCreator.tsx b/src/dashboards/AssignmentCreator.tsx index aa4cc716..7859b068 100644 --- a/src/dashboards/AssignmentCreator.tsx +++ b/src/dashboards/AssignmentCreator.tsx @@ -1,385 +1,593 @@ import Input from "@/components/Low/Input"; import Modal from "@/components/Modal"; -import {Module} from "@/interfaces"; +import { Module } from "@/interfaces"; import clsx from "clsx"; -import {useEffect, useState} from "react"; -import {BsBook, BsCheckCircle, BsClipboard, BsHeadphones, BsMegaphone, BsPen, BsXCircle} from "react-icons/bs"; -import {generate} from "random-words"; -import {capitalize} from "lodash"; +import { useEffect, useState } from "react"; +import { + BsBook, + BsCheckCircle, + BsClipboard, + BsHeadphones, + BsMegaphone, + BsPen, + BsXCircle, +} from "react-icons/bs"; +import { generate } from "random-words"; +import { capitalize } from "lodash"; import useUsers from "@/hooks/useUsers"; -import {Group, User} from "@/interfaces/user"; +import { Group, User } from "@/interfaces/user"; import ProgressBar from "@/components/Low/ProgressBar"; -import {calculateAverageLevel} from "@/utils/score"; +import { calculateAverageLevel } from "@/utils/score"; import Button from "@/components/Low/Button"; import ReactDatePicker from "react-datepicker"; import moment from "moment"; import axios from "axios"; -import {getExam} from "@/utils/exams"; -import {toast} from "react-toastify"; -import {Assignment} from "@/interfaces/results"; +import { getExam } from "@/utils/exams"; +import { toast } from "react-toastify"; +import { Assignment } from "@/interfaces/results"; import Checkbox from "@/components/Low/Checkbox"; -import {InstructorGender, Variant} from "@/interfaces/exam"; +import { InstructorGender, Variant } from "@/interfaces/exam"; import Select from "@/components/Low/Select"; import useExams from "@/hooks/useExams"; interface Props { - isCreating: boolean; - assigner: string; - users: User[]; - groups: Group[]; - assignment?: Assignment; - cancelCreation: () => void; + isCreating: boolean; + assigner: string; + users: User[]; + groups: Group[]; + assignment?: Assignment; + cancelCreation: () => void; } -export default function AssignmentCreator({isCreating, assignment, assigner, groups, users, cancelCreation}: Props) { - const [selectedModules, setSelectedModules] = useState(assignment?.exams.map((e) => e.module) || []); - const [assignees, setAssignees] = useState(assignment?.assignees || []); - const [name, setName] = useState(assignment?.name || generate({minLength: 6, maxLength: 8, min: 2, max: 3, join: " ", formatter: capitalize})); - const [isLoading, setIsLoading] = useState(false); - const [startDate, setStartDate] = useState(assignment ? moment(assignment.startDate).toDate() : new Date()); - const [endDate, setEndDate] = useState( - assignment ? moment(assignment.endDate).toDate() : moment().hours(23).minutes(59).add(8, "day").toDate(), - ); - const [variant, setVariant] = useState("full"); - const [instructorGender, setInstructorGender] = useState(assignment?.instructorGender || "varied"); - // creates a new exam for each assignee or just one exam for all assignees - const [generateMultiple, setGenerateMultiple] = useState(false); - const [useRandomExams, setUseRandomExams] = useState(true); - const [examIDs, setExamIDs] = useState<{id: string; module: Module}[]>([]); +export default function AssignmentCreator({ + isCreating, + assignment, + assigner, + groups, + users, + cancelCreation, +}: Props) { + const [selectedModules, setSelectedModules] = useState( + assignment?.exams.map((e) => e.module) || [] + ); + const [assignees, setAssignees] = useState( + assignment?.assignees || [] + ); + const [name, setName] = useState( + assignment?.name || + generate({ + minLength: 6, + maxLength: 8, + min: 2, + max: 3, + join: " ", + formatter: capitalize, + }) + ); + const [isLoading, setIsLoading] = useState(false); + const [startDate, setStartDate] = useState( + assignment ? moment(assignment.startDate).toDate() : new Date() + ); + const [endDate, setEndDate] = useState( + assignment + ? moment(assignment.endDate).toDate() + : moment().hours(23).minutes(59).add(8, "day").toDate() + ); + const [variant, setVariant] = useState("full"); + const [instructorGender, setInstructorGender] = useState( + assignment?.instructorGender || "varied" + ); + // creates a new exam for each assignee or just one exam for all assignees + const [generateMultiple, setGenerateMultiple] = useState(false); + const [useRandomExams, setUseRandomExams] = useState(true); + const [examIDs, setExamIDs] = useState<{ id: string; module: Module }[]>([]); - const {exams} = useExams(); + const { exams } = useExams(); - useEffect(() => { - setExamIDs((prev) => prev.filter((x) => selectedModules.includes(x.module))); - }, [selectedModules]); + useEffect(() => { + setExamIDs((prev) => + prev.filter((x) => selectedModules.includes(x.module)) + ); + }, [selectedModules]); - const toggleModule = (module: Module) => { - const modules = selectedModules.filter((x) => x !== module); - setSelectedModules((prev) => (prev.includes(module) ? modules : [...modules, module])); - }; + const toggleModule = (module: Module) => { + const modules = selectedModules.filter((x) => x !== module); + setSelectedModules((prev) => + prev.includes(module) ? modules : [...modules, module] + ); + }; - const toggleAssignee = (user: User) => { - setAssignees((prev) => (prev.includes(user.id) ? prev.filter((a) => a !== user.id) : [...prev, user.id])); - }; + const toggleAssignee = (user: User) => { + setAssignees((prev) => + prev.includes(user.id) + ? prev.filter((a) => a !== user.id) + : [...prev, user.id] + ); + }; - const createAssignment = () => { - setIsLoading(true); + const createAssignment = () => { + setIsLoading(true); - (assignment ? axios.patch : axios.post)(`/api/assignments${assignment ? `/${assignment.id}` : ""}`, { - assignees, - name, - startDate, - examIDs: !useRandomExams ? examIDs : undefined, - endDate, - selectedModules, - generateMultiple, - variant, - instructorGender, + (assignment ? axios.patch : axios.post)( + `/api/assignments${assignment ? `/${assignment.id}` : ""}`, + { + assignees, + name, + startDate, + examIDs: !useRandomExams ? examIDs : undefined, + endDate, + selectedModules, + generateMultiple, + variant, + instructorGender, + } + ) + .then(() => { + toast.success( + `The assignment "${name}" has been ${ + assignment ? "updated" : "created" + } successfully!` + ); + cancelCreation(); + }) + .catch((e) => { + console.log(e); + toast.error("Something went wrong, please try again later!"); + }) + .finally(() => setIsLoading(false)); + }; + + const deleteAssignment = () => { + if (assignment) { + setIsLoading(true); + + if ( + !confirm( + `Are you sure you want to delete the "${assignment.name}" assignment?` + ) + ) + return; + axios + .delete(`api/assignments/${assignment.id}`) + .then(() => { + toast.success( + `The assignment "${name}" has been deleted successfully!` + ); + cancelCreation(); + }) + .catch((e) => { + console.log(e); + toast.error("Something went wrong, please try again later!"); + }) + .finally(() => setIsLoading(false)); + } + }; + + const startAssignment = () => { + if (assignment) { + setIsLoading(true); + + axios + .post(`/api/assignments/${assignment.id}/start`) + .then(() => { + toast.success( + `The assignment "${name}" has been started successfully!` + ); + cancelCreation(); }) - .then(() => { - toast.success(`The assignment "${name}" has been ${assignment ? "updated" : "created"} successfully!`); - cancelCreation(); - }) - .catch((e) => { - console.log(e); - toast.error("Something went wrong, please try again later!"); - }) - .finally(() => setIsLoading(false)); - }; + .catch((e) => { + console.log(e); + toast.error("Something went wrong, please try again later!"); + }) + .finally(() => setIsLoading(false)); + } + } - const deleteAssignment = () => { - if (assignment) { - setIsLoading(true); + return ( + +
+
+
toggleModule("reading") + : 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-2", + selectedModules.includes("reading") + ? "border-mti-purple-light" + : "border-mti-gray-platinum" + )} + > +
+ +
+ Reading + {!selectedModules.includes("reading") && + !selectedModules.includes("level") && ( +
+ )} + {selectedModules.includes("level") && ( + + )} + {selectedModules.includes("reading") && ( + + )} +
+
toggleModule("listening") + : 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-2", + selectedModules.includes("listening") + ? "border-mti-purple-light" + : "border-mti-gray-platinum" + )} + > +
+ +
+ Listening + {!selectedModules.includes("listening") && + !selectedModules.includes("level") && ( +
+ )} + {selectedModules.includes("level") && ( + + )} + {selectedModules.includes("listening") && ( + + )} +
+
toggleModule("writing") + : 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-2", + selectedModules.includes("writing") + ? "border-mti-purple-light" + : "border-mti-gray-platinum" + )} + > +
+ +
+ Writing + {!selectedModules.includes("writing") && + !selectedModules.includes("level") && ( +
+ )} + {selectedModules.includes("level") && ( + + )} + {selectedModules.includes("writing") && ( + + )} +
+
toggleModule("speaking") + : 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("speaking") + ? "border-mti-purple-light" + : "border-mti-gray-platinum" + )} + > +
+ +
+ Speaking + {!selectedModules.includes("speaking") && + !selectedModules.includes("level") && ( +
+ )} + {selectedModules.includes("level") && ( + + )} + {selectedModules.includes("speaking") && ( + + )} +
+
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" + )} + > +
+ +
+ Level + {!selectedModules.includes("level") && + selectedModules.length === 0 && ( +
+ )} + {!selectedModules.includes("level") && + selectedModules.length > 0 && ( + + )} + {selectedModules.includes("level") && ( + + )} +
+
- if (!confirm(`Are you sure you want to delete the "${assignment.name}" assignment?`)) return; - axios - .delete(`api/assignments/${assignment.id}`) - .then(() => { - toast.success(`The assignment "${name}" has been deleted successfully!`); - cancelCreation(); - }) - .catch((e) => { - console.log(e); - toast.error("Something went wrong, please try again later!"); - }) - .finally(() => setIsLoading(false)); - } - }; + setName(e)} + defaultValue={name} + label="Assignment Name" + required + /> - return ( - -
-
-
toggleModule("reading") : 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-2", - selectedModules.includes("reading") ? "border-mti-purple-light" : "border-mti-gray-platinum", - )}> -
- -
- Reading - {!selectedModules.includes("reading") && !selectedModules.includes("level") && ( -
- )} - {selectedModules.includes("level") && } - {selectedModules.includes("reading") && } -
-
toggleModule("listening") : 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-2", - selectedModules.includes("listening") ? "border-mti-purple-light" : "border-mti-gray-platinum", - )}> -
- -
- Listening - {!selectedModules.includes("listening") && !selectedModules.includes("level") && ( -
- )} - {selectedModules.includes("level") && } - {selectedModules.includes("listening") && } -
-
toggleModule("writing") : 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-2", - selectedModules.includes("writing") ? "border-mti-purple-light" : "border-mti-gray-platinum", - )}> -
- -
- Writing - {!selectedModules.includes("writing") && !selectedModules.includes("level") && ( -
- )} - {selectedModules.includes("level") && } - {selectedModules.includes("writing") && } -
-
toggleModule("speaking") : 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("speaking") ? "border-mti-purple-light" : "border-mti-gray-platinum", - )}> -
- -
- Speaking - {!selectedModules.includes("speaking") && !selectedModules.includes("level") && ( -
- )} - {selectedModules.includes("level") && } - {selectedModules.includes("speaking") && } -
-
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", - )}> -
- -
- Level - {!selectedModules.includes("level") && selectedModules.length === 0 && ( -
- )} - {!selectedModules.includes("level") && selectedModules.length > 0 && } - {selectedModules.includes("level") && } -
-
+
+
+ + moment(date).isSameOrAfter(new Date())} + dateFormat="dd/MM/yyyy HH:mm" + selected={startDate} + showTimeSelect + onChange={(date) => setStartDate(date)} + /> +
+
+ + moment(date).isAfter(startDate)} + dateFormat="dd/MM/yyyy HH:mm" + selected={endDate} + showTimeSelect + onChange={(date) => setEndDate(date)} + /> +
+
- setName(e)} defaultValue={name} label="Assignment Name" required /> + {selectedModules.includes("speaking") && ( +
+ + e.module === module)?.id || null, + label: + examIDs.find((e) => e.module === module)?.id || "", + }} + onChange={(value) => + value + ? setExamIDs((prev) => [ + ...prev.filter((x) => x.module !== module), + { id: value.value!, module }, + ]) + : setExamIDs((prev) => + prev.filter((x) => x.module !== module) + ) + } + options={exams + .filter((x) => !x.isDiagnostic && x.module === module) + .map((x) => ({ value: x.id, label: x.id }))} + /> +
+ ))} +
+ )} +
+ )} - {selectedModules.includes("speaking") && ( -
- - e.module === module)?.id || null, - label: examIDs.find((e) => e.module === module)?.id || "", - }} - onChange={(value) => - value - ? setExamIDs((prev) => [...prev.filter((x) => x.module !== module), {id: value.value!, module}]) - : setExamIDs((prev) => prev.filter((x) => x.module !== module)) - } - options={exams - .filter((x) => !x.isDiagnostic && x.module === module) - .map((x) => ({value: x.id, label: x.id}))} - /> -
- ))} - - )} - - )} - -
- Assignees ({assignees.length} selected) -
- {groups.map((g) => ( - - ))} -
-
- {users.map((user) => ( -
toggleAssignee(user)} - className={clsx( - "p-4 flex flex-col gap-2 rounded-xl border cursor-pointer w-72", - "transition ease-in-out duration-300", - assignees.includes(user.id) ? "border-mti-purple" : "border-mti-gray-platinum", - )} - key={user.id}> - - {user.name} - {user.email} - - - - Groups:{" "} - {groups - .filter((g) => g.participants.includes(user.id)) - .map((g) => g.name) - .join(", ")} - -
- ))} -
-
-
- setVariant((prev) => (prev === "full" ? "partial" : "full"))}> - Full length exams - - setGenerateMultiple((d) => !d)}> - Generate different exams - -
-
- - {assignment && ( - - )} - -
- -
- ); +
+ + Assignees ({assignees.length} selected) + +
+ {groups.map((g) => ( + + ))} +
+
+ {users.map((user) => ( +
toggleAssignee(user)} + className={clsx( + "p-4 flex flex-col gap-2 rounded-xl border cursor-pointer w-72", + "transition ease-in-out duration-300", + assignees.includes(user.id) + ? "border-mti-purple" + : "border-mti-gray-platinum" + )} + key={user.id} + > + + {user.name} + {user.email} + + + + Groups:{" "} + {groups + .filter((g) => g.participants.includes(user.id)) + .map((g) => g.name) + .join(", ")} + +
+ ))} +
+
+
+ + setVariant((prev) => (prev === "full" ? "partial" : "full")) + } + > + Full length exams + + setGenerateMultiple((d) => !d)} + > + Generate different exams + +
+
+ + {assignment && ( + <> + + + + )} + +
+ + + ); } diff --git a/src/dashboards/Corporate.tsx b/src/dashboards/Corporate.tsx index 1f50539a..d8468326 100644 --- a/src/dashboards/Corporate.tsx +++ b/src/dashboards/Corporate.tsx @@ -2,646 +2,814 @@ import Modal from "@/components/Modal"; import useStats from "@/hooks/useStats"; import useUsers from "@/hooks/useUsers"; -import {CorporateUser, Group, Stat, User} from "@/interfaces/user"; +import { CorporateUser, Group, Stat, User } from "@/interfaces/user"; import UserList from "@/pages/(admin)/Lists/UserList"; -import {dateSorter} from "@/utils"; +import { dateSorter } from "@/utils"; import moment from "moment"; -import {useEffect, useState} from "react"; +import { useEffect, useState } from "react"; import { - BsArrowLeft, - BsClipboard2Data, - BsClipboard2DataFill, - BsClock, - BsGlobeCentralSouthAsia, - BsPaperclip, - BsPerson, - BsPersonAdd, - BsPersonFill, - BsPersonFillGear, - BsPersonGear, - BsPencilSquare, - BsPersonBadge, - BsPersonCheck, - BsPeople, - BsArrowRepeat, - BsPlus, - BsEnvelopePaper, + BsArrowLeft, + BsClipboard2Data, + BsClipboard2DataFill, + BsClock, + BsGlobeCentralSouthAsia, + BsPaperclip, + BsPerson, + BsPersonAdd, + BsPersonFill, + BsPersonFillGear, + BsPersonGear, + BsPencilSquare, + BsPersonBadge, + BsPersonCheck, + BsPeople, + BsArrowRepeat, + BsPlus, + BsEnvelopePaper, } from "react-icons/bs"; import UserCard from "@/components/UserCard"; import useGroups from "@/hooks/useGroups"; -import {averageLevelCalculator, calculateAverageLevel, calculateBandScore} from "@/utils/score"; -import {MODULE_ARRAY} from "@/utils/moduleUtils"; -import {Module} from "@/interfaces"; -import {groupByExam} from "@/utils/stats"; +import { + averageLevelCalculator, + calculateAverageLevel, + calculateBandScore, +} from "@/utils/score"; +import { MODULE_ARRAY } from "@/utils/moduleUtils"; +import { Module } from "@/interfaces"; +import { groupByExam } from "@/utils/stats"; import IconCard from "./IconCard"; import GroupList from "@/pages/(admin)/Lists/GroupList"; import useFilterStore from "@/stores/listFilterStore"; -import {useRouter} from "next/router"; +import { useRouter } from "next/router"; import useCodes from "@/hooks/useCodes"; -import {getUserCorporate} from "@/utils/groups"; +import { getUserCorporate } from "@/utils/groups"; import useAssignments from "@/hooks/useAssignments"; -import {Assignment} from "@/interfaces/results"; +import { Assignment } from "@/interfaces/results"; import AssignmentView from "./AssignmentView"; import AssignmentCreator from "./AssignmentCreator"; import clsx from "clsx"; import AssignmentCard from "./AssignmentCard"; -import {createColumnHelper} from "@tanstack/react-table"; +import { createColumnHelper } from "@tanstack/react-table"; import Checkbox from "@/components/Low/Checkbox"; import List from "@/components/List"; -import {getUserCompanyName} from "@/resources/user"; +import { getUserCompanyName } from "@/resources/user"; +import { + futureAssignmentFilter, + pastAssignmentFilter, + archivedAssignmentFilter, + activeAssignmentFilter +} from '@/utils/assignments'; interface Props { - user: CorporateUser; + user: CorporateUser; } -type StudentPerformanceItem = User & {corporateName: string; group: string}; -const StudentPerformanceList = ({items, stats, users}: {items: StudentPerformanceItem[]; stats: Stat[]; users: User[]}) => { - const [isShowingAmount, setIsShowingAmount] = useState(false); +type StudentPerformanceItem = User & { corporateName: string; group: string }; +const StudentPerformanceList = ({ + items, + stats, + users, +}: { + items: StudentPerformanceItem[]; + stats: Stat[]; + users: User[]; +}) => { + const [isShowingAmount, setIsShowingAmount] = useState(false); - const columnHelper = createColumnHelper(); + const columnHelper = createColumnHelper(); - const columns = [ - columnHelper.accessor("name", { - header: "Student Name", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("email", { - header: "E-mail", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("demographicInformation.passport_id", { - header: "ID", - cell: (info) => info.getValue() || "N/A", - }), - columnHelper.accessor("group", { - header: "Group", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("corporateName", { - header: "Corporate", - cell: (info) => info.getValue() || "N/A", - }), - columnHelper.accessor("levels.reading", { - header: "Reading", - cell: (info) => - !isShowingAmount - ? info.getValue() || 0 - : `${Object.keys(groupByExam(stats.filter((x) => x.module === "reading" && x.user === info.row.original.id))).length} exams`, - }), - columnHelper.accessor("levels.listening", { - header: "Listening", - cell: (info) => - !isShowingAmount - ? info.getValue() || 0 - : `${Object.keys(groupByExam(stats.filter((x) => x.module === "listening" && x.user === info.row.original.id))).length} exams`, - }), - columnHelper.accessor("levels.writing", { - header: "Writing", - cell: (info) => - !isShowingAmount - ? info.getValue() || 0 - : `${Object.keys(groupByExam(stats.filter((x) => x.module === "writing" && x.user === info.row.original.id))).length} exams`, - }), - columnHelper.accessor("levels.speaking", { - header: "Speaking", - cell: (info) => - !isShowingAmount - ? info.getValue() || 0 - : `${Object.keys(groupByExam(stats.filter((x) => x.module === "speaking" && x.user === info.row.original.id))).length} exams`, - }), - columnHelper.accessor("levels.level", { - header: "Level", - cell: (info) => - !isShowingAmount - ? info.getValue() || 0 - : `${Object.keys(groupByExam(stats.filter((x) => x.module === "level" && x.user === info.row.original.id))).length} exams`, - }), - columnHelper.accessor("levels", { - id: "overall_level", - header: "Overall", - cell: (info) => - !isShowingAmount - ? averageLevelCalculator( - users, - stats.filter((x) => x.user === info.row.original.id), - ).toFixed(1) - : `${Object.keys(groupByExam(stats.filter((x) => x.user === info.row.original.id))).length} exams`, - }), - ]; + const columns = [ + columnHelper.accessor("name", { + header: "Student Name", + cell: (info) => info.getValue(), + }), + columnHelper.accessor("email", { + header: "E-mail", + cell: (info) => info.getValue(), + }), + columnHelper.accessor("demographicInformation.passport_id", { + header: "ID", + cell: (info) => info.getValue() || "N/A", + }), + columnHelper.accessor("group", { + header: "Group", + cell: (info) => info.getValue(), + }), + columnHelper.accessor("corporateName", { + header: "Corporate", + cell: (info) => info.getValue() || "N/A", + }), + columnHelper.accessor("levels.reading", { + header: "Reading", + cell: (info) => + !isShowingAmount + ? info.getValue() || 0 + : `${ + Object.keys( + groupByExam( + stats.filter( + (x) => + x.module === "reading" && x.user === info.row.original.id + ) + ) + ).length + } exams`, + }), + columnHelper.accessor("levels.listening", { + header: "Listening", + cell: (info) => + !isShowingAmount + ? info.getValue() || 0 + : `${ + Object.keys( + groupByExam( + stats.filter( + (x) => + x.module === "listening" && + x.user === info.row.original.id + ) + ) + ).length + } exams`, + }), + columnHelper.accessor("levels.writing", { + header: "Writing", + cell: (info) => + !isShowingAmount + ? info.getValue() || 0 + : `${ + Object.keys( + groupByExam( + stats.filter( + (x) => + x.module === "writing" && x.user === info.row.original.id + ) + ) + ).length + } exams`, + }), + columnHelper.accessor("levels.speaking", { + header: "Speaking", + cell: (info) => + !isShowingAmount + ? info.getValue() || 0 + : `${ + Object.keys( + groupByExam( + stats.filter( + (x) => + x.module === "speaking" && x.user === info.row.original.id + ) + ) + ).length + } exams`, + }), + columnHelper.accessor("levels.level", { + header: "Level", + cell: (info) => + !isShowingAmount + ? info.getValue() || 0 + : `${ + Object.keys( + groupByExam( + stats.filter( + (x) => + x.module === "level" && x.user === info.row.original.id + ) + ) + ).length + } exams`, + }), + columnHelper.accessor("levels", { + id: "overall_level", + header: "Overall", + cell: (info) => + !isShowingAmount + ? averageLevelCalculator( + users, + stats.filter((x) => x.user === info.row.original.id) + ).toFixed(1) + : `${ + Object.keys( + groupByExam( + stats.filter((x) => x.user === info.row.original.id) + ) + ).length + } exams`, + }), + ]; - return ( -
- - Show Utilization - - - data={items.sort( - (a, b) => - averageLevelCalculator( - users, - stats.filter((x) => x.user === b.id), - ) - - averageLevelCalculator( - users, - stats.filter((x) => x.user === a.id), - ), - )} - columns={columns} - /> -
- ); + return ( +
+ + Show Utilization + + + data={items.sort( + (a, b) => + averageLevelCalculator( + users, + stats.filter((x) => x.user === b.id) + ) - + averageLevelCalculator( + users, + stats.filter((x) => x.user === a.id) + ) + )} + columns={columns} + /> +
+ ); }; -export default function CorporateDashboard({user}: Props) { - const [page, setPage] = useState(""); - const [selectedUser, setSelectedUser] = useState(); - const [showModal, setShowModal] = useState(false); - const [corporateUserToShow, setCorporateUserToShow] = useState(); - const [selectedAssignment, setSelectedAssignment] = useState(); - const [isCreatingAssignment, setIsCreatingAssignment] = useState(false); - const [userBalance, setUserBalance] = useState(0); +export default function CorporateDashboard({ user }: Props) { + const [page, setPage] = useState(""); + const [selectedUser, setSelectedUser] = useState(); + const [showModal, setShowModal] = useState(false); + const [corporateUserToShow, setCorporateUserToShow] = + useState(); + const [selectedAssignment, setSelectedAssignment] = useState(); + const [isCreatingAssignment, setIsCreatingAssignment] = useState(false); + const [userBalance, setUserBalance] = useState(0); - const {stats} = useStats(); - const {users, reload, isLoading} = useUsers(); - const {codes} = useCodes(user.id); - const {groups} = useGroups({admin: user.id}); - const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({corporate: user.id}); + const { stats } = useStats(); + const { users, reload, isLoading } = useUsers(); + const { codes } = useCodes(user.id); + const { groups } = useGroups({ admin: user.id }); + const { + assignments, + isLoading: isAssignmentsLoading, + reload: reloadAssignments, + } = useAssignments({ corporate: user.id }); - const appendUserFilters = useFilterStore((state) => state.appendUserFilter); - const router = useRouter(); + const appendUserFilters = useFilterStore((state) => state.appendUserFilter); + const router = useRouter(); - useEffect(() => { - setShowModal(!!selectedUser && page === ""); - }, [selectedUser, page]); + useEffect(() => { + setShowModal(!!selectedUser && page === ""); + }, [selectedUser, page]); - useEffect(() => { - const relatedGroups = groups.filter((x) => x.name === "Students" || x.name === "Teachers" || x.name === "Corporate"); - const usersInGroups = relatedGroups.map((x) => x.participants).flat(); - const filteredCodes = codes.filter((x) => !x.userId || !usersInGroups.includes(x.userId)); + useEffect(() => { + const relatedGroups = groups.filter( + (x) => + x.name === "Students" || x.name === "Teachers" || x.name === "Corporate" + ); + const usersInGroups = relatedGroups.map((x) => x.participants).flat(); + const filteredCodes = codes.filter( + (x) => !x.userId || !usersInGroups.includes(x.userId) + ); - setUserBalance(usersInGroups.length + filteredCodes.length); - }, [codes, groups]); + setUserBalance(usersInGroups.length + filteredCodes.length); + }, [codes, groups]); - useEffect(() => { - // in this case it fetches the master corporate account - getUserCorporate(user.id).then(setCorporateUserToShow); - }, [user]); + useEffect(() => { + // in this case it fetches the master corporate account + getUserCorporate(user.id).then(setCorporateUserToShow); + }, [user]); - const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(user.id); - const teacherFilter = (user: User) => user.type === "teacher" && groups.flatMap((g) => g.participants).includes(user.id); + const studentFilter = (user: User) => + user.type === "student" && + groups.flatMap((g) => g.participants).includes(user.id); + const teacherFilter = (user: User) => + user.type === "teacher" && + groups.flatMap((g) => g.participants).includes(user.id); - const getStatsByStudent = (user: User) => stats.filter((s) => s.user === user.id); + const getStatsByStudent = (user: User) => + stats.filter((s) => s.user === user.id); - const UserDisplay = (displayUser: User) => ( -
setSelectedUser(displayUser)} - className="flex w-full p-4 gap-4 items-center hover:bg-mti-purple-ultralight cursor-pointer transition ease-in-out duration-300"> - {displayUser.name} -
- {displayUser.name} - {displayUser.email} -
-
- ); + const UserDisplay = (displayUser: User) => ( +
setSelectedUser(displayUser)} + className="flex w-full p-4 gap-4 items-center hover:bg-mti-purple-ultralight cursor-pointer transition ease-in-out duration-300" + > + {displayUser.name} +
+ {displayUser.name} + {displayUser.email} +
+
+ ); - const StudentsList = () => { - const filter = (x: User) => - x.type === "student" && - (!!selectedUser - ? groups - .filter((g) => g.admin === selectedUser.id) - .flatMap((g) => g.participants) - .includes(x.id) || false - : groups.flatMap((g) => g.participants).includes(x.id)); + const StudentsList = () => { + const filter = (x: User) => + x.type === "student" && + (!!selectedUser + ? groups + .filter((g) => g.admin === selectedUser.id) + .flatMap((g) => g.participants) + .includes(x.id) || false + : groups.flatMap((g) => g.participants).includes(x.id)); - return ( - ( -
-
setPage("")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Students ({total})

-
- )} - /> - ); - }; + return ( + ( +
+
setPage("")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300" + > + + Back +
+

Students ({total})

+
+ )} + /> + ); + }; - const TeachersList = () => { - const filter = (x: User) => - x.type === "teacher" && - (!!selectedUser - ? groups - .filter((g) => g.admin === selectedUser.id) - .flatMap((g) => g.participants) - .includes(x.id) || false - : groups.flatMap((g) => g.participants).includes(x.id)); + const TeachersList = () => { + const filter = (x: User) => + x.type === "teacher" && + (!!selectedUser + ? groups + .filter((g) => g.admin === selectedUser.id) + .flatMap((g) => g.participants) + .includes(x.id) || false + : groups.flatMap((g) => g.participants).includes(x.id)); - return ( - ( -
-
setPage("")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Teachers ({total})

-
- )} - /> - ); - }; + return ( + ( +
+
setPage("")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300" + > + + Back +
+

Teachers ({total})

+
+ )} + /> + ); + }; - const GroupsList = () => { - const filter = (x: Group) => x.admin === user.id || x.participants.includes(user.id); + const GroupsList = () => { + const filter = (x: Group) => + x.admin === user.id || x.participants.includes(user.id); - return ( - <> -
-
setPage("")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-

Groups ({groups.filter(filter).length})

-
+ return ( + <> +
+
setPage("")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300" + > + + Back +
+

+ Groups ({groups.filter(filter).length}) +

+
- - - ); - }; + + + ); + }; - const AssignmentsPage = () => { - const activeFilter = (a: Assignment) => - moment(a.endDate).isAfter(moment()) && moment(a.startDate).isBefore(moment()) && a.assignees.length > a.results.length; - const pastFilter = (a: Assignment) => (moment(a.endDate).isBefore(moment()) || a.assignees.length === a.results.length) && !a.archived; - const archivedFilter = (a: Assignment) => a.archived; - const futureFilter = (a: Assignment) => moment(a.startDate).isAfter(moment()); + const AssignmentsPage = () => { + return ( + <> + { + setSelectedAssignment(undefined); + setIsCreatingAssignment(false); + reloadAssignments(); + }} + assignment={selectedAssignment} + /> + x.admin === user.id || x.participants.includes(user.id) + )} + users={users.filter( + (x) => + x.type === "student" && + (!!selectedUser + ? groups + .filter((g) => g.admin === selectedUser.id) + .flatMap((g) => g.participants) + .includes(x.id) || false + : groups.flatMap((g) => g.participants).includes(x.id)) + )} + assigner={user.id} + isCreating={isCreatingAssignment} + cancelCreation={() => { + setIsCreatingAssignment(false); + setSelectedAssignment(undefined); + reloadAssignments(); + }} + /> +
+
setPage("")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300" + > + + Back +
+
+ Reload + +
+
+
+

+ Active Assignments ({assignments.filter(activeAssignmentFilter).length}) +

+
+ {assignments.filter(activeAssignmentFilter).map((a) => ( + setSelectedAssignment(a)} + key={a.id} + /> + ))} +
+
+
+

+ Planned Assignments ({assignments.filter(futureAssignmentFilter).length}) +

+
+
setIsCreatingAssignment(true)} + className="w-[250px] h-[200px] flex flex-col gap-2 items-center justify-center bg-white hover:bg-mti-purple-ultralight text-mti-purple-light hover:text-mti-purple-dark border border-mti-gray-platinum hover:drop-shadow p-4 cursor-pointer rounded-xl transition ease-in-out duration-300" + > + + New Assignment +
+ {assignments.filter(futureAssignmentFilter).map((a) => ( + { + setSelectedAssignment(a); + setIsCreatingAssignment(true); + }} + key={a.id} + /> + ))} +
+
+
+

+ Past Assignments ({assignments.filter(pastAssignmentFilter).length}) +

+
+ {assignments.filter(pastAssignmentFilter).map((a) => ( + setSelectedAssignment(a)} + key={a.id} + allowDownload + reload={reloadAssignments} + allowArchive + allowExcelDownload + /> + ))} +
+
+
+

+ Archived Assignments ({assignments.filter(archivedAssignmentFilter).length}) +

+
+ {assignments.filter(archivedAssignmentFilter).map((a) => ( + setSelectedAssignment(a)} + key={a.id} + allowDownload + reload={reloadAssignments} + allowUnarchive + allowExcelDownload + /> + ))} +
+
+ + ); + }; - return ( - <> - { - setSelectedAssignment(undefined); - setIsCreatingAssignment(false); - reloadAssignments(); - }} - assignment={selectedAssignment} - /> - x.admin === user.id || x.participants.includes(user.id))} - users={users.filter( - (x) => - x.type === "student" && - (!!selectedUser - ? groups - .filter((g) => g.admin === selectedUser.id) - .flatMap((g) => g.participants) - .includes(x.id) || false - : groups.flatMap((g) => g.participants).includes(x.id)), - )} - assigner={user.id} - isCreating={isCreatingAssignment} - cancelCreation={() => { - setIsCreatingAssignment(false); - setSelectedAssignment(undefined); - reloadAssignments(); - }} - /> -
-
setPage("")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-
- Reload - -
-
-
-

Active Assignments ({assignments.filter(activeFilter).length})

-
- {assignments.filter(activeFilter).map((a) => ( - setSelectedAssignment(a)} key={a.id} /> - ))} -
-
-
-

Planned Assignments ({assignments.filter(futureFilter).length})

-
-
setIsCreatingAssignment(true)} - className="w-[250px] h-[200px] flex flex-col gap-2 items-center justify-center bg-white hover:bg-mti-purple-ultralight text-mti-purple-light hover:text-mti-purple-dark border border-mti-gray-platinum hover:drop-shadow p-4 cursor-pointer rounded-xl transition ease-in-out duration-300"> - - New Assignment -
- {assignments.filter(futureFilter).map((a) => ( - { - setSelectedAssignment(a); - setIsCreatingAssignment(true); - }} - key={a.id} - /> - ))} -
-
-
-

Past Assignments ({assignments.filter(pastFilter).length})

-
- {assignments.filter(pastFilter).map((a) => ( - setSelectedAssignment(a)} - key={a.id} - allowDownload - reload={reloadAssignments} - allowArchive - allowExcelDownload - /> - ))} -
-
-
-

Archived Assignments ({assignments.filter(archivedFilter).length})

-
- {assignments.filter(archivedFilter).map((a) => ( - setSelectedAssignment(a)} - key={a.id} - allowDownload - reload={reloadAssignments} - allowUnarchive - allowExcelDownload - /> - ))} -
-
- - ); - }; + const StudentPerformancePage = () => { + const students = users + .filter( + (x) => + x.type === "student" && + groups.flatMap((g) => g.participants).includes(x.id) + ) + .map((u) => ({ + ...u, + group: groups.find((x) => x.participants.includes(u.id))?.name || "N/A", + corporateName: getUserCompanyName(u, users, groups), + })); - const StudentPerformancePage = () => { - const students = users - .filter((x) => x.type === "student" && groups.flatMap((g) => g.participants).includes(x.id)) - .map((u) => ({ - ...u, - group: groups.find((x) => x.participants.includes(u.id))?.name || "N/A", - corporateName: getUserCompanyName(u, users, groups), - })); + return ( + <> +
+
setPage("")} + className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300" + > + + Back +
+
+ Reload + +
+
+ + + ); + }; - return ( - <> -
-
setPage("")} - className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"> - - Back -
-
- Reload - -
-
- - - ); - }; + const averageLevelCalculator = (studentStats: Stat[]) => { + const formattedStats = studentStats + .map((s) => ({ + focus: users.find((u) => u.id === s.user)?.focus, + score: s.score, + module: s.module, + })) + .filter((f) => !!f.focus); + const bandScores = formattedStats.map((s) => ({ + module: s.module, + level: calculateBandScore( + s.score.correct, + s.score.total, + s.module, + s.focus! + ), + })); - const averageLevelCalculator = (studentStats: Stat[]) => { - const formattedStats = studentStats - .map((s) => ({ - focus: users.find((u) => u.id === s.user)?.focus, - score: s.score, - module: s.module, - })) - .filter((f) => !!f.focus); - const bandScores = formattedStats.map((s) => ({ - module: s.module, - level: calculateBandScore(s.score.correct, s.score.total, s.module, s.focus!), - })); + const levels: { [key in Module]: number } = { + reading: 0, + listening: 0, + writing: 0, + speaking: 0, + level: 0, + }; + bandScores.forEach((b) => (levels[b.module] += b.level)); - const levels: {[key in Module]: number} = { - reading: 0, - listening: 0, - writing: 0, - speaking: 0, - level: 0, - }; - bandScores.forEach((b) => (levels[b.module] += b.level)); + return calculateAverageLevel(levels); + }; - return calculateAverageLevel(levels); - }; + const DefaultDashboard = () => ( + <> + {corporateUserToShow && ( +
+ Linked to:{" "} + + {corporateUserToShow?.corporateInformation?.companyInformation + .name || corporateUserToShow.name} + +
+ )} +
+ setPage("students")} + Icon={BsPersonFill} + label="Students" + value={users.filter(studentFilter).length} + color="purple" + /> + setPage("teachers")} + Icon={BsPencilSquare} + label="Teachers" + value={users.filter(teacherFilter).length} + color="purple" + /> + + groups.flatMap((g) => g.participants).includes(s.user) + ).length + } + color="purple" + /> + + groups.flatMap((g) => g.participants).includes(s.user) + ) + ).toFixed(1)} + color="purple" + /> + setPage("groups")} + Icon={BsPeople} + label="Groups" + value={groups.length} + color="purple" + /> + + + setPage("studentsPerformance")} + /> + +
- const DefaultDashboard = () => ( - <> - {corporateUserToShow && ( -
- Linked to: {corporateUserToShow?.corporateInformation?.companyInformation.name || corporateUserToShow.name} -
- )} -
- setPage("students")} - Icon={BsPersonFill} - label="Students" - value={users.filter(studentFilter).length} - color="purple" - /> - setPage("teachers")} - Icon={BsPencilSquare} - label="Teachers" - value={users.filter(teacherFilter).length} - color="purple" - /> - groups.flatMap((g) => g.participants).includes(s.user)).length} - color="purple" - /> - groups.flatMap((g) => g.participants).includes(s.user))).toFixed(1)} - color="purple" - /> - setPage("groups")} Icon={BsPeople} label="Groups" value={groups.length} color="purple" /> - - - setPage("studentsPerformance")} - /> - -
+
+
+ Latest students +
+ {users + .filter(studentFilter) + .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) + .map((x) => ( + + ))} +
+
+
+ Latest teachers +
+ {users + .filter(teacherFilter) + .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) + .map((x) => ( + + ))} +
+
+
+ Highest level students +
+ {users + .filter(studentFilter) + .sort( + (a, b) => + calculateAverageLevel(b.levels) - + calculateAverageLevel(a.levels) + ) + .map((x) => ( + + ))} +
+
+
+ Highest exam count students +
+ {users + .filter(studentFilter) + .sort( + (a, b) => + Object.keys(groupByExam(getStatsByStudent(b))).length - + Object.keys(groupByExam(getStatsByStudent(a))).length + ) + .map((x) => ( + + ))} +
+
+
+ + ); -
-
- Latest students -
- {users - .filter(studentFilter) - .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) - .map((x) => ( - - ))} -
-
-
- Latest teachers -
- {users - .filter(teacherFilter) - .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) - .map((x) => ( - - ))} -
-
-
- Highest level students -
- {users - .filter(studentFilter) - .sort((a, b) => calculateAverageLevel(b.levels) - calculateAverageLevel(a.levels)) - .map((x) => ( - - ))} -
-
-
- Highest exam count students -
- {users - .filter(studentFilter) - .sort( - (a, b) => - Object.keys(groupByExam(getStatsByStudent(b))).length - Object.keys(groupByExam(getStatsByStudent(a))).length, - ) - .map((x) => ( - - ))} -
-
-
- - ); + return ( + <> + setSelectedUser(undefined)}> + <> + {selectedUser && ( +
+ { + setSelectedUser(undefined); + if (shouldReload) reload(); + }} + onViewStudents={ + selectedUser.type === "corporate" || + selectedUser.type === "teacher" + ? () => { + appendUserFilters({ + id: "view-students", + filter: (x: User) => x.type === "student", + }); + appendUserFilters({ + id: "belongs-to-admin", + filter: (x: User) => + groups + .filter( + (g) => + g.admin === selectedUser.id || + g.participants.includes(selectedUser.id) + ) + .flatMap((g) => g.participants) + .includes(x.id), + }); - return ( - <> - setSelectedUser(undefined)}> - <> - {selectedUser && ( -
- { - setSelectedUser(undefined); - if (shouldReload) reload(); - }} - onViewStudents={ - selectedUser.type === "corporate" || selectedUser.type === "teacher" - ? () => { - appendUserFilters({ - id: "view-students", - filter: (x: User) => x.type === "student", - }); - appendUserFilters({ - id: "belongs-to-admin", - filter: (x: User) => - groups - .filter((g) => g.admin === selectedUser.id || g.participants.includes(selectedUser.id)) - .flatMap((g) => g.participants) - .includes(x.id), - }); + router.push("/list/users"); + } + : undefined + } + onViewTeachers={ + selectedUser.type === "corporate" || + selectedUser.type === "student" + ? () => { + appendUserFilters({ + id: "view-teachers", + filter: (x: User) => x.type === "teacher", + }); + appendUserFilters({ + id: "belongs-to-admin", + filter: (x: User) => + groups + .filter( + (g) => + g.admin === selectedUser.id || + g.participants.includes(selectedUser.id) + ) + .flatMap((g) => g.participants) + .includes(x.id), + }); - router.push("/list/users"); - } - : undefined - } - onViewTeachers={ - selectedUser.type === "corporate" || selectedUser.type === "student" - ? () => { - appendUserFilters({ - id: "view-teachers", - filter: (x: User) => x.type === "teacher", - }); - appendUserFilters({ - id: "belongs-to-admin", - filter: (x: User) => - groups - .filter((g) => g.admin === selectedUser.id || g.participants.includes(selectedUser.id)) - .flatMap((g) => g.participants) - .includes(x.id), - }); - - router.push("/list/users"); - } - : undefined - } - user={selectedUser} - /> -
- )} - -
- {page === "students" && } - {page === "teachers" && } - {page === "groups" && } - {page === "assignments" && } - {page === "studentsPerformance" && } - {page === "" && } - - ); + router.push("/list/users"); + } + : undefined + } + user={selectedUser} + /> +
+ )} + +
+ {page === "students" && } + {page === "teachers" && } + {page === "groups" && } + {page === "assignments" && } + {page === "studentsPerformance" && } + {page === "" && } + + ); } diff --git a/src/dashboards/MasterCorporate.tsx b/src/dashboards/MasterCorporate.tsx index b5ad4275..ab7f1663 100644 --- a/src/dashboards/MasterCorporate.tsx +++ b/src/dashboards/MasterCorporate.tsx @@ -66,21 +66,17 @@ import { PopoverTrigger, } from "@/components/ui/popover"; import MasterStatistical from "./MasterStatistical"; +import { + futureAssignmentFilter, + pastAssignmentFilter, + archivedAssignmentFilter, + activeAssignmentFilter +} from '@/utils/assignments'; interface Props { user: MasterCorporateUser; } -const activeFilter = (a: Assignment) => - moment(a.endDate).isAfter(moment()) && - moment(a.startDate).isBefore(moment()) && - a.assignees.length > a.results.length; -const pastFilter = (a: Assignment) => - (moment(a.endDate).isBefore(moment()) || - a.assignees.length === a.results.length) && - !a.archived; -const archivedFilter = (a: Assignment) => a.archived; -const futureFilter = (a: Assignment) => moment(a.startDate).isAfter(moment()); type StudentPerformanceItem = User & { corporate?: CorporateUser; @@ -469,7 +465,7 @@ export default function MasterCorporateDashboard({ user }: Props) { useEffect(() => { setCorporateAssignments( - assignments.filter(activeFilter).map((a) => ({ + assignments.filter(activeAssignmentFilter).map((a) => ({ ...a, corporate: !!users.find((x) => x.id === a.assigner) ? getCorporateUser( @@ -606,19 +602,6 @@ export default function MasterCorporateDashboard({ user }: Props) { ); }; - // const AssignmentsPage = () => { - // const activeFilter = (a: Assignment) => - // moment(a.endDate).isAfter(moment()) && - // moment(a.startDate).isBefore(moment()) && - // a.assignees.length > a.results.length; - // const pastFilter = (a: Assignment) => - // (moment(a.endDate).isBefore(moment()) || - // a.assignees.length === a.results.length) && - // !a.archived; - // const archivedFilter = (a: Assignment) => a.archived; - // const futureFilter = (a: Assignment) => - // moment(a.startDate).isAfter(moment()); - const StudentPerformancePage = () => { const students = users .filter( @@ -727,11 +710,11 @@ export default function MasterCorporateDashboard({ user }: Props) { Total:{" "} {assignments - .filter(activeFilter) + .filter(activeAssignmentFilter) .reduce((acc, curr) => acc + curr.results.length, 0)} / {assignments - .filter(activeFilter) + .filter(activeAssignmentFilter) .reduce((acc, curr) => curr.exams.length + acc, 0)} {Object.keys( @@ -761,10 +744,10 @@ export default function MasterCorporateDashboard({ user }: Props) {

- Active Assignments ({assignments.filter(activeFilter).length}) + Active Assignments ({assignments.filter(activeAssignmentFilter).length})

- {assignments.filter(activeFilter).map((a) => ( + {assignments.filter(activeAssignmentFilter).map((a) => (

- Planned Assignments ({assignments.filter(futureFilter).length}) + Planned Assignments ({assignments.filter(futureAssignmentFilter).length})

New Assignment
- {assignments.filter(futureFilter).map((a) => ( + {assignments.filter(futureAssignmentFilter).map((a) => (

- Past Assignments ({assignments.filter(pastFilter).length}) + Past Assignments ({assignments.filter(pastAssignmentFilter).length})

- {assignments.filter(pastFilter).map((a) => ( + {assignments.filter(pastAssignmentFilter).map((a) => (

- Archived Assignments ({assignments.filter(archivedFilter).length}) + Archived Assignments ({assignments.filter(archivedAssignmentFilter).length})

- {assignments.filter(archivedFilter).map((a) => ( + {assignments.filter(archivedAssignmentFilter).map((a) => (