diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index d69feebf..6119e11f 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -13,6 +13,7 @@ import { BsCurrencyDollar, BsClipboardData, BsFileLock, + BsPeople, } from "react-icons/bs"; import {CiDumbbell} from "react-icons/ci"; import {RiLogoutBoxFill} from "react-icons/ri"; @@ -109,6 +110,9 @@ export default function Sidebar({path, navDisabled = false, focusMode = false, u {checkAccess(user, getTypesOfUser(["agent"]), permissions, "viewStats") && ( )} + {checkAccess(user, ["developer", "admin", "teacher", "student"], permissions) && ( + + )} {checkAccess(user, getTypesOfUser(["agent"]), permissions, "viewRecords") && ( )} diff --git a/src/dashboards/Admin.tsx b/src/dashboards/Admin.tsx index 85939403..65f15ed1 100644 --- a/src/dashboards/Admin.tsx +++ b/src/dashboards/Admin.tsx @@ -2,714 +2,613 @@ import Modal from "@/components/Modal"; import useStats from "@/hooks/useStats"; import useUsers from "@/hooks/useUsers"; -import { User } from "@/interfaces/user"; +import {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, - BsBriefcaseFill, - BsGlobeCentralSouthAsia, - BsPerson, - BsPersonFill, - BsPencilSquare, - BsBank, - BsCurrencyDollar, - BsLayoutWtf, - BsLayoutSidebar, + BsArrowLeft, + BsBriefcaseFill, + BsGlobeCentralSouthAsia, + BsPerson, + BsPersonFill, + BsPencilSquare, + BsBank, + BsCurrencyDollar, + BsLayoutWtf, + BsLayoutSidebar, } from "react-icons/bs"; import UserCard from "@/components/UserCard"; import useGroups from "@/hooks/useGroups"; import IconCard from "./IconCard"; import useFilterStore from "@/stores/listFilterStore"; -import { useRouter } from "next/router"; +import {useRouter} from "next/router"; import usePaymentStatusUsers from "@/hooks/usePaymentStatusUsers"; import CorporateStudentsLevels from "./CorporateStudentsLevels"; interface Props { - user: User; + user: User; } -export default function AdminDashboard({ user }: Props) { - const [page, setPage] = useState(""); - const [selectedUser, setSelectedUser] = useState(); - const [showModal, setShowModal] = useState(false); +export default function AdminDashboard({user}: Props) { + const [page, setPage] = useState(""); + const [selectedUser, setSelectedUser] = useState(); + const [showModal, setShowModal] = useState(false); - const { stats } = useStats(user.id); - const { users, reload } = useUsers(); - const { groups } = useGroups(); - const { pending, done } = usePaymentStatusUsers(); + const {stats} = useStats(user.id); + const {users, reload} = useUsers(); + const {groups} = useGroups({}); + const {pending, done} = usePaymentStatusUsers(); - 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]); - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(reload, [page]); + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(reload, [page]); - const inactiveCountryManagerFilter = (x: User) => - x.type === "agent" && - (x.status === "disabled" || moment().isAfter(x.subscriptionExpirationDate)); + const inactiveCountryManagerFilter = (x: User) => + x.type === "agent" && (x.status === "disabled" || moment().isAfter(x.subscriptionExpirationDate)); - 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.type === "corporate" - ? displayUser.corporateInformation?.companyInformation?.name || - 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.type === "corporate" + ? displayUser.corporateInformation?.companyInformation?.name || displayUser.name + : displayUser.name} + + {displayUser.email} + + + ); - const StudentsList = () => { - const filter = (x: User) => - x.type === "student" && - (!!selectedUser - ? groups - .filter( - (g) => - g.admin === selectedUser.id || - g.participants.includes(selectedUser.id) - ) - .flatMap((g) => g.participants) - .includes(x.id) - : true); + const StudentsList = () => { + const filter = (x: User) => + x.type === "student" && + (!!selectedUser + ? groups + .filter((g) => g.admin === selectedUser.id || g.participants.includes(selectedUser.id)) + .flatMap((g) => g.participants) + .includes(x.id) + : true); - 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 || - g.participants.includes(selectedUser.id) - ) - .flatMap((g) => g.participants) - .includes(x.id) || false - : true); + const TeachersList = () => { + const filter = (x: User) => + x.type === "teacher" && + (!!selectedUser + ? groups + .filter((g) => g.admin === selectedUser.id || g.participants.includes(selectedUser.id)) + .flatMap((g) => g.participants) + .includes(x.id) || false + : true); - 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 AgentsList = () => { - const filter = (x: User) => x.type === "agent"; + const AgentsList = () => { + const filter = (x: User) => x.type === "agent"; - 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 - - - Country Managers ({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 + + Country Managers ({total}) + + )} + /> + ); + }; - const CorporateList = () => ( - x.type === "corporate"]} - renderHeader={(total) => ( - - 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 - - Corporate ({total}) - - )} - /> - ); + const CorporateList = () => ( + x.type === "corporate"]} + renderHeader={(total) => ( + + 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 + + Corporate ({total}) + + )} + /> + ); - const CorporatePaidStatusList = ({ paid }: { paid: Boolean }) => { - const list = paid ? done : pending; - const filter = (x: User) => x.type === "corporate" && list.includes(x.id); + const CorporatePaidStatusList = ({paid}: {paid: Boolean}) => { + const list = paid ? done : pending; + const filter = (x: User) => x.type === "corporate" && list.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 - - - {paid ? "Payment Done" : "Pending Payment"} ({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 + + + {paid ? "Payment Done" : "Pending Payment"} ({total}) + + + )} + /> + ); + }; - const InactiveCountryManagerList = () => { - 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 - - - Inactive Country Managers ({total}) - - - )} - /> - ); - }; + const InactiveCountryManagerList = () => { + 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 + + Inactive Country Managers ({total}) + + )} + /> + ); + }; - const InactiveStudentsList = () => { - const filter = (x: User) => - x.type === "student" && - (x.status === "disabled" || - moment().isAfter(x.subscriptionExpirationDate)); + const InactiveStudentsList = () => { + const filter = (x: User) => x.type === "student" && (x.status === "disabled" || moment().isAfter(x.subscriptionExpirationDate)); - 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 - - - Inactive 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 + + Inactive Students ({total}) + + )} + /> + ); + }; - const InactiveCorporateList = () => { - const filter = (x: User) => - x.type === "corporate" && - (x.status === "disabled" || - moment().isAfter(x.subscriptionExpirationDate)); + const InactiveCorporateList = () => { + const filter = (x: User) => x.type === "corporate" && (x.status === "disabled" || moment().isAfter(x.subscriptionExpirationDate)); - 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 - - - Inactive Corporate ({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 + + Inactive Corporate ({total}) + + )} + /> + ); + }; - const CorporateStudentsLevelsHelper = () => { - 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 - - - Corporate Students Levels - - - - > - ); - }; + const CorporateStudentsLevelsHelper = () => { + 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 + + Corporate Students Levels + + + > + ); + }; - const DefaultDashboard = () => ( - <> - - x.type === "student").length} - onClick={() => setPage("students")} - color="purple" - /> - x.type === "teacher").length} - onClick={() => setPage("teachers")} - color="purple" - /> - x.type === "corporate").length} - onClick={() => setPage("corporate")} - color="purple" - /> - x.type === "agent").length} - onClick={() => setPage("agents")} - color="purple" - /> - x.demographicInformation) - .map((x) => x.demographicInformation?.country) - ), - ].length - } - color="purple" - /> - setPage("inactiveStudents")} - Icon={BsPersonFill} - label="Inactive Students" - value={ - users.filter( - (x) => - x.type === "student" && - (x.status === "disabled" || - moment().isAfter(x.subscriptionExpirationDate)) - ).length - } - color="rose" - /> - setPage("inactiveCountryManagers")} - Icon={BsBriefcaseFill} - label="Inactive Country Managers" - value={users.filter(inactiveCountryManagerFilter).length} - color="rose" - /> - setPage("inactiveCorporate")} - Icon={BsBank} - label="Inactive Corporate" - value={ - users.filter( - (x) => - x.type === "corporate" && - (x.status === "disabled" || - moment().isAfter(x.subscriptionExpirationDate)) - ).length - } - color="rose" - /> - setPage("paymentdone")} - Icon={BsCurrencyDollar} - label="Payment Done" - value={done.length} - color="purple" - /> - setPage("paymentpending")} - Icon={BsCurrencyDollar} - label="Pending Payment" - value={pending.length} - color="rose" - /> - router.push("https://cms.encoach.com/admin")} - Icon={BsLayoutSidebar} - label="Content Management System (CMS)" - color="green" - /> - setPage("corporatestudentslevels")} - Icon={BsPersonFill} - label="Corporate Students Levels" - color="purple" - /> - + const DefaultDashboard = () => ( + <> + + x.type === "student").length} + onClick={() => setPage("students")} + color="purple" + /> + x.type === "teacher").length} + onClick={() => setPage("teachers")} + color="purple" + /> + x.type === "corporate").length} + onClick={() => setPage("corporate")} + color="purple" + /> + x.type === "agent").length} + onClick={() => setPage("agents")} + color="purple" + /> + x.demographicInformation).map((x) => x.demographicInformation?.country))].length} + color="purple" + /> + setPage("inactiveStudents")} + Icon={BsPersonFill} + label="Inactive Students" + value={ + users.filter((x) => x.type === "student" && (x.status === "disabled" || moment().isAfter(x.subscriptionExpirationDate))) + .length + } + color="rose" + /> + setPage("inactiveCountryManagers")} + Icon={BsBriefcaseFill} + label="Inactive Country Managers" + value={users.filter(inactiveCountryManagerFilter).length} + color="rose" + /> + setPage("inactiveCorporate")} + Icon={BsBank} + label="Inactive Corporate" + value={ + users.filter((x) => x.type === "corporate" && (x.status === "disabled" || moment().isAfter(x.subscriptionExpirationDate))) + .length + } + color="rose" + /> + setPage("paymentdone")} Icon={BsCurrencyDollar} label="Payment Done" value={done.length} color="purple" /> + setPage("paymentpending")} + Icon={BsCurrencyDollar} + label="Pending Payment" + value={pending.length} + color="rose" + /> + router.push("https://cms.encoach.com/admin")} + Icon={BsLayoutSidebar} + label="Content Management System (CMS)" + color="green" + /> + setPage("corporatestudentslevels")} Icon={BsPersonFill} label="Corporate Students Levels" color="purple" /> + - - - Latest students - - {users - .filter((x) => x.type === "student") - .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) - .map((x) => ( - - ))} - - - - Latest teachers - - {users - .filter((x) => x.type === "teacher") - .sort((a, b) => { - return dateSorter(a, b, "desc", "registrationDate"); - }) - .map((x) => ( - - ))} - - - - Latest corporate - - {users - .filter((x) => x.type === "corporate") - .sort((a, b) => { - return dateSorter(a, b, "desc", "registrationDate"); - }) - .map((x) => ( - - ))} - - - - Unpaid Corporate - - {users - .filter( - (x) => x.type === "corporate" && x.status === "paymentDue" - ) - .map((x) => ( - - ))} - - - - Students expiring in 1 month - - {users - .filter( - (x) => - x.type === "student" && - x.subscriptionExpirationDate && - moment().isAfter( - moment(x.subscriptionExpirationDate).subtract(30, "days") - ) && - moment().isBefore(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - Teachers expiring in 1 month - - {users - .filter( - (x) => - x.type === "teacher" && - x.subscriptionExpirationDate && - moment().isAfter( - moment(x.subscriptionExpirationDate).subtract(30, "days") - ) && - moment().isBefore(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - Country Manager expiring in 1 month - - {users - .filter( - (x) => - x.type === "agent" && - x.subscriptionExpirationDate && - moment().isAfter( - moment(x.subscriptionExpirationDate).subtract(30, "days") - ) && - moment().isBefore(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - Corporate expiring in 1 month - - {users - .filter( - (x) => - x.type === "corporate" && - x.subscriptionExpirationDate && - moment().isAfter( - moment(x.subscriptionExpirationDate).subtract(30, "days") - ) && - moment().isBefore(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - Expired Students - - {users - .filter( - (x) => - x.type === "student" && - x.subscriptionExpirationDate && - moment().isAfter(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - Expired Teachers - - {users - .filter( - (x) => - x.type === "teacher" && - x.subscriptionExpirationDate && - moment().isAfter(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - Expired Country Manager - - {users - .filter( - (x) => - x.type === "agent" && - x.subscriptionExpirationDate && - moment().isAfter(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - Expired Corporate - - {users - .filter( - (x) => - x.type === "corporate" && - x.subscriptionExpirationDate && - moment().isAfter(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - > - ); + + + Latest students + + {users + .filter((x) => x.type === "student") + .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) + .map((x) => ( + + ))} + + + + Latest teachers + + {users + .filter((x) => x.type === "teacher") + .sort((a, b) => { + return dateSorter(a, b, "desc", "registrationDate"); + }) + .map((x) => ( + + ))} + + + + Latest corporate + + {users + .filter((x) => x.type === "corporate") + .sort((a, b) => { + return dateSorter(a, b, "desc", "registrationDate"); + }) + .map((x) => ( + + ))} + + + + Unpaid Corporate + + {users + .filter((x) => x.type === "corporate" && x.status === "paymentDue") + .map((x) => ( + + ))} + + + + Students expiring in 1 month + + {users + .filter( + (x) => + x.type === "student" && + x.subscriptionExpirationDate && + moment().isAfter(moment(x.subscriptionExpirationDate).subtract(30, "days")) && + moment().isBefore(moment(x.subscriptionExpirationDate)), + ) + .map((x) => ( + + ))} + + + + Teachers expiring in 1 month + + {users + .filter( + (x) => + x.type === "teacher" && + x.subscriptionExpirationDate && + moment().isAfter(moment(x.subscriptionExpirationDate).subtract(30, "days")) && + moment().isBefore(moment(x.subscriptionExpirationDate)), + ) + .map((x) => ( + + ))} + + + + Country Manager expiring in 1 month + + {users + .filter( + (x) => + x.type === "agent" && + x.subscriptionExpirationDate && + moment().isAfter(moment(x.subscriptionExpirationDate).subtract(30, "days")) && + moment().isBefore(moment(x.subscriptionExpirationDate)), + ) + .map((x) => ( + + ))} + + + + Corporate expiring in 1 month + + {users + .filter( + (x) => + x.type === "corporate" && + x.subscriptionExpirationDate && + moment().isAfter(moment(x.subscriptionExpirationDate).subtract(30, "days")) && + moment().isBefore(moment(x.subscriptionExpirationDate)), + ) + .map((x) => ( + + ))} + + + + Expired Students + + {users + .filter( + (x) => x.type === "student" && x.subscriptionExpirationDate && moment().isAfter(moment(x.subscriptionExpirationDate)), + ) + .map((x) => ( + + ))} + + + + Expired Teachers + + {users + .filter( + (x) => x.type === "teacher" && x.subscriptionExpirationDate && moment().isAfter(moment(x.subscriptionExpirationDate)), + ) + .map((x) => ( + + ))} + + + + Expired Country Manager + + {users + .filter( + (x) => x.type === "agent" && x.subscriptionExpirationDate && moment().isAfter(moment(x.subscriptionExpirationDate)), + ) + .map((x) => ( + + ))} + + + + Expired Corporate + + {users + .filter( + (x) => + x.type === "corporate" && x.subscriptionExpirationDate && moment().isAfter(moment(x.subscriptionExpirationDate)), + ) + .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 - } - onViewCorporate={ - selectedUser.type === "teacher" || - selectedUser.type === "student" - ? () => { - appendUserFilters({ - id: "view-corporate", - filter: (x: User) => x.type === "corporate", - }); - appendUserFilters({ - id: "belongs-to-admin", - filter: (x: User) => - groups - .filter((g) => - g.participants.includes(selectedUser.id) - ) - .flatMap((g) => [g.admin, ...g.participants]) - .includes(x.id), - }); + router.push("/list/users"); + } + : undefined + } + onViewCorporate={ + selectedUser.type === "teacher" || selectedUser.type === "student" + ? () => { + appendUserFilters({ + id: "view-corporate", + filter: (x: User) => x.type === "corporate", + }); + appendUserFilters({ + id: "belongs-to-admin", + filter: (x: User) => + groups + .filter((g) => g.participants.includes(selectedUser.id)) + .flatMap((g) => [g.admin, ...g.participants]) + .includes(x.id), + }); - router.push("/list/users"); - } - : undefined - } - user={selectedUser} - /> - - )} - > - - {page === "students" && } - {page === "teachers" && } - {page === "corporate" && } - {page === "agents" && } - {page === "inactiveStudents" && } - {page === "inactiveCorporate" && } - {page === "inactiveCountryManagers" && } - {page === "paymentdone" && } - {page === "paymentpending" && } - {page === "corporatestudentslevels" && } - {page === "" && } - > - ); + router.push("/list/users"); + } + : undefined + } + user={selectedUser} + /> + + )} + > + + {page === "students" && } + {page === "teachers" && } + {page === "corporate" && } + {page === "agents" && } + {page === "inactiveStudents" && } + {page === "inactiveCorporate" && } + {page === "inactiveCountryManagers" && } + {page === "paymentdone" && } + {page === "paymentpending" && } + {page === "corporatestudentslevels" && } + {page === "" && } + > + ); } diff --git a/src/dashboards/Agent.tsx b/src/dashboards/Agent.tsx index bff2c46d..11028894 100644 --- a/src/dashboards/Agent.tsx +++ b/src/dashboards/Agent.tsx @@ -2,17 +2,12 @@ import Modal from "@/components/Modal"; import useStats from "@/hooks/useStats"; import useUsers from "@/hooks/useUsers"; -import { User } from "@/interfaces/user"; +import {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 { - BsArrowLeft, - BsPersonFill, - BsBank, - BsCurrencyDollar, -} from "react-icons/bs"; +import {useEffect, useState} from "react"; +import {BsArrowLeft, BsPersonFill, BsBank, BsCurrencyDollar} from "react-icons/bs"; import UserCard from "@/components/UserCard"; import useGroups from "@/hooks/useGroups"; @@ -20,276 +15,235 @@ import IconCard from "./IconCard"; import usePaymentStatusUsers from "@/hooks/usePaymentStatusUsers"; interface Props { - user: User; + user: User; } -export default function AgentDashboard({ user }: Props) { - const [page, setPage] = useState(""); - const [selectedUser, setSelectedUser] = useState(); - const [showModal, setShowModal] = useState(false); +export default function AgentDashboard({user}: Props) { + const [page, setPage] = useState(""); + const [selectedUser, setSelectedUser] = useState(); + const [showModal, setShowModal] = useState(false); - const { stats } = useStats(); - const { users, reload } = useUsers(); - const { groups } = useGroups(user.id); - const { pending, done } = usePaymentStatusUsers(); + const {stats} = useStats(); + const {users, reload} = useUsers(); + const {pending, done} = usePaymentStatusUsers(); - useEffect(() => { - setShowModal(!!selectedUser && page === ""); - }, [selectedUser, page]); + useEffect(() => { + setShowModal(!!selectedUser && page === ""); + }, [selectedUser, page]); - const corporateFilter = (user: User) => user.type === "corporate"; - const referredCorporateFilter = (x: User) => - x.type === "corporate" && - !!x.corporateInformation && - x.corporateInformation.referralAgent === user.id; - const inactiveReferredCorporateFilter = (x: User) => - referredCorporateFilter(x) && - (x.status === "disabled" || moment().isAfter(x.subscriptionExpirationDate)); + const corporateFilter = (user: User) => user.type === "corporate"; + const referredCorporateFilter = (x: User) => + x.type === "corporate" && !!x.corporateInformation && x.corporateInformation.referralAgent === user.id; + const inactiveReferredCorporateFilter = (x: User) => + referredCorporateFilter(x) && (x.status === "disabled" || moment().isAfter(x.subscriptionExpirationDate)); - const UserDisplay = ({ - displayUser, - allowClick = true, - }: { - displayUser: User; - allowClick?: boolean; - }) => ( - allowClick && 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.type === "corporate" - ? displayUser.corporateInformation?.companyInformation?.name || - displayUser.name - : displayUser.name} - - {displayUser.email} - - - ); + const UserDisplay = ({displayUser, allowClick = true}: {displayUser: User; allowClick?: boolean}) => ( + allowClick && 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.type === "corporate" + ? displayUser.corporateInformation?.companyInformation?.name || displayUser.name + : displayUser.name} + + {displayUser.email} + + + ); - const ReferredCorporateList = () => { - 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 - - - Referred Corporate ({total}) - - - )} - /> - ); - }; + const ReferredCorporateList = () => { + 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 + + Referred Corporate ({total}) + + )} + /> + ); + }; - const InactiveReferredCorporateList = () => { - 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 - - - Inactive Referred Corporate ({total}) - - - )} - /> - ); - }; + const InactiveReferredCorporateList = () => { + 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 + + Inactive Referred Corporate ({total}) + + )} + /> + ); + }; - const CorporateList = () => { - const filter = (x: User) => x.type === "corporate"; + const CorporateList = () => { + const filter = (x: User) => x.type === "corporate"; - 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 - - Corporate ({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 + + Corporate ({total}) + + )} + /> + ); + }; - const CorporatePaidStatusList = ({ paid }: { paid: Boolean }) => { - const list = paid ? done : pending; - const filter = (x: User) => x.type === "corporate" && list.includes(x.id); + const CorporatePaidStatusList = ({paid}: {paid: Boolean}) => { + const list = paid ? done : pending; + const filter = (x: User) => x.type === "corporate" && list.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 - - - {paid ? "Payment Done" : "Pending Payment"} ({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 + + + {paid ? "Payment Done" : "Pending Payment"} ({total}) + + + )} + /> + ); + }; - const DefaultDashboard = () => ( - <> - - setPage("referredCorporate")} - Icon={BsBank} - label="Referred Corporate" - value={users.filter(referredCorporateFilter).length} - color="purple" - /> - setPage("inactiveReferredCorporate")} - Icon={BsBank} - label="Inactive Referred Corporate" - value={users.filter(inactiveReferredCorporateFilter).length} - color="rose" - /> - setPage("corporate")} - Icon={BsBank} - label="Corporate" - value={users.filter(corporateFilter).length} - color="purple" - /> - setPage("paymentdone")} - Icon={BsCurrencyDollar} - label="Payment Done" - value={done.length} - color="purple" - /> - setPage("paymentpending")} - Icon={BsCurrencyDollar} - label="Pending Payment" - value={pending.length} - color="rose" - /> - + const DefaultDashboard = () => ( + <> + + setPage("referredCorporate")} + Icon={BsBank} + label="Referred Corporate" + value={users.filter(referredCorporateFilter).length} + color="purple" + /> + setPage("inactiveReferredCorporate")} + Icon={BsBank} + label="Inactive Referred Corporate" + value={users.filter(inactiveReferredCorporateFilter).length} + color="rose" + /> + setPage("corporate")} + Icon={BsBank} + label="Corporate" + value={users.filter(corporateFilter).length} + color="purple" + /> + setPage("paymentdone")} Icon={BsCurrencyDollar} label="Payment Done" value={done.length} color="purple" /> + setPage("paymentpending")} + Icon={BsCurrencyDollar} + label="Pending Payment" + value={pending.length} + color="rose" + /> + - - - Latest Referred Corporate - - {users - .filter(referredCorporateFilter) - .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) - .map((x) => ( - - ))} - - - - Latest corporate - - {users - .filter(corporateFilter) - .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) - .map((x) => ( - - ))} - - - - Referenced corporate expiring in 1 month - - {users - .filter( - (x) => - referredCorporateFilter(x) && - moment().isAfter( - moment(x.subscriptionExpirationDate).subtract(30, "days") - ) && - moment().isBefore(moment(x.subscriptionExpirationDate)) - ) - .map((x) => ( - - ))} - - - - > - ); + + + Latest Referred Corporate + + {users + .filter(referredCorporateFilter) + .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) + .map((x) => ( + + ))} + + + + Latest corporate + + {users + .filter(corporateFilter) + .sort((a, b) => dateSorter(a, b, "desc", "registrationDate")) + .map((x) => ( + + ))} + + + + Referenced corporate expiring in 1 month + + {users + .filter( + (x) => + referredCorporateFilter(x) && + moment().isAfter(moment(x.subscriptionExpirationDate).subtract(30, "days")) && + moment().isBefore(moment(x.subscriptionExpirationDate)), + ) + .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 === "referredCorporate" && } - {page === "corporate" && } - {page === "inactiveReferredCorporate" && ( - - )} - {page === "paymentdone" && } - {page === "paymentpending" && } - {page === "" && } - > - ); + 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 === "referredCorporate" && } + {page === "corporate" && } + {page === "inactiveReferredCorporate" && } + {page === "paymentdone" && } + {page === "paymentpending" && } + {page === "" && } + > + ); } diff --git a/src/dashboards/Corporate.tsx b/src/dashboards/Corporate.tsx index 5c8daa26..4c3b1bf8 100644 --- a/src/dashboards/Corporate.tsx +++ b/src/dashboards/Corporate.tsx @@ -62,7 +62,7 @@ export default function CorporateDashboard({user}: Props) { const {stats} = useStats(); const {users, reload} = useUsers(); const {codes} = useCodes(user.id); - const {groups} = useGroups(user.id); + const {groups} = useGroups({admin: user.id}); const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({corporate: user.id}); const appendUserFilters = useFilterStore((state) => state.appendUserFilter); diff --git a/src/dashboards/CorporateStudentsLevels.tsx b/src/dashboards/CorporateStudentsLevels.tsx index 698c06ae..95076ece 100644 --- a/src/dashboards/CorporateStudentsLevels.tsx +++ b/src/dashboards/CorporateStudentsLevels.tsx @@ -1,140 +1,108 @@ import React from "react"; import useUsers from "@/hooks/useUsers"; import useGroups from "@/hooks/useGroups"; -import { User } from "@/interfaces/user"; +import {User} from "@/interfaces/user"; import Select from "@/components/Low/Select"; import ProgressBar from "@/components/Low/ProgressBar"; -import { - BsBook, - BsClipboard, - BsHeadphones, - BsMegaphone, - BsPen, -} from "react-icons/bs"; -import { MODULE_ARRAY } from "@/utils/moduleUtils"; -import { capitalize } from "lodash"; -import { getLevelLabel } from "@/utils/score"; +import {BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs"; +import {MODULE_ARRAY} from "@/utils/moduleUtils"; +import {capitalize} from "lodash"; +import {getLevelLabel} from "@/utils/score"; -const Card = ({ user }: { user: User }) => { - return ( - - - {user.name} - - - {MODULE_ARRAY.map((module) => { - const desiredLevel = user.desiredLevels[module] || 9; - const level = user.levels[module] || 0; - return ( - - - - {module === "reading" && ( - - )} - {module === "listening" && ( - - )} - {module === "writing" && ( - - )} - {module === "speaking" && ( - - )} - {module === "level" && ( - - )} - - - - {capitalize(module)} - - - {module === "level" && ( - - English Level: {getLevelLabel(level).join(" / ")} - - )} - {module !== "level" && ( - - Level {level} / Level 9 - Desired Level: {desiredLevel} - - )} - - - - - - - - ); - })} - - - ); +const Card = ({user}: {user: User}) => { + return ( + + + {user.name} + + + {MODULE_ARRAY.map((module) => { + const desiredLevel = user.desiredLevels[module] || 9; + const level = user.levels[module] || 0; + return ( + + + + {module === "reading" && } + {module === "listening" && } + {module === "writing" && } + {module === "speaking" && } + {module === "level" && } + + + {capitalize(module)} + + {module === "level" && English Level: {getLevelLabel(level).join(" / ")}} + {module !== "level" && ( + + Level {level} / Level 9 + Desired Level: {desiredLevel} + + )} + + + + + + + + ); + })} + + + ); }; const CorporateStudentsLevels = () => { - const { users } = useUsers(); - const { groups } = useGroups(); + const {users} = useUsers(); + const {groups} = useGroups({}); - const corporateUsers = users.filter((u) => u.type === "corporate") as User[]; - const [corporateId, setCorporateId] = React.useState(""); - const corporate = - corporateUsers.find((u) => u.id === corporateId) || corporateUsers[0]; + const corporateUsers = users.filter((u) => u.type === "corporate") as User[]; + const [corporateId, setCorporateId] = React.useState(""); + const corporate = corporateUsers.find((u) => u.id === corporateId) || corporateUsers[0]; - const groupsFromCorporate = corporate - ? groups.filter((g) => g.admin === corporate.id) - : []; + const groupsFromCorporate = corporate ? groups.filter((g) => g.admin === corporate.id) : []; - const groupsParticipants = groupsFromCorporate - .flatMap((g) => g.participants) - .reduce((accm: User[], p) => { - const user = users.find((u) => u.id === p) as User; - if (user) { - return [...accm, user]; - } - return accm; - }, []); + const groupsParticipants = groupsFromCorporate + .flatMap((g) => g.participants) + .reduce((accm: User[], p) => { + const user = users.find((u) => u.id === p) as User; + if (user) { + return [...accm, user]; + } + return accm; + }, []); - return ( - <> - ({ - value: x.id, - label: `${x.name} - ${x.email}`, - }))} - value={corporate ? { value: corporate.id, label: corporate.name } : null} - onChange={(value) => setCorporateId(value?.value!)} - styles={{ - menuPortal: (base) => ({ ...base, zIndex: 9999 }), - option: (styles, state) => ({ - ...styles, - backgroundColor: state.isFocused - ? "#D5D9F0" - : state.isSelected - ? "#7872BF" - : "white", - color: state.isFocused ? "black" : styles.color, - }), - }} - /> - {groupsParticipants.map((u) => ( - - ))} - > - ); + return ( + <> + ({ + value: x.id, + label: `${x.name} - ${x.email}`, + }))} + value={corporate ? {value: corporate.id, label: corporate.name} : null} + onChange={(value) => setCorporateId(value?.value!)} + styles={{ + menuPortal: (base) => ({...base, zIndex: 9999}), + option: (styles, state) => ({ + ...styles, + backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", + color: state.isFocused ? "black" : styles.color, + }), + }} + /> + {groupsParticipants.map((u) => ( + + ))} + > + ); }; export default CorporateStudentsLevels; diff --git a/src/dashboards/MasterCorporate.tsx b/src/dashboards/MasterCorporate.tsx index e5eb1b96..551158a8 100644 --- a/src/dashboards/MasterCorporate.tsx +++ b/src/dashboards/MasterCorporate.tsx @@ -54,7 +54,7 @@ export default function MasterCorporateDashboard({user}: Props) { const {stats} = useStats(); const {users, reload} = useUsers(); const {codes} = useCodes(user.id); - const {groups} = useGroups(user.id, user.type); + const {groups} = useGroups({admin: user.id, userType: user.type}); const masterCorporateUserGroups = [...new Set(groups.filter((u) => u.admin === user.id).flatMap((g) => g.participants))]; const corporateUserGroups = [...new Set(groups.flatMap((g) => g.participants))]; diff --git a/src/dashboards/Teacher.tsx b/src/dashboards/Teacher.tsx index d4238b67..860b74f0 100644 --- a/src/dashboards/Teacher.tsx +++ b/src/dashboards/Teacher.tsx @@ -63,7 +63,7 @@ export default function TeacherDashboard({user}: Props) { const {stats} = useStats(); const {users, reload} = useUsers(); - const {groups} = useGroups(user.id); + const {groups} = useGroups({admin: user.id}); const {permissions} = usePermissions(user.id); const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({assigner: user.id}); diff --git a/src/hooks/useGroups.tsx b/src/hooks/useGroups.tsx index 9b4db75a..f49ab5e5 100644 --- a/src/hooks/useGroups.tsx +++ b/src/hooks/useGroups.tsx @@ -2,7 +2,13 @@ import {Group, User} from "@/interfaces/user"; import axios from "axios"; import {useEffect, useState} from "react"; -export default function useGroups(admin?: string, userType?: string, teacher?: string) { +interface Props { + admin?: string; + userType?: string; + adminAdmins?: string; +} + +export default function useGroups({admin, userType, adminAdmins}: Props) { const [groups, setGroups] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isError, setIsError] = useState(false); @@ -12,24 +18,24 @@ export default function useGroups(admin?: string, userType?: string, teacher?: s const getData = () => { setIsLoading(true); - const url = admin && !teacher ? `/api/groups?admin=${admin}` : "/api/groups"; + const url = admin && !adminAdmins ? `/api/groups?admin=${admin}` : "/api/groups"; axios .get(url) .then((response) => { if (isMasterType) return setGroups(response.data); - const filterByAdmins = !!teacher - ? [teacher, ...response.data.filter((g) => g.participants.includes(teacher)).flatMap((g) => g.admin)] + const filterByAdmins = !!adminAdmins + ? [adminAdmins, ...response.data.filter((g) => g.participants.includes(adminAdmins)).flatMap((g) => g.admin)] : [admin]; - const filter = (g: Group) => filterByAdmins.includes(g.admin) || g.participants.includes(admin || ""); + const adminFilter = (g: Group) => filterByAdmins.includes(g.admin) || g.participants.includes(admin || ""); - const filteredGroups = !!admin || !!teacher ? response.data.filter(filter) : response.data; + const filteredGroups = !!admin || !!adminAdmins ? response.data.filter(adminFilter) : response.data; return setGroups(admin ? filteredGroups.map((g) => ({...g, disableEditing: g.disableEditing || g.admin !== admin})) : filteredGroups); }) .finally(() => setIsLoading(false)); }; - useEffect(getData, [admin, teacher, isMasterType]); + useEffect(getData, [admin, adminAdmins, isMasterType]); return {groups, isLoading, isError, reload: getData}; } diff --git a/src/pages/(admin)/Lists/GroupList.tsx b/src/pages/(admin)/Lists/GroupList.tsx index 3ac5be76..0da16407 100644 --- a/src/pages/(admin)/Lists/GroupList.tsx +++ b/src/pages/(admin)/Lists/GroupList.tsx @@ -201,11 +201,11 @@ export default function GroupList({user}: {user: User}) { const {permissions} = usePermissions(user?.id || ""); const {users} = useUsers(); - const {groups, reload} = useGroups( - user && filterTypes.includes(user?.type) ? user.id : undefined, - user?.type, - user?.type === "teacher" ? user?.id : undefined, - ); + const {groups, reload} = useGroups({ + admin: user && filterTypes.includes(user?.type) ? user.id : undefined, + userType: user?.type, + adminAdmins: user?.type === "teacher" ? user?.id : undefined, + }); useEffect(() => { if (user && ["corporate", "teacher", "mastercorporate"].includes(user.type)) { diff --git a/src/pages/(admin)/Lists/UserList.tsx b/src/pages/(admin)/Lists/UserList.tsx index dabfca1c..220022a4 100644 --- a/src/pages/(admin)/Lists/UserList.tsx +++ b/src/pages/(admin)/Lists/UserList.tsx @@ -58,7 +58,7 @@ export default function UserList({ const {users, reload} = useUsers(); const {permissions} = usePermissions(user?.id || ""); - const {groups} = useGroups(user && ["corporate", "teacher", "mastercorporate"].includes(user?.type) ? user.id : undefined); + const {groups} = useGroups({admin: user && ["corporate", "teacher", "mastercorporate"].includes(user?.type) ? user.id : undefined}); const appendUserFilters = useFilterStore((state) => state.appendUserFilter); const router = useRouter(); diff --git a/src/pages/(status)/PaymentDue.tsx b/src/pages/(status)/PaymentDue.tsx index cf04baa2..b081db1d 100644 --- a/src/pages/(status)/PaymentDue.tsx +++ b/src/pages/(status)/PaymentDue.tsx @@ -31,7 +31,7 @@ export default function PaymentDue({user, hasExpired = false, reload}: Props) { const {packages} = usePackages(); const {discounts} = useDiscounts(); const {users} = useUsers(); - const {groups} = useGroups(); + const {groups} = useGroups({}); const {invites, isLoading: isInvitesLoading, reload: reloadInvites} = useInvites({to: user?.id}); useEffect(() => { diff --git a/src/pages/groups.tsx b/src/pages/groups.tsx new file mode 100644 index 00000000..6e037316 --- /dev/null +++ b/src/pages/groups.tsx @@ -0,0 +1,119 @@ +/* eslint-disable @next/next/no-img-element */ +import Head from "next/head"; +import Navbar from "@/components/Navbar"; +import {BsFileEarmarkText, BsPencil, BsStar, BsBook, BsHeadphones, BsPen, BsMegaphone} from "react-icons/bs"; +import {withIronSessionSsr} from "iron-session/next"; +import {sessionOptions} from "@/lib/session"; +import {useEffect, useState} from "react"; +import useStats from "@/hooks/useStats"; +import {averageScore, groupBySession, totalExams} from "@/utils/stats"; +import useUser from "@/hooks/useUser"; +import Diagnostic from "@/components/Diagnostic"; +import {ToastContainer} from "react-toastify"; +import {capitalize} from "lodash"; +import {Module} from "@/interfaces"; +import ProgressBar from "@/components/Low/ProgressBar"; +import Layout from "@/components/High/Layout"; +import {calculateAverageLevel} from "@/utils/score"; +import axios from "axios"; +import DemographicInformationInput from "@/components/DemographicInformationInput"; +import moment from "moment"; +import Link from "next/link"; +import {MODULE_ARRAY} from "@/utils/moduleUtils"; +import ProfileSummary from "@/components/ProfileSummary"; +import StudentDashboard from "@/dashboards/Student"; +import AdminDashboard from "@/dashboards/Admin"; +import CorporateDashboard from "@/dashboards/Corporate"; +import TeacherDashboard from "@/dashboards/Teacher"; +import AgentDashboard from "@/dashboards/Agent"; +import MasterCorporateDashboard from "@/dashboards/MasterCorporate"; +import PaymentDue from "./(status)/PaymentDue"; +import {useRouter} from "next/router"; +import {PayPalScriptProvider} from "@paypal/react-paypal-js"; +import {CorporateUser, MasterCorporateUser, Type, User, userTypes} from "@/interfaces/user"; +import Select from "react-select"; +import {USER_TYPE_LABELS} from "@/resources/user"; +import {checkAccess, getTypesOfUser} from "@/utils/permissions"; +import {shouldRedirectHome} from "@/utils/navigation.disabled"; +import useGroups from "@/hooks/useGroups"; +import useUsers from "@/hooks/useUsers"; +import {getUserName} from "@/utils/users"; + +export const getServerSideProps = withIronSessionSsr(({req, res}) => { + const user = req.session.user; + + if (!user || !user.isVerified) { + return { + redirect: { + destination: "/login", + permanent: false, + }, + }; + } + + if (shouldRedirectHome(user)) { + return { + redirect: { + destination: "/", + permanent: false, + }, + }; + } + + return { + props: {user: req.session.user}, + }; +}, sessionOptions); + +interface Props { + user: User; + envVariables: {[key: string]: string}; +} +export default function Home(props: Props) { + const {user, mutateUser} = useUser({redirectTo: "/login"}); + const {groups} = useGroups({}); + const {users} = useUsers(); + + const router = useRouter(); + + useEffect(() => { + console.log(groups); + }, [groups]); + + return ( + <> + + EnCoach + + + + + + {user && ( + + + {groups + .filter((x) => x.participants.includes(user.id)) + .map((group) => ( + + + Group: + {group.name} + + + Admin: + {getUserName(users.find((x) => x.id === group.admin))} + + Participants: + {group.participants.map((x) => getUserName(users.find((u) => u.id === x))).join(", ")} + + ))} + + + )} + > + ); +} diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index 5e1fcae9..f4d78455 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -1,818 +1,659 @@ /* eslint-disable @next/next/no-img-element */ import Head from "next/head"; -import { withIronSessionSsr } from "iron-session/next"; -import { sessionOptions } from "@/lib/session"; -import { - ChangeEvent, - Dispatch, - ReactNode, - SetStateAction, - useEffect, - useRef, - useState, -} from "react"; +import {withIronSessionSsr} from "iron-session/next"; +import {sessionOptions} from "@/lib/session"; +import {ChangeEvent, Dispatch, ReactNode, SetStateAction, useEffect, useRef, useState} from "react"; import useUser from "@/hooks/useUser"; -import { toast, ToastContainer } from "react-toastify"; +import {toast, ToastContainer} from "react-toastify"; import Layout from "@/components/High/Layout"; import Input from "@/components/Low/Input"; import Button from "@/components/Low/Button"; import Link from "next/link"; import axios from "axios"; -import { ErrorMessage } from "@/constants/errors"; +import {ErrorMessage} from "@/constants/errors"; import clsx from "clsx"; -import { - CorporateUser, - EmploymentStatus, - EMPLOYMENT_STATUS, - Gender, - User, - DemographicInformation, -} from "@/interfaces/user"; +import {CorporateUser, EmploymentStatus, EMPLOYMENT_STATUS, Gender, User, DemographicInformation} from "@/interfaces/user"; import CountrySelect from "@/components/Low/CountrySelect"; -import { shouldRedirectHome } from "@/utils/navigation.disabled"; +import {shouldRedirectHome} from "@/utils/navigation.disabled"; import moment from "moment"; -import { BsCamera, BsQuestionCircleFill } from "react-icons/bs"; -import { USER_TYPE_LABELS } from "@/resources/user"; +import {BsCamera, BsQuestionCircleFill} from "react-icons/bs"; +import {USER_TYPE_LABELS} from "@/resources/user"; import useGroups from "@/hooks/useGroups"; import useUsers from "@/hooks/useUsers"; -import { convertBase64 } from "@/utils"; -import { Divider } from "primereact/divider"; +import {convertBase64} from "@/utils"; +import {Divider} from "primereact/divider"; import GenderInput from "@/components/High/GenderInput"; import EmploymentStatusInput from "@/components/High/EmploymentStatusInput"; import TimezoneSelect from "@/components/Low/TImezoneSelect"; import Modal from "@/components/Modal"; -import { Module } from "@/interfaces"; +import {Module} from "@/interfaces"; import ModuleLevelSelector from "@/components/Medium/ModuleLevelSelector"; import Select from "@/components/Low/Select"; -import { InstructorGender } from "@/interfaces/exam"; -import { capitalize } from "lodash"; +import {InstructorGender} from "@/interfaces/exam"; +import {capitalize} from "lodash"; import TopicModal from "@/components/Medium/TopicModal"; -import { v4 } from "uuid"; -import { checkAccess, getTypesOfUser } from "@/utils/permissions"; +import {v4} from "uuid"; +import {checkAccess, getTypesOfUser} from "@/utils/permissions"; -export const getServerSideProps = withIronSessionSsr(({ req, res }) => { - const user = req.session.user; +export const getServerSideProps = withIronSessionSsr(({req, res}) => { + const user = req.session.user; - if (!user || !user.isVerified) { - return { - redirect: { - destination: "/login", - permanent: false, - }, - }; - } + if (!user || !user.isVerified) { + return { + redirect: { + destination: "/login", + permanent: false, + }, + }; + } - if (shouldRedirectHome(user)) { - return { - redirect: { - destination: "/", - permanent: false, - }, - }; - } + if (shouldRedirectHome(user)) { + return { + redirect: { + destination: "/", + permanent: false, + }, + }; + } - return { - props: { user: req.session.user }, - }; + return { + props: {user: req.session.user}, + }; }, sessionOptions); interface Props { - user: User; - mutateUser: Function; + user: User; + mutateUser: Function; } -const DoubleColumnRow = ({ children }: { children: ReactNode }) => ( - {children} -); +const DoubleColumnRow = ({children}: {children: ReactNode}) => {children}; -function UserProfile({ user, mutateUser }: Props) { - const [bio, setBio] = useState(user.bio || ""); - const [name, setName] = useState(user.name || ""); - const [email, setEmail] = useState(user.email || ""); - const [password, setPassword] = useState(""); - const [newPassword, setNewPassword] = useState(""); - const [isLoading, setIsLoading] = useState(false); - const [profilePicture, setProfilePicture] = useState(user.profilePicture); +function UserProfile({user, mutateUser}: Props) { + const [bio, setBio] = useState(user.bio || ""); + const [name, setName] = useState(user.name || ""); + const [email, setEmail] = useState(user.email || ""); + const [password, setPassword] = useState(""); + const [newPassword, setNewPassword] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const [profilePicture, setProfilePicture] = useState(user.profilePicture); - const [desiredLevels, setDesiredLevels] = useState< - { [key in Module]: number } | undefined - >( - checkAccess(user, ["developer", "student"]) ? user.desiredLevels : undefined - ); - const [focus, setFocus] = useState<"academic" | "general">(user.focus); + const [desiredLevels, setDesiredLevels] = useState<{[key in Module]: number} | undefined>( + checkAccess(user, ["developer", "student"]) ? user.desiredLevels : undefined, + ); + const [focus, setFocus] = useState<"academic" | "general">(user.focus); - const [country, setCountry] = useState( - user.demographicInformation?.country || "" - ); - const [phone, setPhone] = useState( - user.demographicInformation?.phone || "" - ); - const [gender, setGender] = useState( - user.demographicInformation?.gender || undefined - ); - const [employment, setEmployment] = useState( - checkAccess(user, ["corporate", "mastercorporate"]) - ? undefined - : (user.demographicInformation as DemographicInformation)?.employment - ); - const [passport_id, setPassportID] = useState( - checkAccess(user, ["student"]) - ? (user.demographicInformation as DemographicInformation)?.passport_id - : undefined - ); + const [country, setCountry] = useState(user.demographicInformation?.country || ""); + const [phone, setPhone] = useState(user.demographicInformation?.phone || ""); + const [gender, setGender] = useState(user.demographicInformation?.gender || undefined); + const [employment, setEmployment] = useState( + checkAccess(user, ["corporate", "mastercorporate"]) ? undefined : (user.demographicInformation as DemographicInformation)?.employment, + ); + const [passport_id, setPassportID] = useState( + checkAccess(user, ["student"]) ? (user.demographicInformation as DemographicInformation)?.passport_id : undefined, + ); - const [preferredGender, setPreferredGender] = useState< - InstructorGender | undefined - >( - user.type === "student" || user.type === "developer" - ? user.preferredGender || "varied" - : undefined - ); - const [preferredTopics, setPreferredTopics] = useState( - user.type === "student" || user.type === "developer" - ? user.preferredTopics - : undefined - ); + const [preferredGender, setPreferredGender] = useState( + user.type === "student" || user.type === "developer" ? user.preferredGender || "varied" : undefined, + ); + const [preferredTopics, setPreferredTopics] = useState( + user.type === "student" || user.type === "developer" ? user.preferredTopics : undefined, + ); - const [position, setPosition] = useState( - user.type === "corporate" - ? user.demographicInformation?.position - : undefined - ); - const [corporateInformation, setCorporateInformation] = useState( - user.type === "corporate" ? user.corporateInformation : undefined - ); - const [companyName, setCompanyName] = useState( - user.type === "agent" ? user.agentInformation?.companyName : undefined - ); - const [commercialRegistration, setCommercialRegistration] = useState< - string | undefined - >( - user.type === "agent" - ? user.agentInformation?.commercialRegistration - : undefined - ); - const [arabName, setArabName] = useState( - user.type === "agent" ? user.agentInformation?.companyArabName : undefined - ); + const [position, setPosition] = useState(user.type === "corporate" ? user.demographicInformation?.position : undefined); + const [corporateInformation, setCorporateInformation] = useState(user.type === "corporate" ? user.corporateInformation : undefined); + const [companyName, setCompanyName] = useState(user.type === "agent" ? user.agentInformation?.companyName : undefined); + const [commercialRegistration, setCommercialRegistration] = useState( + user.type === "agent" ? user.agentInformation?.commercialRegistration : undefined, + ); + const [arabName, setArabName] = useState(user.type === "agent" ? user.agentInformation?.companyArabName : undefined); - const [timezone, setTimezone] = useState( - user.demographicInformation?.timezone || moment.tz.guess() - ); + const [timezone, setTimezone] = useState(user.demographicInformation?.timezone || moment.tz.guess()); - const [isPreferredTopicsOpen, setIsPreferredTopicsOpen] = useState(false); + const [isPreferredTopicsOpen, setIsPreferredTopicsOpen] = useState(false); - const { groups } = useGroups(); - const { users } = useUsers(); + const {groups} = useGroups({}); + const {users} = useUsers(); - const profilePictureInput = useRef(null); - const expirationDateColor = (date: Date) => { - const momentDate = moment(date); - const today = moment(new Date()); + const profilePictureInput = useRef(null); + const expirationDateColor = (date: Date) => { + const momentDate = moment(date); + const today = moment(new Date()); - if (today.add(1, "days").isAfter(momentDate)) - return "!bg-mti-red-ultralight border-mti-red-light"; - if (today.add(3, "days").isAfter(momentDate)) - return "!bg-mti-rose-ultralight border-mti-rose-light"; - if (today.add(7, "days").isAfter(momentDate)) - return "!bg-mti-orange-ultralight border-mti-orange-light"; - }; + if (today.add(1, "days").isAfter(momentDate)) return "!bg-mti-red-ultralight border-mti-red-light"; + if (today.add(3, "days").isAfter(momentDate)) return "!bg-mti-rose-ultralight border-mti-rose-light"; + if (today.add(7, "days").isAfter(momentDate)) return "!bg-mti-orange-ultralight border-mti-orange-light"; + }; - const uploadProfilePicture = async (event: ChangeEvent) => { - if (event.target.files && event.target.files[0]) { - const picture = event.target.files[0]; - const base64 = await convertBase64(picture); - setProfilePicture(base64 as string); - } - }; + const uploadProfilePicture = async (event: ChangeEvent) => { + if (event.target.files && event.target.files[0]) { + const picture = event.target.files[0]; + const base64 = await convertBase64(picture); + setProfilePicture(base64 as string); + } + }; - const updateUser = async () => { - setIsLoading(true); - if (email !== user?.email && !password) { - toast.error("To update your e-mail you need to input your password!"); - setIsLoading(false); - return; - } + const updateUser = async () => { + setIsLoading(true); + if (email !== user?.email && !password) { + toast.error("To update your e-mail you need to input your password!"); + setIsLoading(false); + return; + } - if (newPassword && !password) { - toast.error( - "To update your password you need to input your current one!" - ); - setIsLoading(false); - return; - } + if (newPassword && !password) { + toast.error("To update your password you need to input your current one!"); + setIsLoading(false); + return; + } - if (email !== user?.email) { - const userAdmins = groups - .filter((x) => x.participants.includes(user.id)) - .map((x) => x.admin); - const message = - users.filter((x) => userAdmins.includes(x.id) && x.type === "corporate") - .length > 0 - ? "If you change your e-mail address, you will lose all benefits from your university/institute. Are you sure you want to continue?" - : "Are you sure you want to update your e-mail address?"; + if (email !== user?.email) { + const userAdmins = groups.filter((x) => x.participants.includes(user.id)).map((x) => x.admin); + const message = + users.filter((x) => userAdmins.includes(x.id) && x.type === "corporate").length > 0 + ? "If you change your e-mail address, you will lose all benefits from your university/institute. Are you sure you want to continue?" + : "Are you sure you want to update your e-mail address?"; - if (!confirm(message)) { - setIsLoading(false); - return; - } - } + if (!confirm(message)) { + setIsLoading(false); + return; + } + } - axios - .post("/api/users/update", { - bio, - name, - email, - password, - newPassword, - profilePicture, - desiredLevels, - preferredGender, - preferredTopics, - focus, - demographicInformation: { - phone, - country, - employment: user?.type === "corporate" ? undefined : employment, - position: user?.type === "corporate" ? position : undefined, - gender, - passport_id, - timezone, - }, - ...(user.type === "corporate" ? { corporateInformation } : {}), - ...(user.type === "agent" - ? { - agentInformation: { - companyName, - commercialRegistration, - arabName, - }, - } - : {}), - }) - .then((response) => { - if (response.status === 200) { - toast.success("Your profile has been updated!"); - mutateUser((response.data as { user: User }).user); - setIsLoading(false); - return; - } - }) - .catch((error) => { - console.log(error); - toast.error((error.response.data as ErrorMessage).message); - }) - .finally(() => { - setIsLoading(false); - }); - }; + axios + .post("/api/users/update", { + bio, + name, + email, + password, + newPassword, + profilePicture, + desiredLevels, + preferredGender, + preferredTopics, + focus, + demographicInformation: { + phone, + country, + employment: user?.type === "corporate" ? undefined : employment, + position: user?.type === "corporate" ? position : undefined, + gender, + passport_id, + timezone, + }, + ...(user.type === "corporate" ? {corporateInformation} : {}), + ...(user.type === "agent" + ? { + agentInformation: { + companyName, + commercialRegistration, + arabName, + }, + } + : {}), + }) + .then((response) => { + if (response.status === 200) { + toast.success("Your profile has been updated!"); + mutateUser((response.data as {user: User}).user); + setIsLoading(false); + return; + } + }) + .catch((error) => { + console.log(error); + toast.error((error.response.data as ErrorMessage).message); + }) + .finally(() => { + setIsLoading(false); + }); + }; - const ExpirationDate = () => ( - - - Expiry Date (click to purchase) - - - {!user.subscriptionExpirationDate && "Unlimited"} - {user.subscriptionExpirationDate && - moment(user.subscriptionExpirationDate).format("DD/MM/YYYY")} - - - ); + const ExpirationDate = () => ( + + Expiry Date (click to purchase) + + {!user.subscriptionExpirationDate && "Unlimited"} + {user.subscriptionExpirationDate && moment(user.subscriptionExpirationDate).format("DD/MM/YYYY")} + + + ); - const TimezoneInput = () => ( - - - Timezone - - - - ); + const TimezoneInput = () => ( + + Timezone + + + ); - const manualDownloadLink = ["student", "teacher", "corporate"].includes( - user.type - ) - ? `/manuals/${user.type}.pdf` - : ""; + const manualDownloadLink = ["student", "teacher", "corporate"].includes(user.type) ? `/manuals/${user.type}.pdf` : ""; - return ( - - - Edit Profile - - - Edit Profile - e.preventDefault()} - > - - {user.type !== "corporate" ? ( - setName(e)} - placeholder="Enter your name" - defaultValue={name} - required - /> - ) : ( - - setCorporateInformation((prev) => ({ - ...prev!, - companyInformation: { - ...prev!.companyInformation, - name: e, - }, - })) - } - placeholder="Enter your company's name" - defaultValue={corporateInformation?.companyInformation.name} - required - /> - )} + return ( + + + Edit Profile + + + Edit Profile + e.preventDefault()}> + + {user.type !== "corporate" ? ( + setName(e)} + placeholder="Enter your name" + defaultValue={name} + required + /> + ) : ( + + setCorporateInformation((prev) => ({ + ...prev!, + companyInformation: { + ...prev!.companyInformation, + name: e, + }, + })) + } + placeholder="Enter your company's name" + defaultValue={corporateInformation?.companyInformation.name} + required + /> + )} - {user.type === "agent" && ( - setArabName(e)} - placeholder="Enter your arab name" - defaultValue={arabName} - required - /> - )} + {user.type === "agent" && ( + setArabName(e)} + placeholder="Enter your arab name" + defaultValue={arabName} + required + /> + )} - setEmail(e)} - placeholder="Enter email address" - defaultValue={email} - required - /> - - - setPassword(e)} - placeholder="Enter your password" - required - /> - setNewPassword(e)} - placeholder="Enter your new password (optional)" - /> - - {user.type === "agent" && ( - - null} - placeholder="Enter your company's name" - defaultValue={companyName} - disabled - /> - null} - placeholder="Enter commercial registration" - defaultValue={commercialRegistration} - disabled - /> - - )} + setEmail(e)} + placeholder="Enter email address" + defaultValue={email} + required + /> + + + setPassword(e)} + placeholder="Enter your password" + required + /> + setNewPassword(e)} + placeholder="Enter your new password (optional)" + /> + + {user.type === "agent" && ( + + null} + placeholder="Enter your company's name" + defaultValue={companyName} + disabled + /> + null} + placeholder="Enter commercial registration" + defaultValue={commercialRegistration} + disabled + /> + + )} - - - - Country * - - - - setPhone(e)} - placeholder="Enter phone number" - defaultValue={phone} - required - /> - + + + Country * + + + setPhone(e)} + placeholder="Enter phone number" + defaultValue={phone} + required + /> + - {user.type === "student" ? ( - - setPassportID(e)} - placeholder="Enter National ID or Passport number" - value={passport_id} - required - /> - - - ) : ( - - )} + {user.type === "student" ? ( + + setPassportID(e)} + placeholder="Enter National ID or Passport number" + value={passport_id} + required + /> + + + ) : ( + + )} - + - {desiredLevels && - ["developer", "student"].includes(user.type) && ( - <> - - - Desired Levels - - - > - } - /> - - - - Focus - - - setFocus("academic")} - className={clsx( - "w-full border border-mti-gray-platinum rounded-full px-6 py-4 flex justify-center items-center gap-12 bg-white", - "hover:bg-mti-purple-light hover:text-white", - focus === "academic" && - "!bg-mti-purple-light !text-white", - "transition duration-300 ease-in-out" - )} - > - Academic - - setFocus("general")} - className={clsx( - "w-full border border-mti-gray-platinum rounded-full px-6 py-4 flex justify-center items-center gap-12 bg-white", - "hover:bg-mti-purple-light hover:text-white", - focus === "general" && - "!bg-mti-purple-light !text-white", - "transition duration-300 ease-in-out" - )} - > - General - - - - > - )} + {desiredLevels && ["developer", "student"].includes(user.type) && ( + <> + + Desired Levels + >} + /> + + + Focus + + setFocus("academic")} + className={clsx( + "w-full border border-mti-gray-platinum rounded-full px-6 py-4 flex justify-center items-center gap-12 bg-white", + "hover:bg-mti-purple-light hover:text-white", + focus === "academic" && "!bg-mti-purple-light !text-white", + "transition duration-300 ease-in-out", + )}> + Academic + + setFocus("general")} + className={clsx( + "w-full border border-mti-gray-platinum rounded-full px-6 py-4 flex justify-center items-center gap-12 bg-white", + "hover:bg-mti-purple-light hover:text-white", + focus === "general" && "!bg-mti-purple-light !text-white", + "transition duration-300 ease-in-out", + )}> + General + + + + > + )} - {preferredGender && - ["developer", "student"].includes(user.type) && ( - <> - - - - - Speaking Instructor's Gender - - - value - ? setPreferredGender( - value.value as InstructorGender - ) - : null - } - options={[ - { value: "male", label: "Male" }, - { value: "female", label: "Female" }, - { value: "varied", label: "Varied" }, - ]} - /> - - - - Preferred Topics{" "} - - - - - setIsPreferredTopicsOpen(true)} - > - Select Topics ({preferredTopics?.length || "All"}{" "} - selected) - - - + {preferredGender && ["developer", "student"].includes(user.type) && ( + <> + + + + Speaking Instructor's Gender + (value ? setPreferredGender(value.value as InstructorGender) : null)} + options={[ + {value: "male", label: "Male"}, + {value: "female", label: "Female"}, + {value: "varied", label: "Varied"}, + ]} + /> + + + + Preferred Topics{" "} + + + + + setIsPreferredTopicsOpen(true)}> + Select Topics ({preferredTopics?.length || "All"} selected) + + + - setIsPreferredTopicsOpen(false)} - selectTopics={setPreferredTopics} - initialTopics={preferredTopics || []} - /> + setIsPreferredTopicsOpen(false)} + selectTopics={setPreferredTopics} + initialTopics={preferredTopics || []} + /> - - > - )} + + > + )} - {user.type === "corporate" && ( - <> - - null} - label="Number of users" - defaultValue={ - user.corporateInformation.companyInformation.userAmount - } - disabled - required - /> - null} - label="Pricing" - defaultValue={`${user.corporateInformation.payment?.value} ${user.corporateInformation.payment?.currency}`} - disabled - required - /> - - - > - )} + {user.type === "corporate" && ( + <> + + null} + label="Number of users" + defaultValue={user.corporateInformation.companyInformation.userAmount} + disabled + required + /> + null} + label="Pricing" + defaultValue={`${user.corporateInformation.payment?.value} ${user.corporateInformation.payment?.currency}`} + disabled + required + /> + + + > + )} - {user.type === "corporate" && ( - <> - - - setName(e)} - placeholder="Enter your name" - defaultValue={name} - required - /> - - - > - )} + {user.type === "corporate" && ( + <> + + + setName(e)} + placeholder="Enter your name" + defaultValue={name} + required + /> + + + > + )} - {user.type === "corporate" && - user.corporateInformation.referralAgent && ( - <> - - - null} - defaultValue={ - users.find( - (x) => - x.id === user.corporateInformation.referralAgent - )?.name - } - type="text" - label="Country Manager's Name" - placeholder="Not available" - required - disabled - /> - null} - defaultValue={ - users.find( - (x) => - x.id === user.corporateInformation.referralAgent - )?.email - } - type="text" - label="Country Manager's E-mail" - placeholder="Not available" - required - disabled - /> - - - - - Country Manager's Country * - - - x.id === user.corporateInformation.referralAgent - )?.demographicInformation?.country - } - onChange={() => null} - disabled - /> - + {user.type === "corporate" && user.corporateInformation.referralAgent && ( + <> + + + null} + defaultValue={users.find((x) => x.id === user.corporateInformation.referralAgent)?.name} + type="text" + label="Country Manager's Name" + placeholder="Not available" + required + disabled + /> + null} + defaultValue={users.find((x) => x.id === user.corporateInformation.referralAgent)?.email} + type="text" + label="Country Manager's E-mail" + placeholder="Not available" + required + disabled + /> + + + + Country Manager's Country * + x.id === user.corporateInformation.referralAgent)?.demographicInformation + ?.country + } + onChange={() => null} + disabled + /> + - null} - placeholder="Not available" - defaultValue={ - users.find( - (x) => - x.id === user.corporateInformation.referralAgent - )?.demographicInformation?.phone - } - disabled - required - /> - - > - )} + null} + placeholder="Not available" + defaultValue={ + users.find((x) => x.id === user.corporateInformation.referralAgent)?.demographicInformation?.phone + } + disabled + required + /> + + > + )} - {user.type !== "corporate" && ( - - + {user.type !== "corporate" && ( + + - - - - - - )} - - - - (profilePictureInput.current as any)?.click()} - > - - - - - - - - (profilePictureInput.current as any)?.click()} - className="cursor-pointer text-mti-purple-light text-sm" - > - Change picture - - - {USER_TYPE_LABELS[user.type]} - - - {user.type === "agent" && ( - - - - )} - {manualDownloadLink && ( - - - Download Manual - - - )} - - - - Bio - setBio(e.target.value)} - defaultValue={bio} - placeholder="Write your text here..." - /> - + + + + + + )} + + + + (profilePictureInput.current as any)?.click()}> + + + + + + + + (profilePictureInput.current as any)?.click()} + className="cursor-pointer text-mti-purple-light text-sm"> + Change picture + + {USER_TYPE_LABELS[user.type]} + + {user.type === "agent" && ( + + + + )} + {manualDownloadLink && ( + + + Download Manual + + + )} + + + + Bio + setBio(e.target.value)} + defaultValue={bio} + placeholder="Write your text here..." + /> + - - - - Back - - - - Save Changes - - - - - ); + + + + Back + + + + Save Changes + + + + + ); } export default function Home() { - const { user, mutateUser } = useUser({ redirectTo: "/login" }); + const {user, mutateUser} = useUser({redirectTo: "/login"}); - return ( - <> - - Profile | EnCoach - - - - - - {user && } - > - ); + return ( + <> + + Profile | EnCoach + + + + + + {user && } + > + ); } diff --git a/src/pages/record.tsx b/src/pages/record.tsx index e6239244..0862052f 100644 --- a/src/pages/record.tsx +++ b/src/pages/record.tsx @@ -1,30 +1,29 @@ /* eslint-disable @next/next/no-img-element */ import Head from "next/head"; -import { withIronSessionSsr } from "iron-session/next"; -import { sessionOptions } from "@/lib/session"; -import { Stat, User } from "@/interfaces/user"; -import { useEffect, useRef, useState } from "react"; +import {withIronSessionSsr} from "iron-session/next"; +import {sessionOptions} from "@/lib/session"; +import {Stat, User} from "@/interfaces/user"; +import {useEffect, useRef, useState} from "react"; import useStats from "@/hooks/useStats"; -import { groupByDate } from "@/utils/stats"; +import {groupByDate} from "@/utils/stats"; import moment from "moment"; import useUsers from "@/hooks/useUsers"; import useExamStore from "@/stores/examStore"; -import { ToastContainer } from "react-toastify"; -import { useRouter } from "next/router"; +import {ToastContainer} from "react-toastify"; +import {useRouter} from "next/router"; import Layout from "@/components/High/Layout"; import clsx from "clsx"; import Select from "@/components/Low/Select"; import useGroups from "@/hooks/useGroups"; -import { shouldRedirectHome } from "@/utils/navigation.disabled"; +import {shouldRedirectHome} from "@/utils/navigation.disabled"; import useAssignments from "@/hooks/useAssignments"; -import { uuidv4 } from "@firebase/util"; -import { usePDFDownload } from "@/hooks/usePDFDownload"; +import {uuidv4} from "@firebase/util"; +import {usePDFDownload} from "@/hooks/usePDFDownload"; import useRecordStore from "@/stores/recordStore"; import useTrainingContentStore from "@/stores/trainingContentStore"; import StatsGridItem from "@/components/StatGridItem"; - -export const getServerSideProps = withIronSessionSsr(({ req, res }) => { +export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; if (!user || !user.isVerified) { @@ -46,7 +45,7 @@ export const getServerSideProps = withIronSessionSsr(({ req, res }) => { } return { - props: { user: req.session.user }, + props: {user: req.session.user}, }; }, sessionOptions); @@ -55,16 +54,21 @@ const defaultSelectableCorporate = { label: "All", }; -export default function History({ user }: { user: User }) { - const [statsUserId, setStatsUserId, training, setTraining] = useRecordStore((state) => [state.selectedUser, state.setSelectedUser, state.training, state.setTraining]); +export default function History({user}: {user: User}) { + const [statsUserId, setStatsUserId, training, setTraining] = useRecordStore((state) => [ + state.selectedUser, + state.setSelectedUser, + state.training, + state.setTraining, + ]); // const [statsUserId, setStatsUserId] = useState(user.id); - const [groupedStats, setGroupedStats] = useState<{ [key: string]: Stat[] }>(); + const [groupedStats, setGroupedStats] = useState<{[key: string]: Stat[]}>(); const [filter, setFilter] = useState<"months" | "weeks" | "days" | "assignments">(); - const { assignments } = useAssignments({}); + const {assignments} = useAssignments({}); - const { users } = useUsers(); - const { stats, isLoading: isStatsLoading } = useStats(statsUserId); - const { groups: allGroups } = useGroups(); + const {users} = useUsers(); + const {stats, isLoading: isStatsLoading} = useStats(statsUserId); + const {groups: allGroups} = useGroups({}); const groups = allGroups.filter((x) => x.admin === user.id); @@ -104,12 +108,12 @@ export default function History({ user }: { user: User }) { setFilter((prev) => (prev === value ? undefined : value)); }; - const filterStatsByDate = (stats: { [key: string]: Stat[] }) => { + const filterStatsByDate = (stats: {[key: string]: Stat[]}) => { if (filter && filter !== "assignments") { const filterDate = moment() - .subtract({ [filter as string]: 1 }) + .subtract({[filter as string]: 1}) .format("x"); - const filteredStats: { [key: string]: Stat[] } = {}; + const filteredStats: {[key: string]: Stat[]} = {}; Object.keys(stats).forEach((timestamp) => { if (timestamp >= filterDate) filteredStats[timestamp] = stats[timestamp]; @@ -118,7 +122,7 @@ export default function History({ user }: { user: User }) { } if (filter && filter === "assignments") { - const filteredStats: { [key: string]: Stat[] } = {}; + const filteredStats: {[key: string]: Stat[]} = {}; Object.keys(stats).forEach((timestamp) => { if (stats[timestamp].map((s) => s.assignment === undefined).includes(false)) @@ -137,13 +141,13 @@ export default function History({ user }: { user: User }) { useEffect(() => { const handleRouteChange = (url: string) => { - setTraining(false) - } - router.events.on('routeChangeStart', handleRouteChange) + setTraining(false); + }; + router.events.on("routeChangeStart", handleRouteChange); return () => { - router.events.off('routeChangeStart', handleRouteChange) - } - }, [router.events, setTraining]) + router.events.off("routeChangeStart", handleRouteChange); + }; + }, [router.events, setTraining]); const handleTrainingContentSubmission = () => { if (groupedStats) { @@ -156,11 +160,10 @@ export default function History({ user }: { user: User }) { } return accumulator; }, {}); - setTrainingStats(Object.values(selectedStats).flat()) + setTrainingStats(Object.values(selectedStats).flat()); router.push("/training"); } - } - + }; const customContent = (timestamp: string) => { if (!groupedStats) return <>>; @@ -240,13 +243,13 @@ export default function History({ user }: { user: User }) { const selectedUser = getSelectedUser(); const selectedUserSelectValue = selectedUser ? { - value: selectedUser.id, - label: `${selectedUser.name} - ${selectedUser.email}`, - } + value: selectedUser.id, + label: `${selectedUser.name} - ${selectedUser.email}`, + } : { - value: "", - label: "", - }; + value: "", + label: "", + }; return ( <> @@ -272,7 +275,7 @@ export default function History({ user }: { user: User }) { value={selectableCorporates.find((x) => x.value === selectedCorporate)} onChange={(value) => setSelectedCorporate(value?.value || "")} styles={{ - menuPortal: (base) => ({ ...base, zIndex: 9999 }), + menuPortal: (base) => ({...base, zIndex: 9999}), option: (styles, state) => ({ ...styles, backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", @@ -289,7 +292,7 @@ export default function History({ user }: { user: User }) { value={selectedUserSelectValue} onChange={(value) => setStatsUserId(value?.value!)} styles={{ - menuPortal: (base) => ({ ...base, zIndex: 9999 }), + menuPortal: (base) => ({...base, zIndex: 9999}), option: (styles, state) => ({ ...styles, backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", @@ -313,7 +316,7 @@ export default function History({ user }: { user: User }) { value={selectedUserSelectValue} onChange={(value) => setStatsUserId(value?.value!)} styles={{ - menuPortal: (base) => ({ ...base, zIndex: 9999 }), + menuPortal: (base) => ({...base, zIndex: 9999}), option: (styles, state) => ({ ...styles, backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", @@ -323,10 +326,12 @@ export default function History({ user }: { user: User }) { /> > )} - {(training && ( + {training && ( - Select up to 10 exercises - {`(${selectedTrainingExams.length}/${MAX_TRAINING_EXAMS})`} + + Select up to 10 exercises + {`(${selectedTrainingExams.length}/${MAX_TRAINING_EXAMS})`} + - ))} + )} { @@ -202,7 +202,7 @@ export default function Stats() { }} /> )} - {(["corporate", "teacher", "mastercorporate"].includes(user.type) ) && groups.length > 0 && ( + {["corporate", "teacher", "mastercorporate"].includes(user.type) && groups.length > 0 && ( { - const user = req.session.user; +export const getServerSideProps = withIronSessionSsr(({req, res}) => { + const user = req.session.user; - if (!user || !user.isVerified) { - return { - redirect: { - destination: "/login", - permanent: false, - }, - }; - } + if (!user || !user.isVerified) { + return { + redirect: { + destination: "/login", + permanent: false, + }, + }; + } - if (shouldRedirectHome(user)) { - return { - redirect: { - destination: "/", - permanent: false, - }, - }; - } + if (shouldRedirectHome(user)) { + return { + redirect: { + destination: "/", + permanent: false, + }, + }; + } - return { - props: { user: req.session.user }, - }; + return { + props: {user: req.session.user}, + }; }, sessionOptions); const defaultSelectableCorporate = { - value: "", - label: "All", + value: "", + label: "All", }; -const Training: React.FC<{ user: User }> = ({ user }) => { - // Record stuff - const { users } = useUsers(); - const [selectedCorporate, setSelectedCorporate] = useState(defaultSelectableCorporate.value); - const [statsUserId, setStatsUserId, setRecordTraining] = useRecordStore((state) => [state.selectedUser, state.setSelectedUser, state.setTraining]); - const { groups: allGroups } = useGroups(); - const groups = allGroups.filter((x) => x.admin === user.id); - const [filter, setFilter] = useState<"months" | "weeks" | "days">(); +const Training: React.FC<{user: User}> = ({user}) => { + // Record stuff + const {users} = useUsers(); + const [selectedCorporate, setSelectedCorporate] = useState(defaultSelectableCorporate.value); + const [statsUserId, setStatsUserId, setRecordTraining] = useRecordStore((state) => [ + state.selectedUser, + state.setSelectedUser, + state.setTraining, + ]); + const {groups: allGroups} = useGroups({}); + const groups = allGroups.filter((x) => x.admin === user.id); + const [filter, setFilter] = useState<"months" | "weeks" | "days">(); - const toggleFilter = (value: "months" | "weeks" | "days") => { - setFilter((prev) => (prev === value ? undefined : value)); - }; + const toggleFilter = (value: "months" | "weeks" | "days") => { + setFilter((prev) => (prev === value ? undefined : value)); + }; - const [stats, setTrainingStats] = useTrainingContentStore((state) => [state.stats, state.setStats]); - const [trainingContent, setTrainingContent] = useState([]); - const [isNewContentLoading, setIsNewContentLoading] = useState(stats.length != 0); - const [isLoading, setIsLoading] = useState(true); - const [groupedByTrainingContent, setGroupedByTrainingContent] = useState<{ [key: string]: ITrainingContent }>(); + const [stats, setTrainingStats] = useTrainingContentStore((state) => [state.stats, state.setStats]); + const [trainingContent, setTrainingContent] = useState([]); + const [isNewContentLoading, setIsNewContentLoading] = useState(stats.length != 0); + const [isLoading, setIsLoading] = useState(true); + const [groupedByTrainingContent, setGroupedByTrainingContent] = useState<{[key: string]: ITrainingContent}>(); - useEffect(() => { - const handleRouteChange = (url: string) => { - setTrainingStats([]) - } - router.events.on('routeChangeStart', handleRouteChange) - return () => { - router.events.off('routeChangeStart', handleRouteChange) - } - }, [router.events, setTrainingStats]) + useEffect(() => { + const handleRouteChange = (url: string) => { + setTrainingStats([]); + }; + router.events.on("routeChangeStart", handleRouteChange); + return () => { + router.events.off("routeChangeStart", handleRouteChange); + }; + }, [router.events, setTrainingStats]); - useEffect(() => { - const postStats = async () => { - try { - const response = await axios.post<{ id: string }>(`/api/training`, stats); - return response.data.id; - } catch (error) { - setIsNewContentLoading(false); - } - }; + useEffect(() => { + const postStats = async () => { + try { + const response = await axios.post<{id: string}>(`/api/training`, stats); + return response.data.id; + } catch (error) { + setIsNewContentLoading(false); + } + }; - if (isNewContentLoading) { - postStats().then(id => { - setTrainingStats([]); - if (id) { - router.push(`/training/${id}`) - } - }); - } - }, [isNewContentLoading]) + if (isNewContentLoading) { + postStats().then((id) => { + setTrainingStats([]); + if (id) { + router.push(`/training/${id}`); + } + }); + } + }, [isNewContentLoading]); - useEffect(() => { - const loadTrainingContent = async () => { - try { - const response = await axios.get('/api/training'); - setTrainingContent(response.data); - setIsLoading(false); - } catch (error) { - setTrainingContent([]); - setIsLoading(false); - } - }; - loadTrainingContent(); - }, []); + useEffect(() => { + const loadTrainingContent = async () => { + try { + const response = await axios.get("/api/training"); + setTrainingContent(response.data); + setIsLoading(false); + } catch (error) { + setTrainingContent([]); + setIsLoading(false); + } + }; + loadTrainingContent(); + }, []); - const handleNewTrainingContent = () => { - setRecordTraining(true); - router.push('/record') - } + const handleNewTrainingContent = () => { + setRecordTraining(true); + router.push("/record"); + }; + const filterTrainingContentByDate = (trainingContent: {[key: string]: ITrainingContent}) => { + if (filter) { + const filterDate = moment() + .subtract({[filter as string]: 1}) + .format("x"); + const filteredTrainingContent: {[key: string]: ITrainingContent} = {}; - const filterTrainingContentByDate = (trainingContent: { [key: string]: ITrainingContent }) => { - if (filter) { - const filterDate = moment() - .subtract({ [filter as string]: 1 }) - .format("x"); - const filteredTrainingContent: { [key: string]: ITrainingContent } = {}; + Object.keys(trainingContent).forEach((timestamp) => { + if (timestamp >= filterDate) filteredTrainingContent[timestamp] = trainingContent[timestamp]; + }); + return filteredTrainingContent; + } + return trainingContent; + }; - Object.keys(trainingContent).forEach((timestamp) => { - if (timestamp >= filterDate) filteredTrainingContent[timestamp] = trainingContent[timestamp]; - }); - return filteredTrainingContent; - } - return trainingContent; - }; + useEffect(() => { + if (trainingContent.length > 0) { + const grouped = trainingContent.reduce((acc, content) => { + acc[content.created_at] = content; + return acc; + }, {} as {[key: number]: ITrainingContent}); - useEffect(() => { - if (trainingContent.length > 0) { - const grouped = trainingContent.reduce((acc, content) => { - acc[content.created_at] = content; - return acc; - }, {} as { [key: number]: ITrainingContent }); + setGroupedByTrainingContent(grouped); + } + }, [trainingContent]); - setGroupedByTrainingContent(grouped); - } - }, [trainingContent]) + // Record Stuff + const selectableCorporates = [ + defaultSelectableCorporate, + ...users + .filter((x) => x.type === "corporate") + .map((x) => ({ + value: x.id, + label: `${x.name} - ${x.email}`, + })), + ]; + const getUsersList = (): User[] => { + if (selectedCorporate) { + // get groups for that corporate + const selectedCorporateGroups = allGroups.filter((x) => x.admin === selectedCorporate); - // Record Stuff - const selectableCorporates = [ - defaultSelectableCorporate, - ...users - .filter((x) => x.type === "corporate") - .map((x) => ({ - value: x.id, - label: `${x.name} - ${x.email}`, - })), - ]; + // get the teacher ids for that group + const selectedCorporateGroupsParticipants = selectedCorporateGroups.flatMap((x) => x.participants); - const getUsersList = (): User[] => { - if (selectedCorporate) { - // get groups for that corporate - const selectedCorporateGroups = allGroups.filter((x) => x.admin === selectedCorporate); + // // search for groups for these teachers + // const teacherGroups = allGroups.filter((x) => { + // return selectedCorporateGroupsParticipants.includes(x.admin); + // }); - // get the teacher ids for that group - const selectedCorporateGroupsParticipants = selectedCorporateGroups.flatMap((x) => x.participants); + // const usersList = [ + // ...selectedCorporateGroupsParticipants, + // ...teacherGroups.flatMap((x) => x.participants), + // ]; + const userListWithUsers = selectedCorporateGroupsParticipants.map((x) => users.find((y) => y.id === x)) as User[]; + return userListWithUsers.filter((x) => x); + } - // // search for groups for these teachers - // const teacherGroups = allGroups.filter((x) => { - // return selectedCorporateGroupsParticipants.includes(x.admin); - // }); + return users || []; + }; - // const usersList = [ - // ...selectedCorporateGroupsParticipants, - // ...teacherGroups.flatMap((x) => x.participants), - // ]; - const userListWithUsers = selectedCorporateGroupsParticipants.map((x) => users.find((y) => y.id === x)) as User[]; - return userListWithUsers.filter((x) => x); - } + const corporateFilteredUserList = getUsersList(); + const getSelectedUser = () => { + if (selectedCorporate) { + const userInCorporate = corporateFilteredUserList.find((x) => x.id === statsUserId); + return userInCorporate || corporateFilteredUserList[0]; + } - return users || []; - }; + return users.find((x) => x.id === statsUserId) || user; + }; - const corporateFilteredUserList = getUsersList(); - const getSelectedUser = () => { - if (selectedCorporate) { - const userInCorporate = corporateFilteredUserList.find((x) => x.id === statsUserId); - return userInCorporate || corporateFilteredUserList[0]; - } + const selectedUser = getSelectedUser(); + const selectedUserSelectValue = selectedUser + ? { + value: selectedUser.id, + label: `${selectedUser.name} - ${selectedUser.email}`, + } + : { + value: "", + label: "", + }; - return users.find((x) => x.id === statsUserId) || user; - }; + const formatTimestamp = (timestamp: string) => { + const date = moment(parseInt(timestamp)); + const formatter = "YYYY/MM/DD - HH:mm"; - const selectedUser = getSelectedUser(); - const selectedUserSelectValue = selectedUser - ? { - value: selectedUser.id, - label: `${selectedUser.name} - ${selectedUser.email}`, - } - : { - value: "", - label: "", - }; + return date.format(formatter); + }; - const formatTimestamp = (timestamp: string) => { - const date = moment(parseInt(timestamp)); - const formatter = "YYYY/MM/DD - HH:mm"; + const selectTrainingContent = (trainingContent: ITrainingContent) => { + router.push(`/training/${trainingContent.id}`); + }; - return date.format(formatter); - }; + const trainingContentContainer = (timestamp: string) => { + if (!groupedByTrainingContent) return <>>; + const trainingContent: ITrainingContent = groupedByTrainingContent[timestamp]; + const uniqueModules = [...new Set(trainingContent.exams.map((exam) => exam.module))]; - const selectTrainingContent = (trainingContent: ITrainingContent) => { - router.push(`/training/${trainingContent.id}`) - }; + return ( + <> + selectTrainingContent(trainingContent)} + role="button"> + + + {formatTimestamp(timestamp)} + + + + {uniqueModules.map((module) => ( + + ))} + + + + + + > + ); + }; + return ( + <> + + Training | EnCoach + + + + + - const trainingContentContainer = (timestamp: string) => { - if (!groupedByTrainingContent) return <>>; - const trainingContent: ITrainingContent = groupedByTrainingContent[timestamp]; - const uniqueModules = [...new Set(trainingContent.exams.map(exam => exam.module))]; + + {isNewContentLoading || isLoading ? ( + + + {isNewContentLoading && ( + Assessing your exams, please be patient... + )} + + ) : ( + <> + + + {(user.type === "developer" || user.type === "admin") && ( + <> + Corporate - return ( - <> - selectTrainingContent(trainingContent)} - role="button"> - - - {formatTimestamp(timestamp)} - - - - {uniqueModules.map((module) => ( - - ))} - - - - - - > - ); - }; + x.value === selectedCorporate)} + onChange={(value) => setSelectedCorporate(value?.value || "")} + styles={{ + menuPortal: (base) => ({...base, zIndex: 9999}), + option: (styles, state) => ({ + ...styles, + backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", + color: state.isFocused ? "black" : styles.color, + }), + }}> + User - return ( - <> - - Training | EnCoach - - - - - + ({ + value: x.id, + label: `${x.name} - ${x.email}`, + }))} + value={selectedUserSelectValue} + onChange={(value) => setStatsUserId(value?.value!)} + styles={{ + menuPortal: (base) => ({...base, zIndex: 9999}), + option: (styles, state) => ({ + ...styles, + backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", + color: state.isFocused ? "black" : styles.color, + }), + }} + /> + > + )} + {(user.type === "corporate" || user.type === "teacher") && groups.length > 0 && ( + <> + User - - {(isNewContentLoading || isLoading ? ( - - - {isNewContentLoading && ( - Assessing your exams, please be patient... - )} - - ) : ( - <> - - - {(user.type === "developer" || user.type === "admin") && ( - <> - Corporate - - x.value === selectedCorporate)} - onChange={(value) => setSelectedCorporate(value?.value || "")} - styles={{ - menuPortal: (base) => ({ ...base, zIndex: 9999 }), - option: (styles, state) => ({ - ...styles, - backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", - color: state.isFocused ? "black" : styles.color, - }), - }}> - User - - ({ - value: x.id, - label: `${x.name} - ${x.email}`, - }))} - value={selectedUserSelectValue} - onChange={(value) => setStatsUserId(value?.value!)} - styles={{ - menuPortal: (base) => ({ ...base, zIndex: 9999 }), - option: (styles, state) => ({ - ...styles, - backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", - color: state.isFocused ? "black" : styles.color, - }), - }} - /> - > - )} - {(user.type === "corporate" || user.type === "teacher") && groups.length > 0 && ( - <> - User - - groups.flatMap((y) => y.participants).includes(x.id)) - .map((x) => ({ - value: x.id, - label: `${x.name} - ${x.email}`, - }))} - value={selectedUserSelectValue} - onChange={(value) => setStatsUserId(value?.value!)} - styles={{ - menuPortal: (base) => ({ ...base, zIndex: 9999 }), - option: (styles, state) => ({ - ...styles, - backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", - color: state.isFocused ? "black" : styles.color, - }), - }} - /> - > - )} - {(user.type === "student" && ( - <> - - Generate New Training Material - - - - - > - ))} - - - toggleFilter("months")}> - Last month - - toggleFilter("weeks")}> - Last week - - toggleFilter("days")}> - Last day - - - - {trainingContent.length == 0 && ( - - No training content to display... - - )} - {groupedByTrainingContent && Object.keys(groupedByTrainingContent).length > 0 && ( - - {Object.keys(filterTrainingContentByDate(groupedByTrainingContent)) - .sort((a, b) => parseInt(b) - parseInt(a)) - .map(trainingContentContainer)} - - )} - > - ))} - - > - ); -} + groups.flatMap((y) => y.participants).includes(x.id)) + .map((x) => ({ + value: x.id, + label: `${x.name} - ${x.email}`, + }))} + value={selectedUserSelectValue} + onChange={(value) => setStatsUserId(value?.value!)} + styles={{ + menuPortal: (base) => ({...base, zIndex: 9999}), + option: (styles, state) => ({ + ...styles, + backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", + color: state.isFocused ? "black" : styles.color, + }), + }} + /> + > + )} + {user.type === "student" && ( + <> + + Generate New Training Material + + + + + > + )} + + + toggleFilter("months")}> + Last month + + toggleFilter("weeks")}> + Last week + + toggleFilter("days")}> + Last day + + + + {trainingContent.length == 0 && ( + + No training content to display... + + )} + {groupedByTrainingContent && Object.keys(groupedByTrainingContent).length > 0 && ( + + {Object.keys(filterTrainingContentByDate(groupedByTrainingContent)) + .sort((a, b) => parseInt(b) - parseInt(a)) + .map(trainingContentContainer)} + + )} + > + )} + + > + ); +}; export default Training;