Added the ability to choose a difficulty when generating an exam

This commit is contained in:
Tiago Ribeiro
2024-02-10 13:26:08 +00:00
parent 2e894622d0
commit dc3373be6a
6 changed files with 200 additions and 58 deletions

View File

@@ -1,6 +1,6 @@
import Input from "@/components/Low/Input";
import Select from "@/components/Low/Select";
import {Exercise, InteractiveSpeakingExercise, SpeakingExam, SpeakingExercise} from "@/interfaces/exam";
import {Difficulty, Exercise, InteractiveSpeakingExercise, SpeakingExam, SpeakingExercise} from "@/interfaces/exam";
import {AVATARS} from "@/resources/speakingAvatars";
import useExamStore from "@/stores/examStore";
import {getExamById} from "@/utils/exams";
@@ -17,7 +17,19 @@ import {BsArrowRepeat, BsCheck} from "react-icons/bs";
import {toast} from "react-toastify";
import {v4} from "uuid";
const PartTab = ({part, index, setPart}: {part?: SpeakingPart; index: number; setPart: (part?: SpeakingPart) => void}) => {
const DIFFICULTIES: Difficulty[] = ["easy", "medium", "hard"];
const PartTab = ({
part,
index,
difficulty,
setPart,
}: {
part?: SpeakingPart;
difficulty: Difficulty;
index: number;
setPart: (part?: SpeakingPart) => void;
}) => {
const [gender, setGender] = useState<"male" | "female">("male");
const [isLoading, setIsLoading] = useState(false);
@@ -25,8 +37,11 @@ const PartTab = ({part, index, setPart}: {part?: SpeakingPart; index: number; se
setPart(undefined);
setIsLoading(true);
const url = new URLSearchParams();
url.append("difficulty", difficulty);
axios
.get(`/api/exam/speaking/generate/speaking_task_${index}`)
.get(`/api/exam/speaking/generate/speaking_task_${index}?${url.toString()}`)
.then((result) => {
playSound(typeof result.data === "string" ? "error" : "check");
if (typeof result.data === "string") return toast.error("Something went wrong, please try to generate again.");
@@ -174,6 +189,7 @@ const SpeakingGeneration = () => {
const [minTimer, setMinTimer] = useState(14);
const [isLoading, setIsLoading] = useState(false);
const [resultingExam, setResultingExam] = useState<SpeakingExam>();
const [difficulty, setDifficulty] = useState<Difficulty>(sample(DIFFICULTIES)!);
useEffect(() => {
const parts = [part1, part2, part3].filter((x) => !!x);
@@ -213,6 +229,7 @@ const SpeakingGeneration = () => {
setPart1(undefined);
setPart2(undefined);
setPart3(undefined);
setDifficulty(sample(DIFFICULTIES)!);
setMinTimer(14);
})
.catch((error) => {
@@ -240,15 +257,26 @@ const SpeakingGeneration = () => {
return (
<>
<div className="flex flex-col gap-3">
<label className="font-normal text-base text-mti-gray-dim">Timer</label>
<Input
type="number"
name="minTimer"
onChange={(e) => setMinTimer(parseInt(e) < 5 ? 5 : parseInt(e))}
value={minTimer}
className="max-w-[300px]"
/>
<div className="flex gap-4 w-1/2">
<div className="flex flex-col gap-3">
<label className="font-normal text-base text-mti-gray-dim">Timer</label>
<Input
type="number"
name="minTimer"
onChange={(e) => setMinTimer(parseInt(e) < 5 ? 5 : parseInt(e))}
value={minTimer}
className="max-w-[300px]"
/>
</div>
<div className="flex flex-col gap-3 w-full">
<label className="font-normal text-base text-mti-gray-dim">Difficulty</label>
<Select
options={DIFFICULTIES.map((x) => ({value: x, label: capitalize(x)}))}
onChange={(value) => (value ? setDifficulty(value.value as Difficulty) : null)}
value={{value: difficulty, label: capitalize(difficulty)}}
disabled={!!part1 || !!part2 || !!part3}
/>
</div>
</div>
<Tab.Group>
@@ -293,7 +321,7 @@ const SpeakingGeneration = () => {
{part: part2, setPart: setPart2},
{part: part3, setPart: setPart3},
].map(({part, setPart}, index) => (
<PartTab part={part} index={index + 1} key={index} setPart={setPart} />
<PartTab difficulty={difficulty} part={part} index={index + 1} key={index} setPart={setPart} />
))}
</Tab.Panels>
</Tab.Group>