diff --git a/src/dashboards/Corporate.tsx b/src/dashboards/Corporate.tsx index 481f12e1..fa961a46 100644 --- a/src/dashboards/Corporate.tsx +++ b/src/dashboards/Corporate.tsx @@ -2,7 +2,7 @@ import Modal from "@/components/Modal"; import useFilterRecordsByUser from "@/hooks/useFilterRecordsByUser"; import useUsers from "@/hooks/useUsers"; -import {CorporateUser, Group, Stat, User} from "@/interfaces/user"; +import {CorporateUser, Group, MasterCorporateUser, Stat, User} from "@/interfaces/user"; import UserList from "@/pages/(admin)/Lists/UserList"; import {dateSorter} from "@/utils"; import moment from "moment"; @@ -54,6 +54,7 @@ import useUserBalance from "@/hooks/useUserBalance"; interface Props { user: CorporateUser; + linkedCorporate?: CorporateUser | MasterCorporateUser; } type StudentPerformanceItem = User & {corporateName: string; group: string}; @@ -154,11 +155,10 @@ const StudentPerformanceList = ({items, stats, users}: {items: StudentPerformanc ); }; -export default function CorporateDashboard({user}: Props) { +export default function CorporateDashboard({user, linkedCorporate}: Props) { const [page, setPage] = useState(""); const [selectedUser, setSelectedUser] = useState(); const [showModal, setShowModal] = useState(false); - const [corporateUserToShow, setCorporateUserToShow] = useState(); const [selectedAssignment, setSelectedAssignment] = useState(); const [isCreatingAssignment, setIsCreatingAssignment] = useState(false); @@ -193,11 +193,6 @@ export default function CorporateDashboard({user}: Props) { setShowModal(!!selectedUser && page === ""); }, [selectedUser, page]); - useEffect(() => { - // in this case it fetches the master corporate account - getUserCorporate(user.id).then(setCorporateUserToShow); - }, [user]); - const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(user.id); const teacherFilter = (user: User) => user.type === "teacher" && groups.flatMap((g) => g.participants).includes(user.id); @@ -455,9 +450,9 @@ export default function CorporateDashboard({user}: Props) { const DefaultDashboard = () => ( <> - {corporateUserToShow && ( + {!!linkedCorporate && (
- Linked to: {corporateUserToShow?.corporateInformation?.companyInformation.name || corporateUserToShow.name} + Linked to: {linkedCorporate?.corporateInformation?.companyInformation.name || linkedCorporate.name}
)}
diff --git a/src/dashboards/Student.tsx b/src/dashboards/Student.tsx index 5fd2a862..805a2d3b 100644 --- a/src/dashboards/Student.tsx +++ b/src/dashboards/Student.tsx @@ -9,7 +9,7 @@ import useFilterRecordsByUser from "@/hooks/useFilterRecordsByUser"; import useUsers from "@/hooks/useUsers"; import {Invite} from "@/interfaces/invite"; import {Assignment} from "@/interfaces/results"; -import {CorporateUser, Stat, User} from "@/interfaces/user"; +import {CorporateUser, MasterCorporateUser, Stat, User} from "@/interfaces/user"; import useExamStore from "@/stores/examStore"; import {getExamById} from "@/utils/exams"; import {getUserCorporate} from "@/utils/groups"; @@ -30,11 +30,10 @@ import {toast} from "react-toastify"; interface Props { user: User; + linkedCorporate?: CorporateUser | MasterCorporateUser; } -export default function StudentDashboard({user}: Props) { - const [corporateUserToShow, setCorporateUserToShow] = useState(); - +export default function StudentDashboard({user, linkedCorporate}: Props) { const {users} = useUsers(); const {gradingSystem} = useGradingSystem(); const {data: stats} = useFilterRecordsByUser(user.id, !user?.id); @@ -49,10 +48,6 @@ export default function StudentDashboard({user}: Props) { const setSelectedModules = useExamStore((state) => state.setSelectedModules); const setAssignment = useExamStore((state) => state.setAssignment); - useEffect(() => { - getUserCorporate(user.id).then(setCorporateUserToShow); - }, [user]); - const startAssignment = (assignment: Assignment) => { const examPromises = assignment.exams.filter((e) => e.assignee === user.id).map((e) => getExamById(e.module, e.id)); @@ -76,9 +71,9 @@ export default function StudentDashboard({user}: Props) { return ( <> - {corporateUserToShow && ( + {linkedCorporate && (
- Linked to: {corporateUserToShow?.corporateInformation?.companyInformation.name || corporateUserToShow.name} + Linked to: {linkedCorporate?.corporateInformation?.companyInformation.name || linkedCorporate.name}
)} (); const [showModal, setShowModal] = useState(false); const [selectedAssignment, setSelectedAssignment] = useState(); const [isCreatingAssignment, setIsCreatingAssignment] = useState(false); - const [corporateUserToShow, setCorporateUserToShow] = useState(); const {data: stats} = useFilterRecordsByUser(); const {users, reload} = useUsers(); @@ -89,10 +89,6 @@ export default function TeacherDashboard({user}: Props) { setShowModal(!!selectedUser && page === ""); }, [selectedUser, page]); - useEffect(() => { - getUserCorporate(user.id).then(setCorporateUserToShow); - }, [user]); - const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(user.id); const getStatsByStudent = (user: User) => stats.filter((s) => s.user === user.id); @@ -290,15 +286,15 @@ export default function TeacherDashboard({user}: Props) { const DefaultDashboard = () => ( <> - {corporateUserToShow && ( + {linkedCorporate && (
- Linked to: {corporateUserToShow?.corporateInformation?.companyInformation.name || corporateUserToShow.name} + Linked to: {linkedCorporate?.corporateInformation?.companyInformation.name || linkedCorporate.name}
)}
setPage("students")} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index b0f02074..eb1abe6c 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,32 +1,24 @@ /* 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 { averageScore, groupBySession, totalExams } from "@/utils/stats"; +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 {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 {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 {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 {MODULE_ARRAY} from "@/utils/moduleUtils"; import ProfileSummary from "@/components/ProfileSummary"; import StudentDashboard from "@/dashboards/Student"; import AdminDashboard from "@/dashboards/Admin"; @@ -35,209 +27,184 @@ 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, - userTypes, -} from "@/interfaces/user"; +import {useRouter} from "next/router"; +import {PayPalScriptProvider} from "@paypal/react-paypal-js"; +import {CorporateUser, MasterCorporateUser, Type, userTypes} from "@/interfaces/user"; import Select from "react-select"; -import { USER_TYPE_LABELS } from "@/resources/user"; -import { checkAccess, getTypesOfUser } from "@/utils/permissions"; +import {USER_TYPE_LABELS} from "@/resources/user"; +import {checkAccess, getTypesOfUser} from "@/utils/permissions"; +import {getUserCorporate} from "@/utils/groups.be"; -export const getServerSideProps = withIronSessionSsr(({ req, res }) => { - const user = req.session.user; +export const getServerSideProps = withIronSessionSsr(async ({req, res}) => { + const user = req.session.user; - const envVariables: { [key: string]: string } = {}; - Object.keys(process.env) - .filter((x) => x.startsWith("NEXT_PUBLIC")) - .forEach((x: string) => { - envVariables[x] = process.env[x]!; - }); + const envVariables: {[key: string]: string} = {}; + Object.keys(process.env) + .filter((x) => x.startsWith("NEXT_PUBLIC")) + .forEach((x: string) => { + envVariables[x] = process.env[x]!; + }); - if (!user || !user.isVerified) { - return { - redirect: { - destination: "/login", - permanent: false, - }, - }; - } + if (!user || !user.isVerified) { + return { + redirect: { + destination: "/login", + permanent: false, + }, + }; + } - return { - props: { user: req.session.user, envVariables }, - }; + const linkedCorporate = await getUserCorporate(user.id); + + return { + props: {user, envVariables, linkedCorporate}, + }; }, sessionOptions); interface Props { - user: any; - envVariables: { [key: string]: string }; + user: any; + envVariables: {[key: string]: string}; + linkedCorporate?: CorporateUser | MasterCorporateUser; } -export default function Home(props: Props) { - const { envVariables } = props; - const [showDiagnostics, setShowDiagnostics] = useState(false); - const [showDemographicInput, setShowDemographicInput] = useState(false); - const [selectedScreen, setSelectedScreen] = useState("admin"); - const { user, mutateUser } = useUser({ redirectTo: "/login" }); - const router = useRouter(); +export default function Home({linkedCorporate}: Props) { + const [showDiagnostics, setShowDiagnostics] = useState(false); + const [showDemographicInput, setShowDemographicInput] = useState(false); + const [selectedScreen, setSelectedScreen] = useState("admin"); - useEffect(() => { - if (user) { - setShowDemographicInput( - !user.demographicInformation || - !user.demographicInformation.country || - !user.demographicInformation.gender || - !user.demographicInformation.phone - ); - setShowDiagnostics(user.isFirstLogin && user.type === "student"); - } - }, [user]); + const {user, mutateUser} = useUser({redirectTo: "/login"}); + const router = useRouter(); - const checkIfUserExpired = () => { - const expirationDate = user!.subscriptionExpirationDate; + useEffect(() => { + if (user) { + setShowDemographicInput( + !user.demographicInformation || + !user.demographicInformation.country || + !user.demographicInformation.gender || + !user.demographicInformation.phone, + ); + setShowDiagnostics(user.isFirstLogin && user.type === "student"); + } + }, [user]); - if (expirationDate === null || expirationDate === undefined) return false; - if (moment(expirationDate).isAfter(moment(new Date()))) return false; + const checkIfUserExpired = () => { + const expirationDate = user!.subscriptionExpirationDate; - return true; - }; + if (expirationDate === null || expirationDate === undefined) return false; + if (moment(expirationDate).isAfter(moment(new Date()))) return false; - if ( - user && - (user.status === "paymentDue" || - user.status === "disabled" || - checkIfUserExpired()) - ) { - return ( - <> - - EnCoach - - - - - {user.status === "disabled" && ( - -
- - Your account has been disabled! - - - Please contact an administrator if you believe this to be a - mistake. - -
-
- )} - {(user.status === "paymentDue" || checkIfUserExpired()) && ( - - )} - - ); - } + return true; + }; - if (user && showDemographicInput) { - return ( - <> - - EnCoach - - - - - - - - - ); - } + if (user && (user.status === "paymentDue" || user.status === "disabled" || checkIfUserExpired())) { + return ( + <> + + EnCoach + + + + + {user.status === "disabled" && ( + +
+ Your account has been disabled! + Please contact an administrator if you believe this to be a mistake. +
+
+ )} + {(user.status === "paymentDue" || checkIfUserExpired()) && } + + ); + } - if (user && showDiagnostics) { - return ( - <> - - EnCoach - - - - - - setShowDiagnostics(false)} /> - - - ); - } + if (user && showDemographicInput) { + return ( + <> + + EnCoach + + + + + + + + + ); + } - return ( - <> - - EnCoach - - - - - - {user && ( - - {checkAccess(user, ["student"]) && } - {checkAccess(user, ["teacher"]) && } - {checkAccess(user, ["corporate"]) && ( - - )} - {checkAccess(user, ["mastercorporate"]) && ( - - )} - {checkAccess(user, ["agent"]) && } - {checkAccess(user, ["admin"]) && } - {checkAccess(user, ["developer"]) && ( - <> - ({ + value: u, + label: USER_TYPE_LABELS[u], + }))} + value={{ + value: selectedScreen, + label: USER_TYPE_LABELS[selectedScreen], + }} + onChange={(value) => (value ? setSelectedScreen(value.value) : setSelectedScreen("admin"))} + /> + + {selectedScreen === "student" && } + {selectedScreen === "teacher" && } + {selectedScreen === "corporate" && ( + + )} + {selectedScreen === "mastercorporate" && } + {selectedScreen === "agent" && } + {selectedScreen === "admin" && } + + )} + + )} + + ); } diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index 40e8b68b..08db7dd7 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -12,7 +12,7 @@ import Link from "next/link"; import axios from "axios"; 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, MasterCorporateUser} from "@/interfaces/user"; import CountrySelect from "@/components/Low/CountrySelect"; import {shouldRedirectHome} from "@/utils/navigation.disabled"; import moment from "moment"; @@ -34,8 +34,10 @@ import {capitalize} from "lodash"; import TopicModal from "@/components/Medium/TopicModal"; import {v4} from "uuid"; import {checkAccess, getTypesOfUser} from "@/utils/permissions"; +import {getUserCorporate} from "@/utils/groups.be"; +import {InferGetServerSidePropsType} from "next"; -export const getServerSideProps = withIronSessionSsr(({req, res}) => { +export const getServerSideProps = withIronSessionSsr(async ({req, res}) => { const user = req.session.user; if (!user || !user.isVerified) { @@ -57,18 +59,19 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => { } return { - props: {user: req.session.user}, + props: {user, linkedCorporate: await getUserCorporate(user.id)}, }; }, sessionOptions); interface Props { user: User; mutateUser: Function; + linkedCorporate?: CorporateUser | MasterCorporateUser; } const DoubleColumnRow = ({children}: {children: ReactNode}) =>
{children}
; -function UserProfile({user, mutateUser}: Props) { +function UserProfile({user, mutateUser, linkedCorporate}: Props) { const [bio, setBio] = useState(user.bio || ""); const [name, setName] = useState(user.name || ""); const [email, setEmail] = useState(user.email || ""); @@ -245,7 +248,7 @@ function UserProfile({user, mutateUser}: Props) {

Edit Profile

e.preventDefault()}> - {user.type !== "corporate" ? ( + {user.type !== "corporate" && user.type !== "mastercorporate" ? ( setCorporateInformation((prev) => ({ ...prev!, @@ -502,6 +506,7 @@ function UserProfile({user, mutateUser}: Props) { label="Department" placeholder="CEO, Head of Marketing..." required + disabled={!!linkedCorporate} /> @@ -638,7 +643,7 @@ function UserProfile({user, mutateUser}: Props) { ); } -export default function Home() { +export default function Home({linkedCorporate}: {linkedCorporate?: CorporateUser | MasterCorporateUser}) { const {user, mutateUser} = useUser({redirectTo: "/login"}); return ( @@ -653,7 +658,7 @@ export default function Home() { - {user && } + {user && } ); } diff --git a/src/utils/groups.be.ts b/src/utils/groups.be.ts index 99929752..27ef4736 100644 --- a/src/utils/groups.be.ts +++ b/src/utils/groups.be.ts @@ -1,5 +1,5 @@ import {app} from "@/firebase"; -import {CorporateUser, Group, StudentUser, TeacherUser} from "@/interfaces/user"; +import {CorporateUser, Group, MasterCorporateUser, StudentUser, TeacherUser} from "@/interfaces/user"; import {collection, doc, getDoc, getDocs, getFirestore, query, setDoc, where} from "firebase/firestore"; import moment from "moment"; import {getUser} from "./users.be"; @@ -35,14 +35,14 @@ export const updateExpiryDateOnGroup = async (participantID: string, corporateID export const getUserCorporate = async (id: string) => { const user = await getUser(id); - if (user.type === "corporate" || user.type === "mastercorporate") return user; + if (user.type === "mastercorporate") return user; const groups = await getParticipantGroups(id); const admins = await Promise.all(groups.map((x) => x.admin).map(getUser)); - const corporates = admins.filter((x) => x.type === "corporate"); + const corporates = admins.filter((x) => x.type === "corporate" || x.type === "mastercorporate"); if (corporates.length === 0) return undefined; - return corporates.shift() as CorporateUser; + return corporates.shift() as CorporateUser | MasterCorporateUser; }; export const getGroups = async () => {