Enable the option to not have only full exams
This commit is contained in:
@@ -1,442 +1,310 @@
|
|||||||
/* eslint-disable @next/next/no-img-element */
|
/* eslint-disable @next/next/no-img-element */
|
||||||
import { useState } from "react";
|
import {useState} from "react";
|
||||||
import { Module } from "@/interfaces";
|
import {Module} from "@/interfaces";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { User } from "@/interfaces/user";
|
import {User} from "@/interfaces/user";
|
||||||
import ProgressBar from "@/components/Low/ProgressBar";
|
import ProgressBar from "@/components/Low/ProgressBar";
|
||||||
import {
|
import {BsArrowRepeat, BsBook, BsCheck, BsCheckCircle, BsClipboard, BsHeadphones, BsMegaphone, BsPen, BsXCircle} from "react-icons/bs";
|
||||||
BsArrowRepeat,
|
import {totalExamsByModule} from "@/utils/stats";
|
||||||
BsBook,
|
|
||||||
BsCheck,
|
|
||||||
BsCheckCircle,
|
|
||||||
BsClipboard,
|
|
||||||
BsHeadphones,
|
|
||||||
BsMegaphone,
|
|
||||||
BsPen,
|
|
||||||
BsXCircle,
|
|
||||||
} from "react-icons/bs";
|
|
||||||
import { totalExamsByModule } from "@/utils/stats";
|
|
||||||
import useStats from "@/hooks/useStats";
|
import useStats from "@/hooks/useStats";
|
||||||
import Button from "@/components/Low/Button";
|
import Button from "@/components/Low/Button";
|
||||||
import { calculateAverageLevel } from "@/utils/score";
|
import {calculateAverageLevel} from "@/utils/score";
|
||||||
import { sortByModuleName } from "@/utils/moduleUtils";
|
import {sortByModuleName} from "@/utils/moduleUtils";
|
||||||
import { capitalize } from "lodash";
|
import {capitalize} from "lodash";
|
||||||
import ProfileSummary from "@/components/ProfileSummary";
|
import ProfileSummary from "@/components/ProfileSummary";
|
||||||
import { Variant } from "@/interfaces/exam";
|
import {Variant} from "@/interfaces/exam";
|
||||||
import useSessions, { Session } from "@/hooks/useSessions";
|
import useSessions, {Session} from "@/hooks/useSessions";
|
||||||
import SessionCard from "@/components/Medium/SessionCard";
|
import SessionCard from "@/components/Medium/SessionCard";
|
||||||
import useExamStore from "@/stores/examStore";
|
import useExamStore from "@/stores/examStore";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: User;
|
user: User;
|
||||||
page: "exercises" | "exams";
|
page: "exercises" | "exams";
|
||||||
onStart: (
|
onStart: (modules: Module[], avoidRepeated: boolean, variant: Variant) => void;
|
||||||
modules: Module[],
|
disableSelection?: boolean;
|
||||||
avoidRepeated: boolean,
|
|
||||||
variant: Variant,
|
|
||||||
) => void;
|
|
||||||
disableSelection?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Selection({
|
export default function Selection({user, page, onStart, disableSelection = false}: Props) {
|
||||||
user,
|
const [selectedModules, setSelectedModules] = useState<Module[]>([]);
|
||||||
page,
|
const [avoidRepeatedExams, setAvoidRepeatedExams] = useState(true);
|
||||||
onStart,
|
const [variant, setVariant] = useState<Variant>("full");
|
||||||
disableSelection = false,
|
|
||||||
}: Props) {
|
|
||||||
const [selectedModules, setSelectedModules] = useState<Module[]>([]);
|
|
||||||
const [avoidRepeatedExams, setAvoidRepeatedExams] = useState(true);
|
|
||||||
const [variant, setVariant] = useState<Variant>("full");
|
|
||||||
|
|
||||||
const { stats } = useStats(user?.id);
|
const {stats} = useStats(user?.id);
|
||||||
const { sessions, isLoading, reload } = useSessions(user.id);
|
const {sessions, isLoading, reload} = useSessions(user.id);
|
||||||
|
|
||||||
const state = useExamStore((state) => state);
|
const state = useExamStore((state) => state);
|
||||||
|
|
||||||
const toggleModule = (module: Module) => {
|
const toggleModule = (module: Module) => {
|
||||||
const modules = selectedModules.filter((x) => x !== module);
|
const modules = selectedModules.filter((x) => x !== module);
|
||||||
setSelectedModules((prev) =>
|
setSelectedModules((prev) => (prev.includes(module) ? modules : [...modules, module]));
|
||||||
prev.includes(module) ? modules : [...modules, module],
|
};
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadSession = async (session: Session) => {
|
const loadSession = async (session: Session) => {
|
||||||
state.setSelectedModules(session.selectedModules);
|
state.setSelectedModules(session.selectedModules);
|
||||||
state.setExam(session.exam);
|
state.setExam(session.exam);
|
||||||
state.setExams(session.exams);
|
state.setExams(session.exams);
|
||||||
state.setSessionId(session.sessionId);
|
state.setSessionId(session.sessionId);
|
||||||
state.setAssignment(session.assignment);
|
state.setAssignment(session.assignment);
|
||||||
state.setExerciseIndex(session.exerciseIndex);
|
state.setExerciseIndex(session.exerciseIndex);
|
||||||
state.setPartIndex(session.partIndex);
|
state.setPartIndex(session.partIndex);
|
||||||
state.setModuleIndex(session.moduleIndex);
|
state.setModuleIndex(session.moduleIndex);
|
||||||
state.setTimeSpent(session.timeSpent);
|
state.setTimeSpent(session.timeSpent);
|
||||||
state.setUserSolutions(session.userSolutions);
|
state.setUserSolutions(session.userSolutions);
|
||||||
state.setShowSolutions(false);
|
state.setShowSolutions(false);
|
||||||
state.setQuestionIndex(session.questionIndex);
|
state.setQuestionIndex(session.questionIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="relative flex h-full w-full flex-col gap-8 md:gap-16">
|
<div className="relative flex h-full w-full flex-col gap-8 md:gap-16">
|
||||||
{user && (
|
{user && (
|
||||||
<ProfileSummary
|
<ProfileSummary
|
||||||
user={user}
|
user={user}
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
icon: (
|
icon: <BsBook className="text-ielts-reading h-6 w-6 md:h-8 md:w-8" />,
|
||||||
<BsBook className="text-ielts-reading h-6 w-6 md:h-8 md:w-8" />
|
label: "Reading",
|
||||||
),
|
value: totalExamsByModule(stats, "reading"),
|
||||||
label: "Reading",
|
tooltip: "The amount of reading exams performed.",
|
||||||
value: totalExamsByModule(stats, "reading"),
|
},
|
||||||
tooltip: "The amount of reading exams performed.",
|
{
|
||||||
},
|
icon: <BsHeadphones className="text-ielts-listening h-6 w-6 md:h-8 md:w-8" />,
|
||||||
{
|
label: "Listening",
|
||||||
icon: (
|
value: totalExamsByModule(stats, "listening"),
|
||||||
<BsHeadphones className="text-ielts-listening h-6 w-6 md:h-8 md:w-8" />
|
tooltip: "The amount of listening exams performed.",
|
||||||
),
|
},
|
||||||
label: "Listening",
|
{
|
||||||
value: totalExamsByModule(stats, "listening"),
|
icon: <BsPen className="text-ielts-writing h-6 w-6 md:h-8 md:w-8" />,
|
||||||
tooltip: "The amount of listening exams performed.",
|
label: "Writing",
|
||||||
},
|
value: totalExamsByModule(stats, "writing"),
|
||||||
{
|
tooltip: "The amount of writing exams performed.",
|
||||||
icon: (
|
},
|
||||||
<BsPen className="text-ielts-writing h-6 w-6 md:h-8 md:w-8" />
|
{
|
||||||
),
|
icon: <BsMegaphone className="text-ielts-speaking h-6 w-6 md:h-8 md:w-8" />,
|
||||||
label: "Writing",
|
label: "Speaking",
|
||||||
value: totalExamsByModule(stats, "writing"),
|
value: totalExamsByModule(stats, "speaking"),
|
||||||
tooltip: "The amount of writing exams performed.",
|
tooltip: "The amount of speaking exams performed.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: (
|
icon: <BsClipboard className="text-ielts-level h-6 w-6 md:h-8 md:w-8" />,
|
||||||
<BsMegaphone className="text-ielts-speaking h-6 w-6 md:h-8 md:w-8" />
|
label: "Level",
|
||||||
),
|
value: totalExamsByModule(stats, "level"),
|
||||||
label: "Speaking",
|
tooltip: "The amount of level exams performed.",
|
||||||
value: totalExamsByModule(stats, "speaking"),
|
},
|
||||||
tooltip: "The amount of speaking exams performed.",
|
]}
|
||||||
},
|
/>
|
||||||
{
|
)}
|
||||||
icon: (
|
|
||||||
<BsClipboard className="text-ielts-level h-6 w-6 md:h-8 md:w-8" />
|
|
||||||
),
|
|
||||||
label: "Level",
|
|
||||||
value: totalExamsByModule(stats, "level"),
|
|
||||||
tooltip: "The amount of level exams performed.",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<section className="flex flex-col gap-3">
|
<section className="flex flex-col gap-3">
|
||||||
<span className="text-lg font-bold">About {capitalize(page)}</span>
|
<span className="text-lg font-bold">About {capitalize(page)}</span>
|
||||||
<span className="text-mti-gray-taupe">
|
<span className="text-mti-gray-taupe">
|
||||||
{page === "exercises" && (
|
{page === "exercises" && (
|
||||||
<>
|
<>
|
||||||
In the realm of language acquisition, practice makes perfect,
|
In the realm of language acquisition, practice makes perfect, and our exercises are the key to unlocking your full
|
||||||
and our exercises are the key to unlocking your full potential.
|
potential. Dive into a world of interactive and engaging exercises that cater to diverse learning styles. From grammar
|
||||||
Dive into a world of interactive and engaging exercises that
|
drills that build a strong foundation to vocabulary challenges that broaden your lexicon, our exercises are carefully
|
||||||
cater to diverse learning styles. From grammar drills that build
|
designed to make learning English both enjoyable and effective. Whether you're looking to reinforce specific
|
||||||
a strong foundation to vocabulary challenges that broaden your
|
skills or embark on a holistic language journey, our exercises are your companions in the pursuit of excellence.
|
||||||
lexicon, our exercises are carefully designed to make learning
|
Embrace the joy of learning as you navigate through a variety of activities that cater to every facet of language
|
||||||
English both enjoyable and effective. Whether you're
|
acquisition. Your linguistic adventure starts here!
|
||||||
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
|
{page === "exams" && (
|
||||||
navigate through a variety of activities that cater to every
|
<>
|
||||||
facet of language acquisition. Your linguistic adventure starts
|
Welcome to the heart of success on your English language journey! Our exams are crafted with precision to assess and
|
||||||
here!
|
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
|
||||||
{page === "exams" && (
|
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.
|
||||||
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
|
</span>
|
||||||
linguistic prowess, designed to challenge and elevate your
|
</section>
|
||||||
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.
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{sessions.length > 0 && (
|
{sessions.length > 0 && (
|
||||||
<section className="flex flex-col gap-3 md:gap-3">
|
<section className="flex flex-col gap-3 md:gap-3">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={reload}
|
onClick={reload}
|
||||||
className="text-mti-purple-light hover:text-mti-purple-dark flex cursor-pointer items-center gap-2 transition duration-300 ease-in-out"
|
className="text-mti-purple-light hover:text-mti-purple-dark flex cursor-pointer items-center gap-2 transition duration-300 ease-in-out">
|
||||||
>
|
<span className="text-mti-black text-lg font-bold">Unfinished Sessions</span>
|
||||||
<span className="text-mti-black text-lg font-bold">
|
<BsArrowRepeat className={clsx("text-xl", isLoading && "animate-spin")} />
|
||||||
Unfinished Sessions
|
</div>
|
||||||
</span>
|
</div>
|
||||||
<BsArrowRepeat
|
<span className="text-mti-gray-taupe scrollbar-hide flex gap-8 overflow-x-scroll">
|
||||||
className={clsx("text-xl", isLoading && "animate-spin")}
|
{sessions
|
||||||
/>
|
.sort((a, b) => moment(b.date).diff(moment(a.date)))
|
||||||
</div>
|
.map((session) => (
|
||||||
</div>
|
<SessionCard session={session} key={session.sessionId} reload={reload} loadSession={loadSession} />
|
||||||
<span className="text-mti-gray-taupe scrollbar-hide flex gap-8 overflow-x-scroll">
|
))}
|
||||||
{sessions
|
</span>
|
||||||
.sort((a, b) => moment(b.date).diff(moment(a.date)))
|
</section>
|
||||||
.map((session) => (
|
)}
|
||||||
<SessionCard
|
|
||||||
session={session}
|
|
||||||
key={session.sessionId}
|
|
||||||
reload={reload}
|
|
||||||
loadSession={loadSession}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</span>
|
|
||||||
</section>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<section className="-lg:flex-col -lg:items-center -lg:gap-12 mt-4 flex w-full justify-between gap-8">
|
<section className="-lg:flex-col -lg:items-center -lg:gap-12 mt-4 flex w-full justify-between gap-8">
|
||||||
<div
|
<div
|
||||||
onClick={
|
onClick={!disableSelection && !selectedModules.includes("level") ? () => toggleModule("reading") : undefined}
|
||||||
!disableSelection && !selectedModules.includes("level")
|
className={clsx(
|
||||||
? () => toggleModule("reading")
|
"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",
|
||||||
: undefined
|
selectedModules.includes("reading") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum",
|
||||||
}
|
)}>
|
||||||
className={clsx(
|
<div className="bg-ielts-reading absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
||||||
"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",
|
<BsBook className="h-7 w-7 text-white" />
|
||||||
selectedModules.includes("reading") || disableSelection
|
</div>
|
||||||
? "border-mti-purple-light"
|
<span className="font-semibold">Reading:</span>
|
||||||
: "border-mti-gray-platinum",
|
<p className="text-left text-xs">
|
||||||
)}
|
Expand your vocabulary, improve your reading comprehension and improve your ability to interpret texts in English.
|
||||||
>
|
</p>
|
||||||
<div className="bg-ielts-reading absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
{!selectedModules.includes("reading") && !selectedModules.includes("level") && !disableSelection && (
|
||||||
<BsBook className="h-7 w-7 text-white" />
|
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
||||||
</div>
|
)}
|
||||||
<span className="font-semibold">Reading:</span>
|
{(selectedModules.includes("reading") || disableSelection) && (
|
||||||
<p className="text-left text-xs">
|
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
||||||
Expand your vocabulary, improve your reading comprehension and
|
)}
|
||||||
improve your ability to interpret texts in English.
|
{selectedModules.includes("level") && <BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />}
|
||||||
</p>
|
</div>
|
||||||
{!selectedModules.includes("reading") &&
|
<div
|
||||||
!selectedModules.includes("level") &&
|
onClick={!disableSelection && !selectedModules.includes("level") ? () => toggleModule("listening") : undefined}
|
||||||
!disableSelection && (
|
className={clsx(
|
||||||
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
"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",
|
||||||
{(selectedModules.includes("reading") || disableSelection) && (
|
)}>
|
||||||
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
<div className="bg-ielts-listening absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
||||||
)}
|
<BsHeadphones className="h-7 w-7 text-white" />
|
||||||
{selectedModules.includes("level") && (
|
</div>
|
||||||
<BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />
|
<span className="font-semibold">Listening:</span>
|
||||||
)}
|
<p className="text-left text-xs">
|
||||||
</div>
|
Improve your ability to follow conversations in English and your ability to understand different accents and intonations.
|
||||||
<div
|
</p>
|
||||||
onClick={
|
{!selectedModules.includes("listening") && !selectedModules.includes("level") && !disableSelection && (
|
||||||
!disableSelection && !selectedModules.includes("level")
|
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
||||||
? () => toggleModule("listening")
|
)}
|
||||||
: undefined
|
{(selectedModules.includes("listening") || disableSelection) && (
|
||||||
}
|
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
||||||
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") && <BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />}
|
||||||
selectedModules.includes("listening") || disableSelection
|
</div>
|
||||||
? "border-mti-purple-light"
|
<div
|
||||||
: "border-mti-gray-platinum",
|
onClick={!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",
|
||||||
<div className="bg-ielts-listening absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
selectedModules.includes("writing") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum",
|
||||||
<BsHeadphones className="h-7 w-7 text-white" />
|
)}>
|
||||||
</div>
|
<div className="bg-ielts-writing absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
||||||
<span className="font-semibold">Listening:</span>
|
<BsPen className="h-7 w-7 text-white" />
|
||||||
<p className="text-left text-xs">
|
</div>
|
||||||
Improve your ability to follow conversations in English and your
|
<span className="font-semibold">Writing:</span>
|
||||||
ability to understand different accents and intonations.
|
<p className="text-left text-xs">
|
||||||
</p>
|
Allow you to practice writing in a variety of formats, from simple paragraphs to complex essays.
|
||||||
{!selectedModules.includes("listening") &&
|
</p>
|
||||||
!selectedModules.includes("level") &&
|
{!selectedModules.includes("writing") && !selectedModules.includes("level") && !disableSelection && (
|
||||||
!disableSelection && (
|
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
||||||
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
)}
|
||||||
)}
|
{(selectedModules.includes("writing") || disableSelection) && (
|
||||||
{(selectedModules.includes("listening") || disableSelection) && (
|
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
||||||
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
)}
|
||||||
)}
|
{selectedModules.includes("level") && <BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />}
|
||||||
{selectedModules.includes("level") && (
|
</div>
|
||||||
<BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />
|
<div
|
||||||
)}
|
onClick={!disableSelection && !selectedModules.includes("level") ? () => toggleModule("speaking") : undefined}
|
||||||
</div>
|
className={clsx(
|
||||||
<div
|
"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",
|
||||||
onClick={
|
selectedModules.includes("speaking") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum",
|
||||||
!disableSelection && !selectedModules.includes("level")
|
)}>
|
||||||
? () => toggleModule("writing")
|
<div className="bg-ielts-speaking absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
||||||
: undefined
|
<BsMegaphone className="h-7 w-7 text-white" />
|
||||||
}
|
</div>
|
||||||
className={clsx(
|
<span className="font-semibold">Speaking:</span>
|
||||||
"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",
|
<p className="text-left text-xs">
|
||||||
selectedModules.includes("writing") || disableSelection
|
You'll have access to interactive dialogs, pronunciation exercises and speech recordings.
|
||||||
? "border-mti-purple-light"
|
</p>
|
||||||
: "border-mti-gray-platinum",
|
{!selectedModules.includes("speaking") && !selectedModules.includes("level") && !disableSelection && (
|
||||||
)}
|
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
||||||
>
|
)}
|
||||||
<div className="bg-ielts-writing absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
{(selectedModules.includes("speaking") || disableSelection) && (
|
||||||
<BsPen className="h-7 w-7 text-white" />
|
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
||||||
</div>
|
)}
|
||||||
<span className="font-semibold">Writing:</span>
|
{selectedModules.includes("level") && <BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />}
|
||||||
<p className="text-left text-xs">
|
</div>
|
||||||
Allow you to practice writing in a variety of formats, from simple
|
{!disableSelection && (
|
||||||
paragraphs to complex essays.
|
<div
|
||||||
</p>
|
onClick={selectedModules.length === 0 || selectedModules.includes("level") ? () => toggleModule("level") : undefined}
|
||||||
{!selectedModules.includes("writing") &&
|
className={clsx(
|
||||||
!selectedModules.includes("level") &&
|
"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",
|
||||||
!disableSelection && (
|
selectedModules.includes("level") || disableSelection ? "border-mti-purple-light" : "border-mti-gray-platinum",
|
||||||
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
)}>
|
||||||
)}
|
<div className="bg-ielts-level absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
||||||
{(selectedModules.includes("writing") || disableSelection) && (
|
<BsClipboard className="h-7 w-7 text-white" />
|
||||||
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
</div>
|
||||||
)}
|
<span className="font-semibold">Level:</span>
|
||||||
{selectedModules.includes("level") && (
|
<p className="text-left text-xs">You'll be able to test your english level with multiple choice questions.</p>
|
||||||
<BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />
|
{!selectedModules.includes("level") && selectedModules.length === 0 && !disableSelection && (
|
||||||
)}
|
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
||||||
</div>
|
)}
|
||||||
<div
|
{(selectedModules.includes("level") || disableSelection) && (
|
||||||
onClick={
|
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
||||||
!disableSelection && !selectedModules.includes("level")
|
)}
|
||||||
? () => toggleModule("speaking")
|
{!selectedModules.includes("level") && selectedModules.length > 0 && (
|
||||||
: undefined
|
<BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />
|
||||||
}
|
)}
|
||||||
className={clsx(
|
</div>
|
||||||
"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
|
</section>
|
||||||
? "border-mti-purple-light"
|
<div className="-md:flex-col -md:gap-4 -md:justify-center flex w-full items-center md:justify-between">
|
||||||
: "border-mti-gray-platinum",
|
<div className="flex w-full flex-col items-center gap-3">
|
||||||
)}
|
<div
|
||||||
>
|
className="text-mti-gray-dim -md:justify-center flex w-full cursor-pointer items-center gap-3 text-sm"
|
||||||
<div className="bg-ielts-speaking absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
onClick={() => setAvoidRepeatedExams((prev) => !prev)}>
|
||||||
<BsMegaphone className="h-7 w-7 text-white" />
|
<input type="checkbox" className="hidden" />
|
||||||
</div>
|
<div
|
||||||
<span className="font-semibold">Speaking:</span>
|
className={clsx(
|
||||||
<p className="text-left text-xs">
|
"border-mti-purple-light flex h-6 w-6 items-center justify-center rounded-md border bg-white",
|
||||||
You'll have access to interactive dialogs, pronunciation
|
"transition duration-300 ease-in-out",
|
||||||
exercises and speech recordings.
|
avoidRepeatedExams && "!bg-mti-purple-light ",
|
||||||
</p>
|
)}>
|
||||||
{!selectedModules.includes("speaking") &&
|
<BsCheck color="white" className="h-full w-full" />
|
||||||
!selectedModules.includes("level") &&
|
</div>
|
||||||
!disableSelection && (
|
<span className="tooltip" data-tip="If possible, the platform will choose exams not yet done.">
|
||||||
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
Avoid Repeated Questions
|
||||||
)}
|
</span>
|
||||||
{(selectedModules.includes("speaking") || disableSelection) && (
|
</div>
|
||||||
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
<div
|
||||||
)}
|
className="text-mti-gray-dim -md:justify-center flex w-full cursor-pointer items-center gap-3 text-sm"
|
||||||
{selectedModules.includes("level") && (
|
onClick={() => setVariant((prev) => (prev === "full" ? "partial" : "full"))}>
|
||||||
<BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />
|
<input type="checkbox" className="hidden" />
|
||||||
)}
|
<div
|
||||||
</div>
|
className={clsx(
|
||||||
{!disableSelection && (
|
"border-mti-purple-light flex h-6 w-6 items-center justify-center rounded-md border bg-white",
|
||||||
<div
|
"transition duration-300 ease-in-out",
|
||||||
onClick={
|
variant === "full" && "!bg-mti-purple-light ",
|
||||||
selectedModules.length === 0 ||
|
)}>
|
||||||
selectedModules.includes("level")
|
<BsCheck color="white" className="h-full w-full" />
|
||||||
? () => toggleModule("level")
|
</div>
|
||||||
: undefined
|
<span>Full length exams</span>
|
||||||
}
|
</div>
|
||||||
className={clsx(
|
</div>
|
||||||
"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",
|
<div className="tooltip w-full" data-tip={`Your screen size is too small to do ${page}`}>
|
||||||
selectedModules.includes("level") || disableSelection
|
<Button color="purple" className="w-full max-w-xs px-12 md:hidden" disabled>
|
||||||
? "border-mti-purple-light"
|
Start Exam
|
||||||
: "border-mti-gray-platinum",
|
</Button>
|
||||||
)}
|
</div>
|
||||||
>
|
<Button
|
||||||
<div className="bg-ielts-level absolute top-0 flex h-16 w-16 -translate-y-1/2 items-center justify-center rounded-full">
|
onClick={() =>
|
||||||
<BsClipboard className="h-7 w-7 text-white" />
|
onStart(
|
||||||
</div>
|
!disableSelection ? selectedModules.sort(sortByModuleName) : ["reading", "listening", "writing", "speaking"],
|
||||||
<span className="font-semibold">Level:</span>
|
avoidRepeatedExams,
|
||||||
<p className="text-left text-xs">
|
variant,
|
||||||
You'll be able to test your english level with multiple
|
)
|
||||||
choice questions.
|
}
|
||||||
</p>
|
color="purple"
|
||||||
{!selectedModules.includes("level") &&
|
className="-md:hidden w-full max-w-xs px-12 md:self-end"
|
||||||
selectedModules.length === 0 &&
|
disabled={selectedModules.length === 0 && !disableSelection}>
|
||||||
!disableSelection && (
|
Start Exam
|
||||||
<div className="border-mti-gray-platinum mt-4 h-8 w-8 rounded-full border" />
|
</Button>
|
||||||
)}
|
</div>
|
||||||
{(selectedModules.includes("level") || disableSelection) && (
|
</div>
|
||||||
<BsCheckCircle className="text-mti-purple-light mt-4 h-8 w-8" />
|
</>
|
||||||
)}
|
);
|
||||||
{!selectedModules.includes("level") &&
|
|
||||||
selectedModules.length > 0 && (
|
|
||||||
<BsXCircle className="text-mti-red-light mt-4 h-8 w-8" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
<div className="-md:flex-col -md:gap-4 -md:justify-center flex w-full items-center md:justify-between">
|
|
||||||
<div className="flex w-full flex-col items-center gap-3">
|
|
||||||
<div
|
|
||||||
className="text-mti-gray-dim -md:justify-center flex w-full cursor-pointer items-center gap-3 text-sm"
|
|
||||||
onClick={() => setAvoidRepeatedExams((prev) => !prev)}
|
|
||||||
>
|
|
||||||
<input type="checkbox" className="hidden" />
|
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
"border-mti-purple-light flex h-6 w-6 items-center justify-center rounded-md border bg-white",
|
|
||||||
"transition duration-300 ease-in-out",
|
|
||||||
avoidRepeatedExams && "!bg-mti-purple-light ",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<BsCheck color="white" className="h-full w-full" />
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
className="tooltip"
|
|
||||||
data-tip="If possible, the platform will choose exams not yet done."
|
|
||||||
>
|
|
||||||
Avoid Repeated Questions
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="text-mti-gray-dim -md:justify-center flex w-full cursor-pointer items-center gap-3 text-sm"
|
|
||||||
// onClick={() => setVariant((prev) => (prev === "full" ? "partial" : "full"))}>
|
|
||||||
>
|
|
||||||
<input type="checkbox" className="hidden" disabled />
|
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
"border-mti-purple-light flex h-6 w-6 items-center justify-center rounded-md border bg-white",
|
|
||||||
"transition duration-300 ease-in-out",
|
|
||||||
variant === "full" && "!bg-mti-purple-light ",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<BsCheck color="white" className="h-full w-full" />
|
|
||||||
</div>
|
|
||||||
<span>Full length exams</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="tooltip w-full"
|
|
||||||
data-tip={`Your screen size is too small to do ${page}`}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
color="purple"
|
|
||||||
className="w-full max-w-xs px-12 md:hidden"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
Start Exam
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
onClick={() =>
|
|
||||||
onStart(
|
|
||||||
!disableSelection
|
|
||||||
? selectedModules.sort(sortByModuleName)
|
|
||||||
: ["reading", "listening", "writing", "speaking"],
|
|
||||||
avoidRepeatedExams,
|
|
||||||
variant,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
color="purple"
|
|
||||||
className="-md:hidden w-full max-w-xs px-12 md:self-end"
|
|
||||||
disabled={selectedModules.length === 0 && !disableSelection}
|
|
||||||
>
|
|
||||||
Start Exam
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user