diff --git a/src/components/Diagnostic.tsx b/src/components/Diagnostic.tsx index f7b448f4..b38215d6 100644 --- a/src/components/Diagnostic.tsx +++ b/src/components/Diagnostic.tsx @@ -14,6 +14,7 @@ import {useEffect, useState} from "react"; import {BsBook, BsChevronDown, BsHeadphones, BsMegaphone, BsPen, BsQuestionSquare} from "react-icons/bs"; import {toast} from "react-toastify"; import Button from "./Low/Button"; +import ModuleLevelSelector from "./Medium/ModuleLevelSelector"; interface Props { user: User; @@ -90,140 +91,44 @@ export default function Diagnostic({onFinish}: Props) { +

What is your current IELTS level?

-
-
-
- - Reading level - - - - - - {levels.reading === -1 ? "Select your reading level" : `Level ${levels.reading}`} - - - - - {Object.values(writingMarking).map((x) => ( - - setLevels((prev) => ({...prev, reading: x}))} - className="w-full py-4 text-center cursor-pointer bg-white hover:bg-mti-gray-platinum transition ease-in-out duration-300"> - Level {x} - - - ))} - - -
-
- - Listening level - - - - - - {levels.listening === -1 ? "Select your listening level" : `Level ${levels.listening}`} - - - - - {Object.values(writingMarking).map((x) => ( - - setLevels((prev) => ({...prev, listening: x}))} - className="w-full py-5 text-center cursor-pointer bg-white hover:bg-mti-gray-platinum transition ease-in-out duration-300"> - Level {x} - - - ))} - - -
-
- - Writing level - - - - - - {levels.writing === -1 ? "Select your writing level" : `Level ${levels.writing}`} - - - - - {Object.values(writingMarking).map((x) => ( - - setLevels((prev) => ({...prev, writing: x}))} - className="w-full py-5 text-center cursor-pointer bg-white hover:bg-mti-gray-platinum transition ease-in-out duration-300"> - Level {x} - - - ))} - - -
-
- - Speaking level - - - - - - {levels.speaking === -1 ? "Select your speaking level" : `Level ${levels.speaking}`} - - - - - {Object.values(writingMarking).map((x) => ( - - setLevels((prev) => ({...prev, speaking: x}))} - className="w-full py-5 text-center cursor-pointer bg-white hover:bg-mti-gray-platinum transition ease-in-out duration-300"> - Level {x} - - - ))} - - -
-
-
-
- -
- - -
+ +
+ +
+

What is your desired IELTS level?

+ +
+ +
+
+
+ +
); diff --git a/src/components/Low/ProgressBar.tsx b/src/components/Low/ProgressBar.tsx index 341a9869..b900d8e0 100644 --- a/src/components/Low/ProgressBar.tsx +++ b/src/components/Low/ProgressBar.tsx @@ -5,12 +5,14 @@ interface Props { label: string; percentage: number; color: "red" | "rose" | "purple" | Module; + mark?: number; + markLabel?: string; useColor?: boolean; className?: string; textClassName?: string; } -export default function ProgressBar({label, percentage, color, useColor = false, className, textClassName}: Props) { +export default function ProgressBar({label, percentage, color, mark, markLabel, useColor = false, className, textClassName}: Props) { const progressColorClass: {[key in typeof color]: string} = { red: "bg-mti-red-light", rose: "bg-mti-rose-light", @@ -30,6 +32,9 @@ export default function ProgressBar({label, percentage, color, useColor = false, !useColor ? "bg-mti-gray-anti-flash" : progressColorClass[color], useColor && "bg-opacity-20", )}> + {mark && ( +
+ )}
>; +} + +export default function ModuleLevelSelector({levels, setLevels}: Props) { + return ( +
+
+
+ + Reading level + + + + + + {levels.reading === -1 ? "Select your reading level" : `Level ${levels.reading}`} + + + + + {Object.values(writingMarking).map((x) => ( + + setLevels((prev) => ({...prev, reading: x}))} + className="w-full py-4 text-center cursor-pointer bg-white hover:bg-mti-gray-platinum transition ease-in-out duration-300"> + Level {x} + + + ))} + + +
+
+ + Listening level + + + + + + {levels.listening === -1 ? "Select your listening level" : `Level ${levels.listening}`} + + + + + {Object.values(writingMarking).map((x) => ( + + setLevels((prev) => ({...prev, listening: x}))} + className="w-full py-5 text-center cursor-pointer bg-white hover:bg-mti-gray-platinum transition ease-in-out duration-300"> + Level {x} + + + ))} + + +
+
+ + Writing level + + + + + + {levels.writing === -1 ? "Select your writing level" : `Level ${levels.writing}`} + + + + + {Object.values(writingMarking).map((x) => ( + + setLevels((prev) => ({...prev, writing: x}))} + className="w-full py-5 text-center cursor-pointer bg-white hover:bg-mti-gray-platinum transition ease-in-out duration-300"> + Level {x} + + + ))} + + +
+
+ + Speaking level + + + + + + {levels.speaking === -1 ? "Select your speaking level" : `Level ${levels.speaking}`} + + + + + {Object.values(writingMarking).map((x) => ( + + setLevels((prev) => ({...prev, speaking: x}))} + className="w-full py-5 text-center cursor-pointer bg-white hover:bg-mti-gray-platinum transition ease-in-out duration-300"> + Level {x} + + + ))} + + +
+
+
+ ); +} diff --git a/src/dashboards/Student.tsx b/src/dashboards/Student.tsx index ebade14d..03544a19 100644 --- a/src/dashboards/Student.tsx +++ b/src/dashboards/Student.tsx @@ -7,352 +7,254 @@ import useAssignments from "@/hooks/useAssignments"; import useInvites from "@/hooks/useInvites"; import useStats from "@/hooks/useStats"; import useUsers from "@/hooks/useUsers"; -import { Invite } from "@/interfaces/invite"; -import { Assignment } from "@/interfaces/results"; -import { CorporateUser, User } from "@/interfaces/user"; +import {Invite} from "@/interfaces/invite"; +import {Assignment} from "@/interfaces/results"; +import {CorporateUser, User} from "@/interfaces/user"; import useExamStore from "@/stores/examStore"; -import { getExamById } from "@/utils/exams"; -import { getUserCorporate } from "@/utils/groups"; -import { - MODULE_ARRAY, - sortByModule, - sortByModuleName, -} from "@/utils/moduleUtils"; -import { averageScore, groupBySession } from "@/utils/stats"; -import { - CreateOrderActions, - CreateOrderData, - OnApproveActions, - OnApproveData, - OrderResponseBody, -} from "@paypal/paypal-js"; -import { PayPalButtons } from "@paypal/react-paypal-js"; +import {getExamById} from "@/utils/exams"; +import {getUserCorporate} from "@/utils/groups"; +import {MODULE_ARRAY, sortByModule, sortByModuleName} from "@/utils/moduleUtils"; +import {averageScore, groupBySession} from "@/utils/stats"; +import {CreateOrderActions, CreateOrderData, OnApproveActions, OnApproveData, OrderResponseBody} from "@paypal/paypal-js"; +import {PayPalButtons} from "@paypal/react-paypal-js"; import axios from "axios"; import clsx from "clsx"; -import { capitalize } from "lodash"; +import {capitalize} from "lodash"; import moment from "moment"; import Link from "next/link"; -import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; -import { - BsArrowRepeat, - BsBook, - BsClipboard, - BsFileEarmarkText, - BsHeadphones, - BsMegaphone, - BsPen, - BsPencil, - BsStar, -} from "react-icons/bs"; -import { toast } from "react-toastify"; +import {useRouter} from "next/router"; +import {useEffect, useState} from "react"; +import {BsArrowRepeat, BsBook, BsClipboard, BsFileEarmarkText, BsHeadphones, BsMegaphone, BsPen, BsPencil, BsStar} from "react-icons/bs"; +import {toast} from "react-toastify"; interface Props { - user: User; + user: User; } -export default function StudentDashboard({ user }: Props) { - const [corporateUserToShow, setCorporateUserToShow] = - useState(); +export default function StudentDashboard({user}: Props) { + const [corporateUserToShow, setCorporateUserToShow] = useState(); - const { stats } = useStats(user.id); - const { users } = useUsers(); - const { - assignments, - isLoading: isAssignmentsLoading, - reload: reloadAssignments, - } = useAssignments({ assignees: user?.id }); - const { - invites, - isLoading: isInvitesLoading, - reload: reloadInvites, - } = useInvites({ to: user.id }); + const {stats} = useStats(user.id); + const {users} = useUsers(); + const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({assignees: user?.id}); + const {invites, isLoading: isInvitesLoading, reload: reloadInvites} = useInvites({to: user.id}); - const router = useRouter(); + const router = useRouter(); - const setExams = useExamStore((state) => state.setExams); - const setShowSolutions = useExamStore((state) => state.setShowSolutions); - const setUserSolutions = useExamStore((state) => state.setUserSolutions); - const setSelectedModules = useExamStore((state) => state.setSelectedModules); - const setAssignment = useExamStore((state) => state.setAssignment); + const setExams = useExamStore((state) => state.setExams); + const setShowSolutions = useExamStore((state) => state.setShowSolutions); + const setUserSolutions = useExamStore((state) => state.setUserSolutions); + const setSelectedModules = useExamStore((state) => state.setSelectedModules); + const setAssignment = useExamStore((state) => state.setAssignment); - useEffect(() => { - getUserCorporate(user.id).then(setCorporateUserToShow); - }, [user]); + 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)); + const startAssignment = (assignment: Assignment) => { + const examPromises = assignment.exams.filter((e) => e.assignee === user.id).map((e) => getExamById(e.module, e.id)); - Promise.all(examPromises).then((exams) => { - if (exams.every((x) => !!x)) { - setUserSolutions([]); - setShowSolutions(false); - setExams(exams.map((x) => x!).sort(sortByModule)); - setSelectedModules( - exams - .map((x) => x!) - .sort(sortByModule) - .map((x) => x!.module), - ); - setAssignment(assignment); + Promise.all(examPromises).then((exams) => { + if (exams.every((x) => !!x)) { + setUserSolutions([]); + setShowSolutions(false); + setExams(exams.map((x) => x!).sort(sortByModule)); + setSelectedModules( + exams + .map((x) => x!) + .sort(sortByModule) + .map((x) => x!.module), + ); + setAssignment(assignment); - router.push("/exercises"); - } - }); - }; + router.push("/exercises"); + } + }); + }; - return ( - <> - {corporateUserToShow && ( -
- Linked to:{" "} - - {corporateUserToShow?.corporateInformation?.companyInformation - .name || corporateUserToShow.name} - -
- )} - - ), - value: Object.keys(groupBySession(stats)).length, - label: "Exams", - }, - { - icon: ( - - ), - value: stats.length, - label: "Exercises", - }, - { - icon: ( - - ), - value: `${stats.length > 0 ? averageScore(stats) : 0}%`, - label: "Average Score", - }, - ]} - /> + return ( + <> + {corporateUserToShow && ( +
+ Linked to: {corporateUserToShow?.corporateInformation?.companyInformation.name || corporateUserToShow.name} +
+ )} + , + value: Object.keys(groupBySession(stats)).length, + label: "Exams", + }, + { + icon: , + value: stats.length, + label: "Exercises", + }, + { + icon: , + value: `${stats.length > 0 ? averageScore(stats) : 0}%`, + label: "Average Score", + }, + ]} + /> -
- Bio - - {user.bio || - "Your bio will appear here, you can change it by clicking on your name in the top right corner."} - -
+ {/* Bio */} +
+ Bio + + {user.bio || "Your bio will appear here, you can change it by clicking on your name in the top right corner."} + +
-
-
-
- - Assignments - - -
-
- - {assignments.filter((a) => moment(a.endDate).isSameOrAfter(moment())) - .length === 0 && - "Assignments will appear here. It seems that for now there are no assignments for you."} - {assignments - .filter((a) => moment(a.endDate).isSameOrAfter(moment())) - .sort((a, b) => moment(a.startDate).diff(b.startDate)) - .map((assignment) => ( -
r.user).includes(user.id) && - "border-mti-green-light", - )} - key={assignment.id} - > -
-

- {assignment.name} -

- - - {moment(assignment.startDate).format("DD/MM/YY, HH:mm")} - - - - - {moment(assignment.endDate).format("DD/MM/YY, HH:mm")} - - -
-
-
- {assignment.exams - .filter((e) => e.assignee === user.id) - .map((e) => e.module) - .sort(sortByModuleName) - .map((module) => ( -
- {module === "reading" && ( - - )} - {module === "listening" && ( - - )} - {module === "writing" && ( - - )} - {module === "speaking" && ( - - )} - {module === "level" && ( - - )} -
- ))} -
- {!assignment.results.map((r) => r.user).includes(user.id) && ( - <> -
- -
- - - )} - {assignment.results.map((r) => r.user).includes(user.id) && ( - - )} -
-
- ))} -
-
+ {/* Assignments */} +
+
+
+ Assignments + +
+
+ + {assignments.filter((a) => moment(a.endDate).isSameOrAfter(moment())).length === 0 && + "Assignments will appear here. It seems that for now there are no assignments for you."} + {assignments + .filter((a) => moment(a.endDate).isSameOrAfter(moment())) + .sort((a, b) => moment(a.startDate).diff(b.startDate)) + .map((assignment) => ( +
r.user).includes(user.id) && "border-mti-green-light", + )} + key={assignment.id}> +
+

{assignment.name}

+ + {moment(assignment.startDate).format("DD/MM/YY, HH:mm")} + - + {moment(assignment.endDate).format("DD/MM/YY, HH:mm")} + +
+
+
+ {assignment.exams + .filter((e) => e.assignee === user.id) + .map((e) => e.module) + .sort(sortByModuleName) + .map((module) => ( +
+ {module === "reading" && } + {module === "listening" && } + {module === "writing" && } + {module === "speaking" && } + {module === "level" && } +
+ ))} +
+ {!assignment.results.map((r) => r.user).includes(user.id) && ( + <> +
+ +
+ + + )} + {assignment.results.map((r) => r.user).includes(user.id) && ( + + )} +
+
+ ))} +
+
- {invites.length > 0 && ( -
-
-
- Invites - -
-
- - {invites.map((invite) => ( - - ))} - -
- )} + {/* Invites */} + {invites.length > 0 && ( +
+
+
+ Invites + +
+
+ + {invites.map((invite) => ( + + ))} + +
+ )} -
- Score History -
- {MODULE_ARRAY.map((module) => ( -
-
-
- {module === "reading" && ( - - )} - {module === "listening" && ( - - )} - {module === "writing" && ( - - )} - {module === "speaking" && ( - - )} - {module === "level" && ( - - )} -
-
- - {capitalize(module)} - - - Level {user.levels[module] || 0} / Level{" "} - {user.desiredLevels[module] || 9} - -
-
-
- -
-
- ))} -
-
- - ); + {/* Score History */} +
+ Score History +
+ {MODULE_ARRAY.map((module) => ( +
+
+
+ {module === "reading" && } + {module === "listening" && } + {module === "writing" && } + {module === "speaking" && } + {module === "level" && } +
+
+ {capitalize(module)} + + Level {user.levels[module] || 0} / Level 9 (Desired Level: {user.desiredLevels[module] || 9}) + +
+
+
+ +
+
+ ))} +
+
+ + ); } diff --git a/src/exams/Selection.tsx b/src/exams/Selection.tsx index d35cc855..5d1e5883 100644 --- a/src/exams/Selection.tsx +++ b/src/exams/Selection.tsx @@ -1,384 +1,261 @@ /* eslint-disable @next/next/no-img-element */ -import { useState } from "react"; -import { Module } from "@/interfaces"; +import {useState} from "react"; +import {Module} from "@/interfaces"; import clsx from "clsx"; -import { User } from "@/interfaces/user"; +import {User} from "@/interfaces/user"; import ProgressBar from "@/components/Low/ProgressBar"; -import { - BsBook, - BsCheck, - BsCheckCircle, - BsClipboard, - BsHeadphones, - BsMegaphone, - BsPen, - BsXCircle, -} from "react-icons/bs"; -import { totalExamsByModule } from "@/utils/stats"; +import {BsBook, BsCheck, BsCheckCircle, BsClipboard, BsHeadphones, BsMegaphone, BsPen, BsXCircle} from "react-icons/bs"; +import {totalExamsByModule} from "@/utils/stats"; import useStats from "@/hooks/useStats"; import Button from "@/components/Low/Button"; -import { calculateAverageLevel } from "@/utils/score"; -import { sortByModuleName } from "@/utils/moduleUtils"; -import { capitalize } from "lodash"; +import {calculateAverageLevel} from "@/utils/score"; +import {sortByModuleName} from "@/utils/moduleUtils"; +import {capitalize} from "lodash"; import ProfileSummary from "@/components/ProfileSummary"; -import { Variant } from "@/interfaces/exam"; +import {Variant} from "@/interfaces/exam"; interface Props { - user: User; - page: "exercises" | "exams"; - onStart: ( - modules: Module[], - avoidRepeated: boolean, - variant: Variant, - ) => void; - disableSelection?: boolean; + user: User; + page: "exercises" | "exams"; + onStart: (modules: Module[], avoidRepeated: boolean, variant: Variant) => void; + disableSelection?: boolean; } -export default function Selection({ - user, - page, - onStart, - disableSelection = false, -}: Props) { - const [selectedModules, setSelectedModules] = useState([]); - const [avoidRepeatedExams, setAvoidRepeatedExams] = useState(true); - const [variant, setVariant] = useState("full"); - const { stats } = useStats(user?.id); +export default function Selection({user, page, onStart, disableSelection = false}: Props) { + const [selectedModules, setSelectedModules] = useState([]); + const [avoidRepeatedExams, setAvoidRepeatedExams] = useState(true); + const [variant, setVariant] = useState("full"); + const {stats} = useStats(user?.id); - const toggleModule = (module: Module) => { - const modules = selectedModules.filter((x) => x !== module); - setSelectedModules((prev) => - prev.includes(module) ? modules : [...modules, module], - ); - }; + const toggleModule = (module: Module) => { + const modules = selectedModules.filter((x) => x !== module); + setSelectedModules((prev) => (prev.includes(module) ? modules : [...modules, module])); + }; - return ( - <> -
- {user && ( - - ), - label: "Reading", - value: totalExamsByModule(stats, "reading"), - }, - { - icon: ( - - ), - label: "Listening", - value: totalExamsByModule(stats, "listening"), - }, - { - icon: ( - - ), - label: "Writing", - value: totalExamsByModule(stats, "writing"), - }, - { - icon: ( - - ), - label: "Speaking", - value: totalExamsByModule(stats, "speaking"), - }, - { - icon: ( - - ), - label: "Level", - value: totalExamsByModule(stats, "level"), - }, - ]} - /> - )} + return ( + <> +
+ {user && ( + , + label: "Reading", + value: totalExamsByModule(stats, "reading"), + }, + { + icon: , + label: "Listening", + value: totalExamsByModule(stats, "listening"), + }, + { + icon: , + label: "Writing", + value: totalExamsByModule(stats, "writing"), + }, + { + icon: , + label: "Speaking", + value: totalExamsByModule(stats, "speaking"), + }, + { + icon: , + label: "Vocab/Grammar", + value: totalExamsByModule(stats, "level"), + }, + ]} + /> + )} -
- About {capitalize(page)} - - {page === "exercises" && ( - <> - In the realm of language acquisition, practice makes perfect, - and our exercises are the key to unlocking your full potential. - Dive into a world of interactive and engaging exercises that - cater to diverse learning styles. From grammar drills that build - a strong foundation to vocabulary challenges that broaden your - lexicon, our exercises are carefully designed to make learning - English both enjoyable and effective. Whether you're - looking to reinforce specific skills or embark on a holistic - language journey, our exercises are your companions in the - pursuit of excellence. Embrace the joy of learning as you - navigate through a variety of activities that cater to every - facet of language acquisition. Your linguistic adventure starts - here! - - )} - {page === "exams" && ( - <> - Welcome to the heart of success on your English language - journey! Our exams are crafted with precision to assess and - enhance your language skills. Each test is a passport to your - linguistic prowess, designed to challenge and elevate your - abilities. Whether you're a beginner or a seasoned learner, - our exams cater to all levels, providing a comprehensive - evaluation of your reading, writing, speaking, and listening - skills. Prepare to embark on a journey of self-discovery and - language mastery as you navigate through our thoughtfully - curated exams. Your success is not just a destination; it's - a testament to your dedication and our commitment to empowering - you with the English language. - - )} - -
-
-
toggleModule("reading") - : undefined - } - className={clsx( - "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", - selectedModules.includes("reading") || disableSelection - ? "border-mti-purple-light" - : "border-mti-gray-platinum", - )} - > -
- -
- Reading: -

- Expand your vocabulary, improve your reading comprehension and - improve your ability to interpret texts in English. -

- {!selectedModules.includes("reading") && - !selectedModules.includes("level") && - !disableSelection && ( -
- )} - {(selectedModules.includes("reading") || disableSelection) && ( - - )} - {selectedModules.includes("level") && ( - - )} -
-
toggleModule("listening") - : undefined - } - className={clsx( - "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", - selectedModules.includes("listening") || disableSelection - ? "border-mti-purple-light" - : "border-mti-gray-platinum", - )} - > -
- -
- Listening: -

- Improve your ability to follow conversations in English and your - ability to understand different accents and intonations. -

- {!selectedModules.includes("listening") && - !selectedModules.includes("level") && - !disableSelection && ( -
- )} - {(selectedModules.includes("listening") || disableSelection) && ( - - )} - {selectedModules.includes("level") && ( - - )} -
-
toggleModule("writing") - : undefined - } - className={clsx( - "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", - selectedModules.includes("writing") || disableSelection - ? "border-mti-purple-light" - : "border-mti-gray-platinum", - )} - > -
- -
- Writing: -

- Allow you to practice writing in a variety of formats, from simple - paragraphs to complex essays. -

- {!selectedModules.includes("writing") && - !selectedModules.includes("level") && - !disableSelection && ( -
- )} - {(selectedModules.includes("writing") || disableSelection) && ( - - )} - {selectedModules.includes("level") && ( - - )} -
-
toggleModule("speaking") - : undefined - } - className={clsx( - "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", - selectedModules.includes("speaking") || disableSelection - ? "border-mti-purple-light" - : "border-mti-gray-platinum", - )} - > -
- -
- Speaking: -

- You'll have access to interactive dialogs, pronunciation - exercises and speech recordings. -

- {!selectedModules.includes("speaking") && - !selectedModules.includes("level") && - !disableSelection && ( -
- )} - {(selectedModules.includes("speaking") || disableSelection) && ( - - )} - {selectedModules.includes("level") && ( - - )} -
- {!disableSelection && ( -
toggleModule("level") - : undefined - } - className={clsx( - "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", - selectedModules.includes("level") || disableSelection - ? "border-mti-purple-light" - : "border-mti-gray-platinum", - )} - > -
- -
- Level: -

- You'll be able to test your english level with multiple - choice questions. -

- {!selectedModules.includes("level") && - selectedModules.length === 0 && - !disableSelection && ( -
- )} - {(selectedModules.includes("level") || disableSelection) && ( - - )} - {!selectedModules.includes("level") && - selectedModules.length > 0 && ( - - )} -
- )} -
-
-
-
setAvoidRepeatedExams((prev) => !prev)} - > - -
- -
- - Avoid Repeated Questions - -
-
- setVariant((prev) => (prev === "full" ? "partial" : "full")) - } - > - -
- -
- Full length exams -
-
-
- -
- -
-
- - ); +
+ About {capitalize(page)} + + {page === "exercises" && ( + <> + In the realm of language acquisition, practice makes perfect, and our exercises are the key to unlocking your full + potential. Dive into a world of interactive and engaging exercises that cater to diverse learning styles. From grammar + drills that build a strong foundation to vocabulary challenges that broaden your lexicon, our exercises are carefully + designed to make learning English both enjoyable and effective. Whether you're looking to reinforce specific + skills or embark on a holistic language journey, our exercises are your companions in the pursuit of excellence. + Embrace the joy of learning as you navigate through a variety of activities that cater to every facet of language + acquisition. Your linguistic adventure starts here! + + )} + {page === "exams" && ( + <> + Welcome to the heart of success on your English language journey! Our exams are crafted with precision to assess and + enhance your language skills. Each test is a passport to your linguistic prowess, designed to challenge and elevate + your abilities. Whether you're a beginner or a seasoned learner, our exams cater to all levels, providing a + comprehensive evaluation of your reading, writing, speaking, and listening skills. Prepare to embark on a journey of + self-discovery and language mastery as you navigate through our thoughtfully curated exams. Your success is not just a + destination; it's a testament to your dedication and our commitment to empowering you with the English language. + + )} + +
+
+
toggleModule("reading") : undefined} + className={clsx( + "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", + selectedModules.includes("reading") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum", + )}> +
+ +
+ Reading: +

+ Expand your vocabulary, improve your reading comprehension and improve your ability to interpret texts in English. +

+ {!selectedModules.includes("reading") && !selectedModules.includes("level") && !disableSelection && ( +
+ )} + {(selectedModules.includes("reading") || disableSelection) && ( + + )} + {selectedModules.includes("level") && } +
+
toggleModule("listening") : undefined} + className={clsx( + "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", + selectedModules.includes("listening") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum", + )}> +
+ +
+ Listening: +

+ Improve your ability to follow conversations in English and your ability to understand different accents and intonations. +

+ {!selectedModules.includes("listening") && !selectedModules.includes("level") && !disableSelection && ( +
+ )} + {(selectedModules.includes("listening") || disableSelection) && ( + + )} + {selectedModules.includes("level") && } +
+
toggleModule("writing") : undefined} + className={clsx( + "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", + selectedModules.includes("writing") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum", + )}> +
+ +
+ Writing: +

+ Allow you to practice writing in a variety of formats, from simple paragraphs to complex essays. +

+ {!selectedModules.includes("writing") && !selectedModules.includes("level") && !disableSelection && ( +
+ )} + {(selectedModules.includes("writing") || disableSelection) && ( + + )} + {selectedModules.includes("level") && } +
+
toggleModule("speaking") : undefined} + className={clsx( + "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", + selectedModules.includes("speaking") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum", + )}> +
+ +
+ Speaking: +

+ You'll have access to interactive dialogs, pronunciation exercises and speech recordings. +

+ {!selectedModules.includes("speaking") && !selectedModules.includes("level") && !disableSelection && ( +
+ )} + {(selectedModules.includes("speaking") || disableSelection) && ( + + )} + {selectedModules.includes("level") && } +
+ {!disableSelection && ( +
toggleModule("level") : undefined} + className={clsx( + "bg-mti-white-alt relative flex w-64 max-w-xs cursor-pointer flex-col items-center gap-2 rounded-xl border p-5 pt-12 transition duration-300 ease-in-out", + selectedModules.includes("level") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum", + )}> +
+ +
+ Level: +

You'll be able to test your english level with multiple choice questions.

+ {!selectedModules.includes("level") && selectedModules.length === 0 && !disableSelection && ( +
+ )} + {(selectedModules.includes("level") || disableSelection) && ( + + )} + {!selectedModules.includes("level") && selectedModules.length > 0 && ( + + )} +
+ )} +
+
+
+
setAvoidRepeatedExams((prev) => !prev)}> + +
+ +
+ + Avoid Repeated Questions + +
+
setVariant((prev) => (prev === "full" ? "partial" : "full"))}> + +
+ +
+ Full length exams +
+
+
+ +
+ +
+
+ + ); } diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index 8273741b..4bdcd1b2 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -2,7 +2,7 @@ import Head from "next/head"; import {withIronSessionSsr} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; -import {ChangeEvent, ReactNode, useEffect, useRef, useState} from "react"; +import {ChangeEvent, Dispatch, ReactNode, SetStateAction, useEffect, useRef, useState} from "react"; import useUser from "@/hooks/useUser"; import {toast, ToastContainer} from "react-toastify"; import Layout from "@/components/High/Layout"; @@ -25,6 +25,9 @@ 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 ModuleLevelSelector from "@/components/Medium/ModuleLevelSelector"; export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; @@ -69,6 +72,10 @@ function UserProfile({user, mutateUser}: Props) { 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 [country, setCountry] = useState(user.demographicInformation?.country || ""); const [phone, setPhone] = useState(user.demographicInformation?.phone || ""); const [gender, setGender] = useState(user.demographicInformation?.gender || undefined); @@ -138,6 +145,7 @@ function UserProfile({user, mutateUser}: Props) { password, newPassword, profilePicture, + desiredLevels, demographicInformation: { phone, country, @@ -319,6 +327,18 @@ function UserProfile({user, mutateUser}: Props) { + {desiredLevels && ["developer", "student"].includes(user.type) && ( +
+ + >} + /> +
+ )} + + + {user.type === "corporate" && ( <>