diff --git a/src/components/Exercises/MultipleChoice.tsx b/src/components/Exercises/MultipleChoice.tsx index d29eab9d..ebaaf856 100644 --- a/src/components/Exercises/MultipleChoice.tsx +++ b/src/components/Exercises/MultipleChoice.tsx @@ -16,9 +16,13 @@ function Question({ }: MultipleChoiceQuestion & {userSolution: string | undefined; onSelectOption?: (option: string) => void; showSolution?: boolean}) { return (
- - {id} - {prompt} - + {isNaN(Number(id)) ? ( + {prompt} + ) : ( + + {id} - {prompt} + + )}
{variant === "image" && options.map((option) => ( diff --git a/src/components/Solutions/MultipleChoice.tsx b/src/components/Solutions/MultipleChoice.tsx index 4d2b8e61..ecbf0025 100644 --- a/src/components/Solutions/MultipleChoice.tsx +++ b/src/components/Solutions/MultipleChoice.tsx @@ -27,9 +27,13 @@ function Question({ return (
- - {id} - {prompt} - + {isNaN(Number(id)) ? ( + {prompt} + ) : ( + + {id} - {prompt} + + )}
{variant === "image" && options.map((option) => ( diff --git a/src/pages/(exam)/ExamPage.tsx b/src/pages/(exam)/ExamPage.tsx index 99b102c4..d583284b 100644 --- a/src/pages/(exam)/ExamPage.tsx +++ b/src/pages/(exam)/ExamPage.tsx @@ -1,6 +1,6 @@ /* eslint-disable @next/next/no-img-element */ -import { Module } from "@/interfaces"; -import { useEffect, useState } from "react"; +import {Module} from "@/interfaces"; +import {useEffect, useState} from "react"; import AbandonPopup from "@/components/AbandonPopup"; import Layout from "@/components/High/Layout"; @@ -12,567 +12,447 @@ import Selection from "@/exams/Selection"; import Speaking from "@/exams/Speaking"; import Writing from "@/exams/Writing"; import useUser from "@/hooks/useUser"; -import { Exam, UserSolution, Variant } from "@/interfaces/exam"; -import { Stat } from "@/interfaces/user"; +import {Exam, UserSolution, Variant} from "@/interfaces/exam"; +import {Stat} from "@/interfaces/user"; import useExamStore from "@/stores/examStore"; -import { - evaluateSpeakingAnswer, - evaluateWritingAnswer, -} from "@/utils/evaluation"; -import { defaultExamUserSolutions, getExam } from "@/utils/exams"; +import {evaluateSpeakingAnswer, evaluateWritingAnswer} from "@/utils/evaluation"; +import {defaultExamUserSolutions, getExam} from "@/utils/exams"; import axios from "axios"; -import { useRouter } from "next/router"; -import { toast, ToastContainer } from "react-toastify"; -import { v4 as uuidv4 } from "uuid"; +import {useRouter} from "next/router"; +import {toast, ToastContainer} from "react-toastify"; +import {v4 as uuidv4} from "uuid"; import useSessions from "@/hooks/useSessions"; import ShortUniqueId from "short-unique-id"; interface Props { - page: "exams" | "exercises"; + page: "exams" | "exercises"; } -export default function ExamPage({ page }: Props) { - const [variant, setVariant] = useState("full"); - const [avoidRepeated, setAvoidRepeated] = useState(false); - const [hasBeenUploaded, setHasBeenUploaded] = useState(false); - const [showAbandonPopup, setShowAbandonPopup] = useState(false); - const [isEvaluationLoading, setIsEvaluationLoading] = useState(false); - const [statsAwaitingEvaluation, setStatsAwaitingEvaluation] = useState< - string[] - >([]); - const [timeSpent, setTimeSpent] = useState(0); +export default function ExamPage({page}: Props) { + const [variant, setVariant] = useState("full"); + const [avoidRepeated, setAvoidRepeated] = useState(false); + const [hasBeenUploaded, setHasBeenUploaded] = useState(false); + const [showAbandonPopup, setShowAbandonPopup] = useState(false); + const [isEvaluationLoading, setIsEvaluationLoading] = useState(false); + const [statsAwaitingEvaluation, setStatsAwaitingEvaluation] = useState([]); + const [timeSpent, setTimeSpent] = useState(0); - const resetStore = useExamStore((state) => state.reset); - const assignment = useExamStore((state) => state.assignment); - const initialTimeSpent = useExamStore((state) => state.timeSpent); + const resetStore = useExamStore((state) => state.reset); + const assignment = useExamStore((state) => state.assignment); + const initialTimeSpent = useExamStore((state) => state.timeSpent); - const examStore = useExamStore; + const examStore = useExamStore; - const { exam, setExam } = useExamStore((state) => state); - const { exams, setExams } = useExamStore((state) => state); - const { sessionId, setSessionId } = useExamStore((state) => state); - const { partIndex, setPartIndex } = useExamStore((state) => state); - const { moduleIndex, setModuleIndex } = useExamStore((state) => state); - const { questionIndex, setQuestionIndex } = useExamStore((state) => state); - const { exerciseIndex, setExerciseIndex } = useExamStore((state) => state); - const { userSolutions, setUserSolutions } = useExamStore((state) => state); - const { showSolutions, setShowSolutions } = useExamStore((state) => state); - const { selectedModules, setSelectedModules } = useExamStore( - (state) => state, - ); + const {exam, setExam} = useExamStore((state) => state); + const {exams, setExams} = useExamStore((state) => state); + const {sessionId, setSessionId} = useExamStore((state) => state); + const {partIndex, setPartIndex} = useExamStore((state) => state); + const {moduleIndex, setModuleIndex} = useExamStore((state) => state); + const {questionIndex, setQuestionIndex} = useExamStore((state) => state); + const {exerciseIndex, setExerciseIndex} = useExamStore((state) => state); + const {userSolutions, setUserSolutions} = useExamStore((state) => state); + const {showSolutions, setShowSolutions} = useExamStore((state) => state); + const {selectedModules, setSelectedModules} = useExamStore((state) => state); - const { user } = useUser({ redirectTo: "/login" }); - const router = useRouter(); + const {user} = useUser({redirectTo: "/login"}); + const router = useRouter(); - const reset = () => { - resetStore(); - setVariant("full"); - setAvoidRepeated(false); - setHasBeenUploaded(false); - setShowAbandonPopup(false); - setIsEvaluationLoading(false); - setStatsAwaitingEvaluation([]); - setTimeSpent(0); - }; + const reset = () => { + resetStore(); + setVariant("full"); + setAvoidRepeated(false); + setHasBeenUploaded(false); + setShowAbandonPopup(false); + setIsEvaluationLoading(false); + setStatsAwaitingEvaluation([]); + setTimeSpent(0); + }; - // eslint-disable-next-line react-hooks/exhaustive-deps - const saveSession = async () => { - console.log("Saving your session..."); + // eslint-disable-next-line react-hooks/exhaustive-deps + const saveSession = async () => { + console.log("Saving your session..."); - await axios.post("/api/sessions", { - id: sessionId, - sessionId, - date: new Date().toISOString(), - userSolutions, - moduleIndex, - selectedModules, - assignment, - timeSpent, - exams, - exam, - partIndex, - exerciseIndex, - questionIndex, - user: user?.id, - }); - }; + await axios.post("/api/sessions", { + id: sessionId, + sessionId, + date: new Date().toISOString(), + userSolutions, + moduleIndex, + selectedModules, + assignment, + timeSpent, + exams, + exam, + partIndex, + exerciseIndex, + questionIndex, + user: user?.id, + }); + }; - useEffect( - () => setTimeSpent((prev) => prev + initialTimeSpent), - [initialTimeSpent], - ); + useEffect(() => setTimeSpent((prev) => prev + initialTimeSpent), [initialTimeSpent]); - useEffect(() => { - if (userSolutions.length === 0 && exams.length > 0) { - const defaultSolutions = exams.map(defaultExamUserSolutions).flat(); - setUserSolutions(defaultSolutions); - } - }, [exams, setUserSolutions, userSolutions]); + useEffect(() => { + if (userSolutions.length === 0 && exams.length > 0) { + const defaultSolutions = exams.map(defaultExamUserSolutions).flat(); + setUserSolutions(defaultSolutions); + } + }, [exams, setUserSolutions, userSolutions]); - useEffect(() => { - if ( - sessionId.length > 0 && - userSolutions.length > 0 && - selectedModules.length > 0 && - exams.length > 0 && - !!exam && - timeSpent > 0 && - !showSolutions && - moduleIndex < selectedModules.length - ) - saveSession(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - assignment, - exam, - exams, - moduleIndex, - selectedModules, - sessionId, - userSolutions, - user, - exerciseIndex, - partIndex, - questionIndex, - ]); + useEffect(() => { + if ( + sessionId.length > 0 && + userSolutions.length > 0 && + selectedModules.length > 0 && + exams.length > 0 && + !!exam && + timeSpent > 0 && + !showSolutions && + moduleIndex < selectedModules.length + ) + saveSession(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [assignment, exam, exams, moduleIndex, selectedModules, sessionId, userSolutions, user, exerciseIndex, partIndex, questionIndex]); - useEffect(() => { - if ( - timeSpent % 20 === 0 && - timeSpent > 0 && - moduleIndex < selectedModules.length && - !showSolutions - ) - saveSession(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [timeSpent]); + useEffect(() => { + if (timeSpent % 20 === 0 && timeSpent > 0 && moduleIndex < selectedModules.length && !showSolutions) saveSession(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [timeSpent]); - useEffect(() => { - if (selectedModules.length > 0 && sessionId.length === 0) { - const shortUID = new ShortUniqueId(); - setSessionId(shortUID.randomUUID(8)); - } - }, [setSessionId, selectedModules, sessionId]); + useEffect(() => { + if (selectedModules.length > 0 && sessionId.length === 0) { + const shortUID = new ShortUniqueId(); + setSessionId(shortUID.randomUUID(8)); + } + }, [setSessionId, selectedModules, sessionId]); - useEffect(() => { - if (user?.type === "developer") console.log(exam); - }, [exam, user]); + useEffect(() => { + if (user?.type === "developer") console.log(exam); + }, [exam, user]); - useEffect(() => { - if (selectedModules.length > 0 && timeSpent === 0 && !showSolutions) { - const timerInterval = setInterval(() => { - setTimeSpent((prev) => prev + 1); - }, 1000); + useEffect(() => { + if (selectedModules.length > 0 && timeSpent === 0 && !showSolutions) { + const timerInterval = setInterval(() => { + setTimeSpent((prev) => prev + 1); + }, 1000); - return () => { - clearInterval(timerInterval); - }; - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedModules.length]); + return () => { + clearInterval(timerInterval); + }; + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedModules.length]); - useEffect(() => { - if (showSolutions) setModuleIndex(-1); - }, [setModuleIndex, showSolutions]); + useEffect(() => { + if (showSolutions) setModuleIndex(-1); + }, [setModuleIndex, showSolutions]); - useEffect(() => { - (async () => { - if ( - selectedModules.length > 0 && - exams.length > 0 && - moduleIndex < selectedModules.length - ) { - const nextExam = exams[moduleIndex]; + useEffect(() => { + (async () => { + if (selectedModules.length > 0 && exams.length > 0 && moduleIndex < selectedModules.length) { + const nextExam = exams[moduleIndex]; - if (partIndex === -1 && nextExam.module !== "listening") - setPartIndex(0); - if ( - exerciseIndex === -1 && - !["reading", "listening"].includes(nextExam?.module) - ) - setExerciseIndex(0); - setExam(nextExam ? updateExamWithUserSolutions(nextExam) : undefined); - } - })(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedModules, moduleIndex, exams]); + if (partIndex === -1 && nextExam.module !== "listening") setPartIndex(0); + if (exerciseIndex === -1 && !["reading", "listening"].includes(nextExam?.module)) setExerciseIndex(0); + setExam(nextExam ? updateExamWithUserSolutions(nextExam) : undefined); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedModules, moduleIndex, exams]); - useEffect(() => { - (async () => { - if (selectedModules.length > 0 && exams.length === 0) { - const examPromises = selectedModules.map((module) => - getExam( - module, - avoidRepeated, - variant, - user?.type === "student" || user?.type === "developer" - ? user.preferredGender - : undefined, - ), - ); - Promise.all(examPromises).then((values) => { - if (values.every((x) => !!x)) { - setExams(values.map((x) => x!)); - } else { - toast.error("Something went wrong, please try again"); - setTimeout(router.reload, 500); - } - }); - } - })(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedModules, setExams, exams]); + useEffect(() => { + (async () => { + if (selectedModules.length > 0 && exams.length === 0) { + const examPromises = selectedModules.map((module) => + getExam( + module, + avoidRepeated, + variant, + user?.type === "student" || user?.type === "developer" ? user.preferredGender : undefined, + ), + ); + Promise.all(examPromises).then((values) => { + if (values.every((x) => !!x)) { + setExams(values.map((x) => x!)); + } else { + toast.error("Something went wrong, please try again"); + setTimeout(router.reload, 500); + } + }); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedModules, setExams, exams]); - useEffect(() => { - if ( - selectedModules.length > 0 && - exams.length !== 0 && - moduleIndex >= selectedModules.length && - !hasBeenUploaded && - !showSolutions - ) { - const newStats: Stat[] = userSolutions.map((solution) => ({ - ...solution, - id: solution.id || uuidv4(), - timeSpent, - session: sessionId, - exam: solution.exam!, - module: solution.module!, - user: user?.id || "", - date: new Date().getTime(), - isDisabled: solution.isDisabled, - ...(assignment ? { assignment: assignment.id } : {}), - })); + useEffect(() => { + if (selectedModules.length > 0 && exams.length !== 0 && moduleIndex >= selectedModules.length && !hasBeenUploaded && !showSolutions) { + const newStats: Stat[] = userSolutions.map((solution) => ({ + ...solution, + id: solution.id || uuidv4(), + timeSpent, + session: sessionId, + exam: solution.exam!, + module: solution.module!, + user: user?.id || "", + date: new Date().getTime(), + isDisabled: solution.isDisabled, + ...(assignment ? {assignment: assignment.id} : {}), + })); - axios - .post<{ ok: boolean }>("/api/stats", newStats) - .then((response) => setHasBeenUploaded(response.data.ok)) - .catch(() => setHasBeenUploaded(false)); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedModules, moduleIndex, hasBeenUploaded]); + axios + .post<{ok: boolean}>("/api/stats", newStats) + .then((response) => setHasBeenUploaded(response.data.ok)) + .catch(() => setHasBeenUploaded(false)); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedModules, moduleIndex, hasBeenUploaded]); - useEffect(() => { - setIsEvaluationLoading(statsAwaitingEvaluation.length !== 0); - }, [statsAwaitingEvaluation]); + useEffect(() => { + setIsEvaluationLoading(statsAwaitingEvaluation.length !== 0); + }, [statsAwaitingEvaluation]); - useEffect(() => { - if (statsAwaitingEvaluation.length > 0) { - checkIfStatsHaveBeenEvaluated(statsAwaitingEvaluation); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [statsAwaitingEvaluation]); + useEffect(() => { + if (statsAwaitingEvaluation.length > 0) { + checkIfStatsHaveBeenEvaluated(statsAwaitingEvaluation); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [statsAwaitingEvaluation]); - const checkIfStatsHaveBeenEvaluated = (ids: string[]) => { - setTimeout(async () => { - try { - const awaitedStats = await Promise.all( - ids.map( - async (id) => (await axios.get(`/api/stats/${id}`)).data, - ), - ); - const solutionsEvaluated = awaitedStats.every((stat) => - stat.solutions.every((x) => x.evaluation !== null), - ); - if (solutionsEvaluated) { - const statsUserSolutions: UserSolution[] = awaitedStats.map( - (stat) => ({ - id: stat.id, - exercise: stat.exercise, - score: stat.score, - solutions: stat.solutions, - type: stat.type, - exam: stat.exam, - module: stat.module, - }), - ); + const checkIfStatsHaveBeenEvaluated = (ids: string[]) => { + setTimeout(async () => { + try { + const awaitedStats = await Promise.all(ids.map(async (id) => (await axios.get(`/api/stats/${id}`)).data)); + const solutionsEvaluated = awaitedStats.every((stat) => stat.solutions.every((x) => x.evaluation !== null)); + if (solutionsEvaluated) { + const statsUserSolutions: UserSolution[] = awaitedStats.map((stat) => ({ + id: stat.id, + exercise: stat.exercise, + score: stat.score, + solutions: stat.solutions, + type: stat.type, + exam: stat.exam, + module: stat.module, + })); - const updatedUserSolutions = userSolutions.map((x) => { - const respectiveSolution = statsUserSolutions.find( - (y) => y.exercise === x.exercise, - ); - return respectiveSolution ? respectiveSolution : x; - }); + const updatedUserSolutions = userSolutions.map((x) => { + const respectiveSolution = statsUserSolutions.find((y) => y.exercise === x.exercise); + return respectiveSolution ? respectiveSolution : x; + }); - setUserSolutions(updatedUserSolutions); - return setStatsAwaitingEvaluation((prev) => - prev.filter((x) => !ids.includes(x)), - ); - } + setUserSolutions(updatedUserSolutions); + return setStatsAwaitingEvaluation((prev) => prev.filter((x) => !ids.includes(x))); + } - return checkIfStatsHaveBeenEvaluated(ids); - } catch { - return checkIfStatsHaveBeenEvaluated(ids); - } - }, 5 * 1000); - }; + return checkIfStatsHaveBeenEvaluated(ids); + } catch { + return checkIfStatsHaveBeenEvaluated(ids); + } + }, 5 * 1000); + }; - const updateExamWithUserSolutions = (exam: Exam): Exam => { - if (exam.module === "reading" || exam.module === "listening") { - const parts = exam.parts.map((p) => - Object.assign(p, { - exercises: p.exercises.map((x) => - Object.assign(x, { - userSolutions: userSolutions.find((y) => x.id === y.exercise) - ?.solutions, - }), - ), - }), - ); - return Object.assign(exam, { parts }); - } + const updateExamWithUserSolutions = (exam: Exam): Exam => { + if (exam.module === "reading" || exam.module === "listening") { + const parts = exam.parts.map((p) => + Object.assign(p, { + exercises: p.exercises.map((x) => + Object.assign(x, { + userSolutions: userSolutions.find((y) => x.id === y.exercise)?.solutions, + }), + ), + }), + ); + return Object.assign(exam, {parts}); + } - const exercises = exam.exercises.map((x) => - Object.assign(x, { - userSolutions: userSolutions.find((y) => x.id === y.exercise) - ?.solutions, - }), - ); - return Object.assign(exam, { exercises }); - }; + const exercises = exam.exercises.map((x) => + Object.assign(x, { + userSolutions: userSolutions.find((y) => x.id === y.exercise)?.solutions, + }), + ); + return Object.assign(exam, {exercises}); + }; - const onFinish = async (solutions: UserSolution[]) => { - const solutionIds = solutions.map((x) => x.exercise); - const solutionExams = solutions.map((x) => x.exam); + const onFinish = async (solutions: UserSolution[]) => { + const solutionIds = solutions.map((x) => x.exercise); + const solutionExams = solutions.map((x) => x.exam); - let newSolutions = [...solutions]; + let newSolutions = [...solutions]; - if (exam && !solutionExams.includes(exam.id)) return; + if (exam && !solutionExams.includes(exam.id)) return; - if ( - exam && - (exam.module === "writing" || exam.module === "speaking") && - solutions.length > 0 && - !showSolutions - ) { - setHasBeenUploaded(true); - setIsEvaluationLoading(true); + if (exam && (exam.module === "writing" || exam.module === "speaking") && solutions.length > 0 && !showSolutions) { + setHasBeenUploaded(true); + setIsEvaluationLoading(true); - const responses: UserSolution[] = ( - await Promise.all( - exam.exercises.map(async (exercise, index) => { - const evaluationID = uuidv4(); - if (exercise.type === "writing") - return await evaluateWritingAnswer( - exercise, - index + 1, - solutions.find((x) => x.exercise === exercise.id)!, - evaluationID, - ); + const responses: UserSolution[] = ( + await Promise.all( + exam.exercises.map(async (exercise, index) => { + const evaluationID = uuidv4(); + if (exercise.type === "writing") + return await evaluateWritingAnswer(exercise, index + 1, solutions.find((x) => x.exercise === exercise.id)!, evaluationID); - if ( - exercise.type === "interactiveSpeaking" || - exercise.type === "speaking" - ) - return await evaluateSpeakingAnswer( - exercise, - solutions.find((x) => x.exercise === exercise.id)!, - evaluationID, - ); - }), - ) - ).filter((x) => !!x) as UserSolution[]; + if (exercise.type === "interactiveSpeaking" || exercise.type === "speaking") + return await evaluateSpeakingAnswer( + exercise, + solutions.find((x) => x.exercise === exercise.id)!, + evaluationID, + index === 0 ? 1 : 2, + ); + }), + ) + ).filter((x) => !!x) as UserSolution[]; - newSolutions = [ - ...newSolutions.filter( - (x) => !responses.map((y) => y.exercise).includes(x.exercise), - ), - ...responses, - ]; - setStatsAwaitingEvaluation((prev) => [ - ...prev, - ...responses.filter((x) => !!x).map((r) => (r as any).id), - ]); - setHasBeenUploaded(false); - } + newSolutions = [...newSolutions.filter((x) => !responses.map((y) => y.exercise).includes(x.exercise)), ...responses]; + setStatsAwaitingEvaluation((prev) => [...prev, ...responses.filter((x) => !!x).map((r) => (r as any).id)]); + setHasBeenUploaded(false); + } - axios.get("/api/stats/update"); + axios.get("/api/stats/update"); - setUserSolutions([ - ...userSolutions.filter((x) => !solutionIds.includes(x.exercise)), - ...newSolutions, - ]); - setModuleIndex(moduleIndex + 1); + setUserSolutions([...userSolutions.filter((x) => !solutionIds.includes(x.exercise)), ...newSolutions]); + setModuleIndex(moduleIndex + 1); - setPartIndex(-1); - setExerciseIndex(-1); - setQuestionIndex(0); - }; + setPartIndex(-1); + setExerciseIndex(-1); + setQuestionIndex(0); + }; - const aggregateScoresByModule = (): { - module: Module; - total: number; - missing: number; - correct: number; - }[] => { - const scores: { - [key in Module]: { total: number; missing: number; correct: number }; - } = { - reading: { - total: 0, - correct: 0, - missing: 0, - }, - listening: { - total: 0, - correct: 0, - missing: 0, - }, - writing: { - total: 0, - correct: 0, - missing: 0, - }, - speaking: { - total: 0, - correct: 0, - missing: 0, - }, - level: { - total: 0, - correct: 0, - missing: 0, - }, - }; + const aggregateScoresByModule = (): { + module: Module; + total: number; + missing: number; + correct: number; + }[] => { + const scores: { + [key in Module]: {total: number; missing: number; correct: number}; + } = { + reading: { + total: 0, + correct: 0, + missing: 0, + }, + listening: { + total: 0, + correct: 0, + missing: 0, + }, + writing: { + total: 0, + correct: 0, + missing: 0, + }, + speaking: { + total: 0, + correct: 0, + missing: 0, + }, + level: { + total: 0, + correct: 0, + missing: 0, + }, + }; - userSolutions.forEach((x) => { - const examModule = - x.module || - (x.type === "writing" - ? "writing" - : x.type === "speaking" || x.type === "interactiveSpeaking" - ? "speaking" - : undefined); + userSolutions.forEach((x) => { + const examModule = + x.module || (x.type === "writing" ? "writing" : x.type === "speaking" || x.type === "interactiveSpeaking" ? "speaking" : undefined); - scores[examModule!] = { - total: scores[examModule!].total + x.score.total, - correct: scores[examModule!].correct + x.score.correct, - missing: scores[examModule!].missing + x.score.missing, - }; - }); + scores[examModule!] = { + total: scores[examModule!].total + x.score.total, + correct: scores[examModule!].correct + x.score.correct, + missing: scores[examModule!].missing + x.score.missing, + }; + }); - return Object.keys(scores) - .filter((x) => scores[x as Module].total > 0) - .map((x) => ({ module: x as Module, ...scores[x as Module] })); - }; + return Object.keys(scores) + .filter((x) => scores[x as Module].total > 0) + .map((x) => ({module: x as Module, ...scores[x as Module]})); + }; - const renderScreen = () => { - if (selectedModules.length === 0) { - return ( - { - setModuleIndex(0); - setAvoidRepeated(avoid); - setSelectedModules(modules); - setVariant(variant); - }} - /> - ); - } + const renderScreen = () => { + if (selectedModules.length === 0) { + return ( + { + setModuleIndex(0); + setAvoidRepeated(avoid); + setSelectedModules(modules); + setVariant(variant); + }} + /> + ); + } - if (moduleIndex >= selectedModules.length || moduleIndex === -1) { - return ( - { - setShowSolutions(true); - setModuleIndex(index || 0); - setExerciseIndex( - ["reading", "listening"].includes(exams[0].module) ? -1 : 0, - ); - setPartIndex(exams[0].module === "listening" ? -1 : 0); - setExam(exams[0]); - }} - scores={aggregateScoresByModule()} - /> - ); - } + if (moduleIndex >= selectedModules.length || moduleIndex === -1) { + return ( + { + setShowSolutions(true); + setModuleIndex(index || 0); + setExerciseIndex(["reading", "listening"].includes(exams[0].module) ? -1 : 0); + setPartIndex(exams[0].module === "listening" ? -1 : 0); + setExam(exams[0]); + }} + scores={aggregateScoresByModule()} + /> + ); + } - if (exam && exam.module === "reading") { - return ( - - ); - } + if (exam && exam.module === "reading") { + return ; + } - if (exam && exam.module === "listening") { - return ( - - ); - } + if (exam && exam.module === "listening") { + return ; + } - if (exam && exam.module === "writing") { - return ( - - ); - } + if (exam && exam.module === "writing") { + return ; + } - if (exam && exam.module === "speaking") { - return ( - - ); - } + if (exam && exam.module === "speaking") { + return ; + } - if (exam && exam.module === "level") { - return ( - - ); - } + if (exam && exam.module === "level") { + return ; + } - return <>Loading...; - }; + return <>Loading...; + }; - return ( - <> - - {user && ( - setShowAbandonPopup(true)} - > - <> - {renderScreen()} - {!showSolutions && moduleIndex < selectedModules.length && ( - { - reset(); - }} - onCancel={() => setShowAbandonPopup(false)} - /> - )} - - - )} - - ); + return ( + <> + + {user && ( + setShowAbandonPopup(true)}> + <> + {renderScreen()} + {!showSolutions && moduleIndex < selectedModules.length && ( + { + reset(); + }} + onCancel={() => setShowAbandonPopup(false)} + /> + )} + + + )} + + ); } diff --git a/src/pages/(status)/PaymentDue.tsx b/src/pages/(status)/PaymentDue.tsx index 1285d041..a1fba804 100644 --- a/src/pages/(status)/PaymentDue.tsx +++ b/src/pages/(status)/PaymentDue.tsx @@ -121,12 +121,12 @@ export default function PaymentDue({user, hasExpired = false, clientID, reload}:
- {!appliedDiscount && ( + {appliedDiscount === 0 && ( {p.price} {p.currency} )} - {appliedDiscount && ( + {appliedDiscount > 0 && (
{p.price} {p.currency} diff --git a/src/pages/api/evaluate/speaking.ts b/src/pages/api/evaluate/speaking.ts index 79293783..3f9431b9 100644 --- a/src/pages/api/evaluate/speaking.ts +++ b/src/pages/api/evaluate/speaking.ts @@ -30,6 +30,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { const audioFile = files.audio; const audioFileRef = ref(storage, `speaking_recordings/${fields.id}.wav`); + const task = parseInt(fields.task.toString()); const binary = fs.readFileSync((audioFile as any).path).buffer; const snapshot = await uploadBytes(audioFileRef, binary); @@ -39,7 +40,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { res.status(200).json(null); console.log("🌱 - Still processing"); - const backendRequest = await evaluate({answers: [{question: fields.question, answer: path}]}); + const backendRequest = await evaluate({answer: path, question: fields.question}, task); console.log("🌱 - Process complete"); const correspondingStat = await getCorrespondingStat(fields.id, 1); @@ -76,14 +77,14 @@ async function getCorrespondingStat(id: string, index: number): Promise { return getCorrespondingStat(id, index + 1); } -async function evaluate(body: {answers: object[]}): Promise { - const backendRequest = await axios.post(`${process.env.BACKEND_URL}/speaking_task_3`, body, { +async function evaluate(body: {answer: string; question: string}, task: number): Promise { + const backendRequest = await axios.post(`${process.env.BACKEND_URL}/speaking_task_${task}`, body, { headers: { Authorization: `Bearer ${process.env.BACKEND_JWT}`, }, }); - if (typeof backendRequest.data === "string") return evaluate(body); + if (typeof backendRequest.data === "string") return evaluate(body, task); return backendRequest; } diff --git a/src/pages/api/users/update.ts b/src/pages/api/users/update.ts index bbd1b75c..5fd6f8e7 100644 --- a/src/pages/api/users/update.ts +++ b/src/pages/api/users/update.ts @@ -90,7 +90,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { if (updatedUser.status || updatedUser.type === "corporate") { // there's no await as this does not affect the user propagateStatusChange(queryId, updatedUser.status); - propagateExpiryDateChanges(queryId, user.subscriptionExpirationDate || null, updatedUser.subscriptionExpirationDate || null); + propagateExpiryDateChanges(queryId, user.subscriptionExpirationDate, updatedUser.subscriptionExpirationDate || null); } res.status(200).json({ok: true}); diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index dbc2ca9d..2548b9c6 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -1,783 +1,655 @@ /* 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, -} from "@/interfaces/user"; +import {CorporateUser, EmploymentStatus, EMPLOYMENT_STATUS, Gender, User} 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"; -export const getServerSideProps = withIronSessionSsr(({ req, res }) => { - const user = req.session.user; +import {v4} from "uuid"; +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 - >( - ["developer", "student"].includes(user.type) - ? user.desiredLevels - : undefined, - ); + const [desiredLevels, setDesiredLevels] = useState<{[key in Module]: number} | undefined>( + ["developer", "student"].includes(user.type) ? 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( - user.type === "corporate" - ? undefined - : user.demographicInformation?.employment, - ); - const [passport_id, setPassportID] = useState( - user.type === "student" - ? user.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( + user.type === "corporate" ? undefined : user.demographicInformation?.employment, + ); + const [passport_id, setPassportID] = useState(user.type === "student" ? user.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, - 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 = () => ( -
- - - {!user.subscriptionExpirationDate && "Unlimited"} - {user.subscriptionExpirationDate && - moment(user.subscriptionExpirationDate).format("DD/MM/YYYY")} - -
- ); + const ExpirationDate = () => ( +
+ + + {!user.subscriptionExpirationDate && "Unlimited"} + {user.subscriptionExpirationDate && moment(user.subscriptionExpirationDate).format("DD/MM/YYYY")} + +
+ ); - const TimezoneInput = () => ( -
- - -
- ); + const TimezoneInput = () => ( +
+ + +
+ ); - 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 + /> +
+ )} - -
- - -
- setPhone(e)} - placeholder="Enter phone number" - defaultValue={phone} - required - /> -
+ +
+ + +
+ 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) && ( -
- - - > - } - /> -
- )} + {desiredLevels && ["developer", "student"].includes(user.type) && ( + <> +
+ + >} + /> +
+
+ +
+ + +
+
+ + )} - {preferredGender && - ["developer", "student"].includes(user.type) && ( - <> - - -
- - (value ? setPreferredGender(value.value as InstructorGender) : null)} + options={[ + {value: "male", label: "Male"}, + {value: "female", label: "Female"}, + {value: "varied", label: "Varied"}, + ]} + /> +
+
+ + +
+
- 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 - /> - - -
- - - 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 + /> + + +
+ + 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()} - > -
-
- -
- {user.name} -
- - (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 && ( - - - - )} -
-
-
- Bio -