{
- if (user.type === "corporate" || (user.type === "mastercorporate" && (!paymentValue || paymentValue < 0)))
+ if ((user.type === "corporate" || user.type === "mastercorporate") && (!paymentValue || paymentValue < 0))
return toast.error("Please set a price for the user's package before updating!");
+
if (!confirm(`Are you sure you want to update ${user.name}'s account?`)) return;
axios
@@ -213,7 +214,7 @@ const UserCard = ({
},
{
icon:
,
- value: user.corporateInformation.companyInformation.userAmount,
+ value: user.corporateInformation?.companyInformation?.userAmount,
label: "Number of Users",
},
]
@@ -277,7 +278,15 @@ const UserCard = ({
onChange={setCompanyName}
placeholder="Enter corporate name"
defaultValue={companyName}
- disabled={disabled || checkAccess(loggedInUser, getTypesOfUser(["developer", "admin"]))}
+ disabled={
+ disabled ||
+ checkAccess(
+ loggedInUser,
+ getTypesOfUser(
+ user.type === "mastercorporate" ? ["developer", "admin"] : ["developer", "admin", "mastercorporate"],
+ ),
+ )
+ }
/>
void;
}
-export default function AssignmentCreator({isCreating, assignment, assigner, groups, users, cancelCreation}: Props) {
+export default function AssignmentCreator({isCreating, assignment, groups, users, cancelCreation}: Props) {
const [selectedModules, setSelectedModules] = useState
(assignment?.exams.map((e) => e.module) || []);
const [assignees, setAssignees] = useState(assignment?.assignees || []);
const [name, setName] = useState(
diff --git a/src/dashboards/Corporate.tsx b/src/dashboards/Corporate.tsx
index 2f0c0f5e..fa961a46 100644
--- a/src/dashboards/Corporate.tsx
+++ b/src/dashboards/Corporate.tsx
@@ -2,805 +2,636 @@
import Modal from "@/components/Modal";
import useFilterRecordsByUser from "@/hooks/useFilterRecordsByUser";
import useUsers from "@/hooks/useUsers";
-import { CorporateUser, Group, Stat, User } from "@/interfaces/user";
+import {CorporateUser, Group, MasterCorporateUser, 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, useMemo, 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 {
- futureAssignmentFilter,
- pastAssignmentFilter,
- archivedAssignmentFilter,
- activeAssignmentFilter,
-} from "@/utils/assignments";
+import {getUserCompanyName} from "@/resources/user";
+import {futureAssignmentFilter, pastAssignmentFilter, archivedAssignmentFilter, activeAssignmentFilter} from "@/utils/assignments";
import useUserBalance from "@/hooks/useUserBalance";
interface Props {
- user: CorporateUser;
+ user: CorporateUser;
+ linkedCorporate?: CorporateUser | MasterCorporateUser;
}
-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);
+export default function CorporateDashboard({user, linkedCorporate}: Props) {
+ const [page, setPage] = useState("");
+ const [selectedUser, setSelectedUser] = useState();
+ const [showModal, setShowModal] = useState(false);
+ const [selectedAssignment, setSelectedAssignment] = useState();
+ const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
- const { data: stats } = useFilterRecordsByUser();
- 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 { balance } = useUserBalance();
+ const {data: stats} = useFilterRecordsByUser();
+ 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 {balance} = useUserBalance();
- const appendUserFilters = useFilterStore((state) => state.appendUserFilter);
- const router = useRouter();
+ const appendUserFilters = useFilterStore((state) => state.appendUserFilter);
+ const router = useRouter();
- useEffect(() => {
- setShowModal(!!selectedUser && page === "");
- }, [selectedUser, page]);
+ const assignmentsGroups = useMemo(() => groups.filter((x) => x.admin === user.id || x.participants.includes(user.id)), [groups, user.id]);
- useEffect(() => {
- // in this case it fetches the master corporate account
- getUserCorporate(user.id).then(setCorporateUserToShow);
- }, [user]);
+ const assignmentsUsers = useMemo(
+ () =>
+ 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)),
+ ),
+ [groups, users, selectedUser],
+ );
- 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);
+ useEffect(() => {
+ setShowModal(!!selectedUser && page === "");
+ }, [selectedUser, page]);
- const getStatsByStudent = (user: User) =>
- stats.filter((s) => s.user === 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 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.email}
-
-
- );
+ const getStatsByStudent = (user: User) => stats.filter((s) => s.user === user.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));
+ 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.email}
+
+
+ );
- 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 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 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
+
+
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
-
-
Teachers ({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 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
+
+
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
-
-
- Groups ({groups.filter(filter).length})
-
-
+ 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})
+
- 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
- />
- ))}
-
-
- >
- );
- };
+
+ >
+ );
+ };
- 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 AssignmentsPage = () => {
+ return (
+ <>
+ {
+ setSelectedAssignment(undefined);
+ setIsCreatingAssignment(false);
+ reloadAssignments();
+ }}
+ assignment={selectedAssignment}
+ />
+ {
+ 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 (
- <>
-
-
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 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 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!
- ),
- }));
+ 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 levels: { [key in Module]: number } = {
- reading: 0,
- listening: 0,
- writing: 0,
- speaking: 0,
- level: 0,
- };
- bandScores.forEach((b) => (levels[b.module] += b.level));
+ 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!),
+ }));
- return calculateAverageLevel(levels);
- };
+ 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 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")}
- />
-
-
+ return calculateAverageLevel(levels);
+ };
-
-
-
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) => (
-
- ))}
-
-
-
- >
- );
+ const DefaultDashboard = () => (
+ <>
+ {!!linkedCorporate && (
+
+ Linked to: {linkedCorporate?.corporateInformation?.companyInformation.name || linkedCorporate.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")}
+ />
+
+
- 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),
- });
+
+
+
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) => (
+
+ ))}
+
+
+
+ >
+ );
- 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),
- });
+ 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
- }
- user={selectedUser}
- />
-
- )}
- >
-
- {page === "students" && }
- {page === "teachers" && }
- {page === "groups" && }
- {page === "assignments" && }
- {page === "studentsPerformance" && }
- {page === "" && }
- >
- );
+ 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 === "" && }
+ >
+ );
}
diff --git a/src/dashboards/MasterCorporate.tsx b/src/dashboards/MasterCorporate.tsx
index 9c2a0554..f3dd3534 100644
--- a/src/dashboards/MasterCorporate.tsx
+++ b/src/dashboards/MasterCorporate.tsx
@@ -2,1103 +2,841 @@
import Modal from "@/components/Modal";
import useFilterRecordsByUser from "@/hooks/useFilterRecordsByUser";
import useUsers from "@/hooks/useUsers";
-import {
- CorporateUser,
- Group,
- MasterCorporateUser,
- Stat,
- User,
-} from "@/interfaces/user";
+import {CorporateUser, Group, MasterCorporateUser, 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, useMemo } from "react";
+import {useEffect, useState, useMemo} from "react";
import {
- BsArrowLeft,
- BsClipboard2Data,
- BsClock,
- BsPaperclip,
- BsPersonFill,
- BsPencilSquare,
- BsPersonCheck,
- BsPeople,
- BsBank,
- BsEnvelopePaper,
- BsArrowRepeat,
- BsPlus,
- BsPersonFillGear,
- BsFilter,
- BsDatabase,
+ BsArrowLeft,
+ BsClipboard2Data,
+ BsClock,
+ BsPaperclip,
+ BsPersonFill,
+ BsPencilSquare,
+ BsPersonCheck,
+ BsPeople,
+ BsBank,
+ BsEnvelopePaper,
+ BsArrowRepeat,
+ BsPlus,
+ BsPersonFillGear,
+ BsFilter,
+ BsDatabase,
} 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 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 { createColumn, createColumnHelper } from "@tanstack/react-table";
+import {createColumn, createColumnHelper} from "@tanstack/react-table";
import List from "@/components/List";
-import { getUserCorporate } from "@/utils/groups";
-import { getCorporateUser, getUserCompanyName } from "@/resources/user";
+import {getUserCorporate} from "@/utils/groups";
+import {getCorporateUser, getUserCompanyName} from "@/resources/user";
import Checkbox from "@/components/Low/Checkbox";
-import { groupBy, uniq, uniqBy } from "lodash";
+import {groupBy, uniq, uniqBy} from "lodash";
import Select from "@/components/Low/Select";
-import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from "@/components/ui/popover";
+import {Menu, MenuButton, MenuItem, MenuItems} from "@headlessui/react";
+import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover";
import MasterStatistical from "./MasterStatistical";
-import {
- futureAssignmentFilter,
- pastAssignmentFilter,
- archivedAssignmentFilter,
- activeAssignmentFilter,
-} from "@/utils/assignments";
+import {futureAssignmentFilter, pastAssignmentFilter, archivedAssignmentFilter, activeAssignmentFilter} from "@/utils/assignments";
import useUserBalance from "@/hooks/useUserBalance";
interface Props {
- user: MasterCorporateUser;
+ user: MasterCorporateUser;
}
type StudentPerformanceItem = User & {
- corporate?: CorporateUser;
- group?: Group;
+ corporate?: CorporateUser;
+ group?: Group;
};
-const StudentPerformanceList = ({
- items,
- stats,
- users,
- groups,
-}: {
- items: StudentPerformanceItem[];
- stats: Stat[];
- users: User[];
- groups: Group[];
-}) => {
- const [isShowingAmount, setIsShowingAmount] = useState(false);
- const [availableCorporates] = useState(
- uniqBy(
- items.map((x) => x.corporate),
- "id"
- )
- );
- const [availableGroups] = useState(
- uniqBy(
- items.map((x) => x.group),
- "id"
- )
- );
+const StudentPerformanceList = ({items, stats, users, groups}: {items: StudentPerformanceItem[]; stats: Stat[]; users: User[]; groups: Group[]}) => {
+ const [isShowingAmount, setIsShowingAmount] = useState(false);
+ const [availableCorporates] = useState(
+ uniqBy(
+ items.map((x) => x.corporate),
+ "id",
+ ),
+ );
+ const [availableGroups] = useState(
+ uniqBy(
+ items.map((x) => x.group),
+ "id",
+ ),
+ );
- const [selectedCorporate, setSelectedCorporate] = useState<
- CorporateUser | null | undefined
- >(null);
- const [selectedGroup, setSelectedGroup] = useState(
- null
- );
+ const [selectedCorporate, setSelectedCorporate] = useState(null);
+ const [selectedGroup, setSelectedGroup] = useState(null);
- 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()?.name || "N/A",
- }),
- columnHelper.accessor("corporate", {
- header: "Corporate",
- cell: (info) =>
- !!info.getValue()
- ? getUserCompanyName(info.getValue() as User, users, groups)
- : "N/A",
- }),
- columnHelper.accessor("levels.reading", {
- header: "Reading",
- cell: (info) =>
- !isShowingAmount
- ? calculateBandScore(
- stats
- .filter(
- (x) =>
- x.module === "reading" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.correct, 0),
- stats
- .filter(
- (x) =>
- x.module === "reading" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.total, 0),
- "level",
- info.row.original.focus || "academic"
- ) || 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
- ? calculateBandScore(
- stats
- .filter(
- (x) =>
- x.module === "listening" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.correct, 0),
- stats
- .filter(
- (x) =>
- x.module === "listening" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.total, 0),
- "level",
- info.row.original.focus || "academic"
- ) || 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
- ? calculateBandScore(
- stats
- .filter(
- (x) =>
- x.module === "writing" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.correct, 0),
- stats
- .filter(
- (x) =>
- x.module === "writing" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.total, 0),
- "level",
- info.row.original.focus || "academic"
- ) || 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
- ? calculateBandScore(
- stats
- .filter(
- (x) =>
- x.module === "speaking" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.correct, 0),
- stats
- .filter(
- (x) =>
- x.module === "speaking" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.total, 0),
- "level",
- info.row.original.focus || "academic"
- ) || 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
- ? calculateBandScore(
- stats
- .filter(
- (x) => x.module === "level" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.correct, 0),
- stats
- .filter(
- (x) => x.module === "level" && x.user === info.row.original.id
- )
- .reduce((acc, curr) => acc + curr.score.total, 0),
- "level",
- info.row.original.focus || "academic"
- ) || 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()?.name || "N/A",
+ }),
+ columnHelper.accessor("corporate", {
+ header: "Corporate",
+ cell: (info) => (!!info.getValue() ? getUserCompanyName(info.getValue() as User, users, groups) : "N/A"),
+ }),
+ columnHelper.accessor("levels.reading", {
+ header: "Reading",
+ cell: (info) =>
+ !isShowingAmount
+ ? calculateBandScore(
+ stats
+ .filter((x) => x.module === "reading" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.correct, 0),
+ stats
+ .filter((x) => x.module === "reading" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.total, 0),
+ "level",
+ info.row.original.focus || "academic",
+ ) || 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
+ ? calculateBandScore(
+ stats
+ .filter((x) => x.module === "listening" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.correct, 0),
+ stats
+ .filter((x) => x.module === "listening" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.total, 0),
+ "level",
+ info.row.original.focus || "academic",
+ ) || 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
+ ? calculateBandScore(
+ stats
+ .filter((x) => x.module === "writing" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.correct, 0),
+ stats
+ .filter((x) => x.module === "writing" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.total, 0),
+ "level",
+ info.row.original.focus || "academic",
+ ) || 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
+ ? calculateBandScore(
+ stats
+ .filter((x) => x.module === "speaking" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.correct, 0),
+ stats
+ .filter((x) => x.module === "speaking" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.total, 0),
+ "level",
+ info.row.original.focus || "academic",
+ ) || 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
+ ? calculateBandScore(
+ stats
+ .filter((x) => x.module === "level" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.correct, 0),
+ stats
+ .filter((x) => x.module === "level" && x.user === info.row.original.id)
+ .reduce((acc, curr) => acc + curr.score.total, 0),
+ "level",
+ info.row.original.focus || "academic",
+ ) || 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 filterUsers = (data: StudentPerformanceItem[]) => {
- console.log(data, selectedCorporate);
- const filterByCorporate = (item: StudentPerformanceItem) =>
- item.corporate?.id === selectedCorporate?.id;
- const filterByGroup = (item: StudentPerformanceItem) =>
- item.group?.id === selectedGroup?.id;
+ const filterUsers = (data: StudentPerformanceItem[]) => {
+ console.log(data, selectedCorporate);
+ const filterByCorporate = (item: StudentPerformanceItem) => item.corporate?.id === selectedCorporate?.id;
+ const filterByGroup = (item: StudentPerformanceItem) => item.group?.id === selectedGroup?.id;
- const filters: ((item: StudentPerformanceItem) => boolean)[] = [];
- if (selectedCorporate !== null) filters.push(filterByCorporate);
- if (selectedGroup !== null) filters.push(filterByGroup);
+ const filters: ((item: StudentPerformanceItem) => boolean)[] = [];
+ if (selectedCorporate !== null) filters.push(filterByCorporate);
+ if (selectedGroup !== null) filters.push(filterByGroup);
- return filters.reduce((d, f) => d.filter(f), data);
- };
+ return filters.reduce((d, f) => d.filter(f), data);
+ };
- return (
-
-
-
- Show Utilization
-
-
-
-
-
-
-
-
-
- Filters
-
-
-
-
-
- data={filterUsers(
- 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
+
+
+
+
+
+
+
+
+
+ Filters
+ ({
+ value: x?.id || "N/A",
+ label: x?.corporateInformation?.companyInformation?.name || x?.name || "N/A",
+ }))}
+ isClearable
+ value={
+ selectedCorporate === null
+ ? null
+ : {
+ value: selectedCorporate?.id || "N/A",
+ label:
+ selectedCorporate?.corporateInformation?.companyInformation?.name ||
+ selectedCorporate?.name ||
+ "N/A",
+ }
+ }
+ placeholder="Select a Corporate..."
+ onChange={(value) =>
+ !value
+ ? setSelectedCorporate(null)
+ : setSelectedCorporate(
+ value.value === "N/A" ? undefined : availableCorporates.find((x) => x?.id === value.value),
+ )
+ }
+ />
+ ({
+ value: x?.id || "N/A",
+ label: x?.name || "N/A",
+ }))}
+ isClearable
+ value={
+ selectedGroup === null
+ ? null
+ : {
+ value: selectedGroup?.id || "N/A",
+ label: selectedGroup?.name || "N/A",
+ }
+ }
+ placeholder="Select a Group..."
+ onChange={(value) =>
+ !value
+ ? setSelectedGroup(null)
+ : setSelectedGroup(value.value === "N/A" ? undefined : availableGroups.find((x) => x?.id === value.value))
+ }
+ />
+
+
+
+
+
+ data={filterUsers(
+ 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 MasterCorporateDashboard({ user }: Props) {
- const [page, setPage] = useState("");
- const [selectedUser, setSelectedUser] = useState();
- const [showModal, setShowModal] = useState(false);
- const [selectedAssignment, setSelectedAssignment] = useState();
- const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
- const [corporateAssignments, setCorporateAssignments] = useState<
- (Assignment & { corporate?: CorporateUser })[]
- >([]);
+export default function MasterCorporateDashboard({user}: Props) {
+ const [page, setPage] = useState("");
+ const [selectedUser, setSelectedUser] = useState();
+ const [showModal, setShowModal] = useState(false);
+ const [selectedAssignment, setSelectedAssignment] = useState();
+ const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
+ const [corporateAssignments, setCorporateAssignments] = useState<(Assignment & {corporate?: CorporateUser})[]>([]);
- const { data: stats } = useFilterRecordsByUser();
- const { users, reload } = useUsers();
- const { codes } = useCodes(user.id);
- const { groups } = useGroups({ admin: user.id, userType: user.type });
- const { balance } = useUserBalance();
+ const {data: stats} = useFilterRecordsByUser();
+ const {users, reload} = useUsers();
+ const {groups} = useGroups({admin: user.id, userType: user.type});
+ const {balance} = useUserBalance();
- const masterCorporateUserGroups = useMemo(() => [
- ...new Set(
- groups.filter((u) => u.admin === user.id).flatMap((g) => g.participants)
- ),
- ], [groups, user.id]);
+ const masterCorporateUserGroups = useMemo(
+ () => [...new Set(groups.filter((u) => u.admin === user.id).flatMap((g) => g.participants))],
+ [groups, user.id],
+ );
- const corporateUserGroups = [
- ...new Set(groups.flatMap((g) => g.participants)),
- ];
+ const corporateUserGroups = useMemo(() => [...new Set(groups.flatMap((g) => g.participants))], [groups]);
- const {
- assignments,
- isLoading: isAssignmentsLoading,
- reload: reloadAssignments,
- } = useAssignments({ corporate: user.id });
+ const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({corporate: user.id});
- const appendUserFilters = useFilterStore((state) => state.appendUserFilter);
- const router = useRouter();
+ const assignmentsGroups = useMemo(() => groups.filter((x) => x.admin === user.id || x.participants.includes(user.id)), [groups, user.id]);
+ const assignmentsUsers = useMemo(
+ () =>
+ 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)),
+ ),
+ [groups, users, selectedUser],
+ );
- useEffect(() => {
- setShowModal(!!selectedUser && page === "");
- }, [selectedUser, page]);
+ const appendUserFilters = useFilterStore((state) => state.appendUserFilter);
+ const router = useRouter();
- useEffect(() => {
- setCorporateAssignments(
- assignments.filter(activeAssignmentFilter).map((a) => ({
- ...a,
- corporate: !!users.find((x) => x.id === a.assigner)
- ? getCorporateUser(
- users.find((x) => x.id === a.assigner)!,
- users,
- groups
- )
- : undefined,
- }))
- );
- }, [assignments, groups, users]);
+ useEffect(() => {
+ setShowModal(!!selectedUser && page === "");
+ }, [selectedUser, page]);
- const studentFilter = (user: User) =>
- user.type === "student" && corporateUserGroups.includes(user.id);
- const teacherFilter = (user: User) =>
- user.type === "teacher" && corporateUserGroups.includes(user.id);
- const getStatsByStudent = (user: User) =>
- stats.filter((s) => s.user === user.id);
+ useEffect(() => {
+ setCorporateAssignments(
+ assignments.filter(activeAssignmentFilter).map((a) => ({
+ ...a,
+ corporate: !!users.find((x) => x.id === a.assigner)
+ ? getCorporateUser(users.find((x) => x.id === a.assigner)!, users, groups)
+ : undefined,
+ })),
+ );
+ }, [assignments, groups, users]);
- 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.email}
-
-
- );
+ const studentFilter = (user: User) => user.type === "student" && corporateUserGroups.includes(user.id);
+ const teacherFilter = (user: User) => user.type === "teacher" && corporateUserGroups.includes(user.id);
+ const getStatsByStudent = (user: User) => stats.filter((s) => s.user === user.id);
- const StudentsList = () => {
- const filter = (x: User) =>
- x.type === "student" &&
- (!!selectedUser
- ? corporateUserGroups.includes(x.id) || false
- : corporateUserGroups.includes(x.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.email}
+
+
+ );
- 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 StudentsList = () => {
+ const filter = (x: User) =>
+ x.type === "student" && (!!selectedUser ? corporateUserGroups.includes(x.id) || false : corporateUserGroups.includes(x.id));
- const TeachersList = () => {
- const filter = (x: User) =>
- x.type === "teacher" &&
- (!!selectedUser
- ? corporateUserGroups.includes(x.id) || false
- : corporateUserGroups.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
-
-
Teachers ({total})
-
- )}
- />
- );
- };
+ const TeachersList = () => {
+ const filter = (x: User) =>
+ x.type === "teacher" && (!!selectedUser ? corporateUserGroups.includes(x.id) || false : corporateUserGroups.includes(x.id));
- const corporateUserFilter = (x: User) =>
- x.type === "corporate" &&
- (!!selectedUser
- ? masterCorporateUserGroups.includes(x.id) || false
- : masterCorporateUserGroups.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})
+
+ )}
+ />
+ );
+ };
- const CorporateList = () => {
- 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
-
-
Corporates ({total})
-
- )}
- />
- );
- };
+ const corporateUserFilter = (x: User) =>
+ x.type === "corporate" && (!!selectedUser ? masterCorporateUserGroups.includes(x.id) || false : masterCorporateUserGroups.includes(x.id));
- const GroupsList = () => {
- 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.length})
-
+ const CorporateList = () => {
+ 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
+
+
Corporates ({total})
+
+ )}
+ />
+ );
+ };
-
- >
- );
- };
+ const GroupsList = () => {
+ 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.length})
+
- 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)),
- corporate: getCorporateUser(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
-
-
-
-
- >
- );
- };
+ 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)),
+ corporate: getCorporateUser(u, users, groups),
+ }));
- 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 Status
-
-
- Total:{" "}
- {assignments
- .filter(activeAssignmentFilter)
- .reduce((acc, curr) => acc + curr.results.length, 0)}
- /
- {assignments
- .filter(activeAssignmentFilter)
- .reduce((acc, curr) => curr.exams.length + acc, 0)}
-
- {Object.keys(
- groupBy(corporateAssignments, (x) => x.corporate?.id)
- ).map((x) => (
-
-
- {getUserCompanyName(
- users.find((u) => u.id === x)!,
- users,
- groups
- )}
- :{" "}
-
-
- {groupBy(corporateAssignments, (x) => x.corporate?.id)[
- x
- ].reduce((acc, curr) => curr.results.length + acc, 0)}
- /
- {groupBy(corporateAssignments, (x) => x.corporate?.id)[
- x
- ].reduce((acc, curr) => curr.exams.length + acc, 0)}
-
-
- ))}
-
-
-
-
- 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 (
+ <>
+
+
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 masterCorporateUsers = useMemo(
- () =>
- masterCorporateUserGroups.reduce((accm: CorporateUser[], id) => {
- const user = users.find((u) => u.id === id) as CorporateUser;
- if (user) return [...accm, user];
- return accm;
- }, []),
- [masterCorporateUserGroups, users]
- );
+ const AssignmentsPage = () => {
+ return (
+ <>
+ {
+ setSelectedAssignment(undefined);
+ setIsCreatingAssignment(false);
+ reloadAssignments();
+ }}
+ assignment={selectedAssignment}
+ />
+ {
+ 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 Status
+
+
+ Total: {assignments.filter(activeAssignmentFilter).reduce((acc, curr) => acc + curr.results.length, 0)}/
+ {assignments.filter(activeAssignmentFilter).reduce((acc, curr) => curr.exams.length + acc, 0)}
+
+ {Object.keys(groupBy(corporateAssignments, (x) => x.corporate?.id)).map((x) => (
+
+ {getUserCompanyName(users.find((u) => u.id === x)!, users, groups)}:
+
+ {groupBy(corporateAssignments, (x) => x.corporate?.id)[x].reduce((acc, curr) => curr.results.length + acc, 0)}/
+ {groupBy(corporateAssignments, (x) => x.corporate?.id)[x].reduce((acc, curr) => curr.exams.length + acc, 0)}
+
+
+ ))}
+
+
+
+ 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
+ />
+ ))}
+
+
+ >
+ );
+ };
- const MasterStatisticalPage = () => {
- 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
-
-
Master Statistical
-
-
- >
- );
- };
+ const masterCorporateUsers = useMemo(
+ () =>
+ masterCorporateUserGroups.reduce((accm: CorporateUser[], id) => {
+ const user = users.find((u) => u.id === id) as CorporateUser;
+ if (user) return [...accm, user];
+ return accm;
+ }, []),
+ [masterCorporateUserGroups, users],
+ );
- const DefaultDashboard = () => (
- <>
-
- 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("corporate")}
- />
- setPage("studentsPerformance")}
- />
- setPage("statistical")}
- />
-
-
+ const MasterStatisticalPage = () => {
+ 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
+
+
Master Statistical
+
+
+ >
+ );
+ };
-
-
-
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) => (
-
- ))}
-
-
-
- >
- );
+ const DefaultDashboard = () => (
+ <>
+
+ 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("corporate")}
+ />
+ setPage("studentsPerformance")}
+ />
+ setPage("statistical")}
+ />
+
+
- 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),
- });
+
+
+
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) => (
+
+ ))}
+
+
+
+ >
+ );
- 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),
- });
+ 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
- }
- user={selectedUser}
- />
-
- )}
- >
-
- {page === "students" && }
- {page === "teachers" && }
- {page === "groups" && }
- {page === "corporate" && }
- {page === "assignments" && }
- {page === "studentsPerformance" && }
- {page === "statistical" && }
- {page === "" && }
- >
- );
+ 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 === "corporate" && }
+ {page === "assignments" && }
+ {page === "studentsPerformance" && }
+ {page === "statistical" && }
+ {page === "" && }
+ >
+ );
}
diff --git a/src/dashboards/Student.tsx b/src/dashboards/Student.tsx
index 5fd2a862..805a2d3b 100644
--- a/src/dashboards/Student.tsx
+++ b/src/dashboards/Student.tsx
@@ -9,7 +9,7 @@ import useFilterRecordsByUser from "@/hooks/useFilterRecordsByUser";
import useUsers from "@/hooks/useUsers";
import {Invite} from "@/interfaces/invite";
import {Assignment} from "@/interfaces/results";
-import {CorporateUser, Stat, User} from "@/interfaces/user";
+import {CorporateUser, MasterCorporateUser, Stat, User} from "@/interfaces/user";
import useExamStore from "@/stores/examStore";
import {getExamById} from "@/utils/exams";
import {getUserCorporate} from "@/utils/groups";
@@ -30,11 +30,10 @@ import {toast} from "react-toastify";
interface Props {
user: User;
+ linkedCorporate?: CorporateUser | MasterCorporateUser;
}
-export default function StudentDashboard({user}: Props) {
- const [corporateUserToShow, setCorporateUserToShow] = useState();
-
+export default function StudentDashboard({user, linkedCorporate}: Props) {
const {users} = useUsers();
const {gradingSystem} = useGradingSystem();
const {data: stats} = useFilterRecordsByUser(user.id, !user?.id);
@@ -49,10 +48,6 @@ export default function StudentDashboard({user}: Props) {
const setSelectedModules = useExamStore((state) => state.setSelectedModules);
const setAssignment = useExamStore((state) => state.setAssignment);
- useEffect(() => {
- getUserCorporate(user.id).then(setCorporateUserToShow);
- }, [user]);
-
const startAssignment = (assignment: Assignment) => {
const examPromises = assignment.exams.filter((e) => e.assignee === user.id).map((e) => getExamById(e.module, e.id));
@@ -76,9 +71,9 @@ export default function StudentDashboard({user}: Props) {
return (
<>
- {corporateUserToShow && (
+ {linkedCorporate && (
- Linked to: {corporateUserToShow?.corporateInformation?.companyInformation.name || corporateUserToShow.name}
+ Linked to: {linkedCorporate?.corporateInformation?.companyInformation.name || linkedCorporate.name}
)}
();
- const [showModal, setShowModal] = useState(false);
- const [selectedAssignment, setSelectedAssignment] = useState();
- const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
- const [corporateUserToShow, setCorporateUserToShow] =
- useState();
+export default function TeacherDashboard({user, linkedCorporate}: Props) {
+ const [page, setPage] = useState("");
+ const [selectedUser, setSelectedUser] = useState();
+ const [showModal, setShowModal] = useState(false);
+ const [selectedAssignment, setSelectedAssignment] = useState();
+ const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
- const { data: stats } = useFilterRecordsByUser();
- const { users, reload } = useUsers();
- const { groups } = useGroups({ adminAdmins: user.id });
- const { permissions } = usePermissions(user.id);
- const {
- assignments,
- isLoading: isAssignmentsLoading,
- reload: reloadAssignments,
- } = useAssignments({ assigner: user.id });
+ const {data: stats} = useFilterRecordsByUser();
+ const {users, reload} = useUsers();
+ const {groups} = useGroups({adminAdmins: user.id});
+ const {permissions} = usePermissions(user.id);
+ const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({assigner: user.id});
- useEffect(() => {
- setShowModal(!!selectedUser && page === "");
- }, [selectedUser, page]);
+ const assignmentsGroups = useMemo(() => groups.filter((x) => x.admin === user.id || x.participants.includes(user.id)), [groups, user.id]);
- useEffect(() => {
- getUserCorporate(user.id).then(setCorporateUserToShow);
- }, [user]);
+ const assignmentsUsers = useMemo(
+ () =>
+ users.filter(
+ (x) =>
+ x.type === "student" &&
+ (!!selectedUser
+ ? groups
+ .filter((g) => g.admin === selectedUser.id)
+ .flatMap((g) => g.participants)
+ .includes(x.id)
+ : groups.flatMap((g) => g.participants).includes(x.id)),
+ ),
+ [groups, users, selectedUser],
+ );
- const studentFilter = (user: User) =>
- user.type === "student" &&
- groups.flatMap((g) => g.participants).includes(user.id);
+ useEffect(() => {
+ setShowModal(!!selectedUser && page === "");
+ }, [selectedUser, page]);
- const getStatsByStudent = (user: User) =>
- stats.filter((s) => s.user === user.id);
+ const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(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.email}
-
-
- );
+ const getStatsByStudent = (user: User) => stats.filter((s) => s.user === user.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));
+ 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.email}
+
+
+ );
- 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 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 GroupsList = () => {
- const filter = (x: Group) => x.admin === 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
+
+
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
-
-
- Groups ({groups.filter(filter).length})
-
-
+ const GroupsList = () => {
+ const filter = (x: Group) => x.admin === 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})
+
- 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 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!),
+ }));
- return calculateAverageLevel(levels);
- };
+ 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 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)
- : 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 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"
- />
-
- groups.flatMap((g) => g.participants).includes(s.user)
- ).length
- }
- color="purple"
- />
-
- groups.flatMap((g) => g.participants).includes(s.user)
- )
- ).toFixed(1)}
- color="purple"
- />
- {checkAccess(
- user,
- ["teacher", "developer"],
- permissions,
- "viewGroup"
- ) && (
- x.admin === user.id).length}
- color="purple"
- onClick={() => setPage("groups")}
- />
- )}
- setPage("assignments")}
- className="bg-white rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300"
- >
-
-
- Assignments
-
- {assignments.filter((a) => !a.archived).length}
-
-
-
-
+ const AssignmentsPage = () => {
+ return (
+ <>
+ {
+ setSelectedAssignment(undefined);
+ setIsCreatingAssignment(false);
+ reloadAssignments();
+ }}
+ assignment={selectedAssignment}
+ />
+ {
+ 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
+ />
+ ))}
+
+
+ >
+ );
+ };
-
-
-
Latest students
-
- {users
- .filter(studentFilter)
- .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) => (
-
- ))}
-
-
-
- >
- );
+ const DefaultDashboard = () => (
+ <>
+ {linkedCorporate && (
+
+ Linked to: {linkedCorporate?.corporateInformation?.companyInformation.name || linkedCorporate.name}
+
+ )}
+
+ setPage("students")}
+ Icon={BsPersonFill}
+ label="Students"
+ value={users.filter(studentFilter).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"
+ />
+ {checkAccess(user, ["teacher", "developer"], permissions, "viewGroup") && (
+ x.admin === user.id).length}
+ color="purple"
+ onClick={() => setPage("groups")}
+ />
+ )}
+ setPage("assignments")}
+ className="bg-white rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300">
+
+
+ Assignments
+ {assignments.filter((a) => !a.archived).length}
+
+
+
- return (
- <>
- setSelectedUser(undefined)}>
- <>
- {selectedUser && (
-
- {
- setSelectedUser(undefined);
- if (shouldReload) reload();
- }}
- onViewStudents={
- selectedUser.type === "corporate" ||
- selectedUser.type === "teacher"
- ? () => setPage("students")
- : undefined
- }
- onViewTeachers={
- selectedUser.type === "corporate"
- ? () => setPage("teachers")
- : undefined
- }
- user={selectedUser}
- />
-
- )}
- >
-
- {page === "students" && }
- {page === "groups" && }
- {page === "assignments" && }
- {page === "" && }
- >
- );
+
+
+
Latest students
+
+ {users
+ .filter(studentFilter)
+ .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" ? () => setPage("students") : undefined
+ }
+ onViewTeachers={selectedUser.type === "corporate" ? () => setPage("teachers") : undefined}
+ user={selectedUser}
+ />
+
+ )}
+ >
+
+ {page === "students" && }
+ {page === "groups" && }
+ {page === "assignments" && }
+ {page === "" && }
+ >
+ );
}
diff --git a/src/pages/(admin)/BatchCodeGenerator.tsx b/src/pages/(admin)/BatchCodeGenerator.tsx
index ac6764b4..f10dc2c1 100644
--- a/src/pages/(admin)/BatchCodeGenerator.tsx
+++ b/src/pages/(admin)/BatchCodeGenerator.tsx
@@ -55,7 +55,14 @@ const USER_TYPE_PERMISSIONS: {
},
};
-export default function BatchCodeGenerator({user, onFinish}: {user: User; onFinish: () => void}) {
+interface Props {
+ user: User;
+ users: User[];
+ permissions: PermissionType[];
+ onFinish: () => void;
+}
+
+export default function BatchCodeGenerator({user, users, permissions, onFinish}: Props) {
const [infos, setInfos] = useState<{email: string; name: string; passport_id: string}[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [expiryDate, setExpiryDate] = useState(
@@ -65,9 +72,6 @@ export default function BatchCodeGenerator({user, onFinish}: {user: User; onFini
const [type, setType] = useState("student");
const [showHelp, setShowHelp] = useState(false);
- const {users} = useUsers();
- const {permissions} = usePermissions(user?.id || "");
-
const {openFilePicker, filesContent, clear} = useFilePicker({
accept: ".xlsx",
multiple: false,
diff --git a/src/pages/(admin)/BatchCreateUser.tsx b/src/pages/(admin)/BatchCreateUser.tsx
index bf08962a..03417eba 100644
--- a/src/pages/(admin)/BatchCreateUser.tsx
+++ b/src/pages/(admin)/BatchCreateUser.tsx
@@ -61,7 +61,14 @@ const USER_TYPE_PERMISSIONS: {
},
};
-export default function BatchCreateUser({user, onFinish}: {user: User; onFinish: () => void}) {
+interface Props {
+ user: User;
+ users: User[];
+ permissions: PermissionType[];
+ onFinish: () => void;
+}
+
+export default function BatchCreateUser({user, users, permissions, onFinish}: Props) {
const [infos, setInfos] = useState<
{
email: string;
@@ -83,9 +90,6 @@ export default function BatchCreateUser({user, onFinish}: {user: User; onFinish:
const [type, setType] = useState("student");
const [showHelp, setShowHelp] = useState(false);
- const {users} = useUsers();
- const {permissions} = usePermissions(user?.id || "");
-
const {openFilePicker, filesContent, clear} = useFilePicker({
accept: ".xlsx",
multiple: false,
diff --git a/src/pages/(admin)/CodeGenerator.tsx b/src/pages/(admin)/CodeGenerator.tsx
index cbd1b5fb..c1799783 100644
--- a/src/pages/(admin)/CodeGenerator.tsx
+++ b/src/pages/(admin)/CodeGenerator.tsx
@@ -48,14 +48,19 @@ const USER_TYPE_PERMISSIONS: {
},
};
-export default function CodeGenerator({user, onFinish}: {user: User; onFinish: () => void}) {
+interface Props {
+ user: User;
+ permissions: PermissionType[];
+ onFinish: () => void;
+}
+
+export default function CodeGenerator({user, permissions, onFinish}: Props) {
const [generatedCode, setGeneratedCode] = useState();
const [expiryDate, setExpiryDate] = useState(
user?.subscriptionExpirationDate ? moment(user.subscriptionExpirationDate).toDate() : null,
);
const [isExpiryDateEnabled, setIsExpiryDateEnabled] = useState(true);
const [type, setType] = useState("student");
- const {permissions} = usePermissions(user?.id || "");
useEffect(() => {
if (!isExpiryDateEnabled) setExpiryDate(null);
diff --git a/src/pages/(admin)/Lists/GroupList.tsx b/src/pages/(admin)/Lists/GroupList.tsx
index 54948f7a..3f7c1a6a 100644
--- a/src/pages/(admin)/Lists/GroupList.tsx
+++ b/src/pages/(admin)/Lists/GroupList.tsx
@@ -7,7 +7,7 @@ import {CorporateUser, Group, User} from "@/interfaces/user";
import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table";
import axios from "axios";
import {capitalize, uniq} from "lodash";
-import {useEffect, useState} from "react";
+import {useEffect, useMemo, useState} from "react";
import {BsPencil, BsQuestionCircleFill, BsTrash} from "react-icons/bs";
import Select from "react-select";
import {toast} from "react-toastify";
@@ -65,6 +65,14 @@ const CreatePanel = ({user, users, group, onClose}: CreateDialogProps) => {
readAs: "ArrayBuffer",
});
+ const availableUsers = useMemo(() => {
+ if (user.type === "teacher") return users.filter((x) => ["student"].includes(x.type));
+ if (user.type === "corporate") return users.filter((x) => ["teacher", "student"].includes(x.type));
+ if (user.type === "mastercorporate") return users.filter((x) => ["corporate", "teacher", "student"].includes(x.type));
+
+ return users;
+ }, [user, users]);
+
useEffect(() => {
if (filesContent.length > 0) {
setIsLoading(true);
@@ -155,15 +163,7 @@ const CreatePanel = ({user, users, group, onClose}: CreateDialogProps) => {
value: x,
label: `${users.find((y) => y.id === x)?.email} - ${users.find((y) => y.id === x)?.name}`,
}))}
- options={users
- .filter((x) =>
- user.type === "teacher"
- ? x.type === "student"
- : user.type === "corporate"
- ? x.type === "student" || x.type === "teacher"
- : x.type === "student" || x.type === "teacher" || x.type === "corporate",
- )
- .map((x) => ({value: x.id, label: `${x.email} - ${x.name}`}))}
+ options={availableUsers.map((x) => ({value: x.id, label: `${x.email} - ${x.name}`}))}
onChange={(value) => setParticipants(value.map((x) => x.value))}
isMulti
isSearchable
diff --git a/src/pages/(admin)/Lists/index.tsx b/src/pages/(admin)/Lists/index.tsx
index e9626763..477e40e0 100644
--- a/src/pages/(admin)/Lists/index.tsx
+++ b/src/pages/(admin)/Lists/index.tsx
@@ -9,10 +9,15 @@ import PackageList from "./PackageList";
import UserList from "./UserList";
import {checkAccess} from "@/utils/permissions";
import usePermissions from "@/hooks/usePermissions";
+import {PermissionType} from "@/interfaces/permissions";
-export default function Lists({user}: {user: User}) {
- const {permissions} = usePermissions(user?.id || "");
+interface Props {
+ user: User;
+ users: User[];
+ permissions: PermissionType[];
+}
+export default function Lists({user, users, permissions}: Props) {
return (
diff --git a/src/pages/(admin)/UserCreator.tsx b/src/pages/(admin)/UserCreator.tsx
index a5a61db4..38dd4f3c 100644
--- a/src/pages/(admin)/UserCreator.tsx
+++ b/src/pages/(admin)/UserCreator.tsx
@@ -54,7 +54,14 @@ const USER_TYPE_PERMISSIONS: {
},
};
-export default function UserCreator({user, onFinish}: {user: User; onFinish: () => void}) {
+interface Props {
+ user: User;
+ users: User[];
+ permissions: PermissionType[];
+ onFinish: () => void;
+}
+
+export default function UserCreator({user, users, permissions, onFinish}: Props) {
const [name, setName] = useState();
const [email, setEmail] = useState();
const [phone, setPhone] = useState();
@@ -72,10 +79,9 @@ export default function UserCreator({user, onFinish}: {user: User; onFinish: ()
const [isExpiryDateEnabled, setIsExpiryDateEnabled] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [type, setType] = useState("student");
+ const [position, setPosition] = useState();
- const {permissions} = usePermissions(user?.id || "");
const {groups} = useGroups({admin: ["developer", "admin"].includes(user?.type) ? undefined : user?.id, userType: user?.type});
- const {users} = useUsers();
useEffect(() => {
if (!isExpiryDateEnabled) setExpiryDate(null);
@@ -104,6 +110,7 @@ export default function UserCreator({user, onFinish}: {user: User; onFinish: ()
email,
password,
groupID: group,
+ corporate: selectedCorporate || user.id,
type,
studentID: type === "student" ? studentID : undefined,
expiryDate,
@@ -111,6 +118,7 @@ export default function UserCreator({user, onFinish}: {user: User; onFinish: ()
passport_id: type === "student" ? passportID : undefined,
phone,
country,
+ position,
},
};
@@ -131,6 +139,7 @@ export default function UserCreator({user, onFinish}: {user: User; onFinish: ()
setExpiryDate(user?.subscriptionExpirationDate ? moment(user?.subscriptionExpirationDate).toDate() : null);
setIsExpiryDateEnabled(true);
setType("student");
+ setPosition(undefined);
})
.catch(() => toast.error("Something went wrong! Please try again later!"))
.finally(() => setIsLoading(false));
@@ -186,10 +195,16 @@ export default function UserCreator({user, onFinish}: {user: User; onFinish: ()