Added the ability to choose a difficulty when generating an exam
This commit is contained in:
@@ -1,23 +1,30 @@
|
||||
import {LevelExam, MultipleChoiceExercise} from "@/interfaces/exam";
|
||||
import Select from "@/components/Low/Select";
|
||||
import {Difficulty, LevelExam, MultipleChoiceExercise} from "@/interfaces/exam";
|
||||
import useExamStore from "@/stores/examStore";
|
||||
import {getExamById} from "@/utils/exams";
|
||||
import {playSound} from "@/utils/sound";
|
||||
import {Tab} from "@headlessui/react";
|
||||
import axios from "axios";
|
||||
import clsx from "clsx";
|
||||
import {capitalize, sample} from "lodash";
|
||||
import {useRouter} from "next/router";
|
||||
import {useState} from "react";
|
||||
import {BsArrowRepeat} from "react-icons/bs";
|
||||
import {toast} from "react-toastify";
|
||||
import {v4} from "uuid";
|
||||
|
||||
const TaskTab = ({exam, setExam}: {exam?: LevelExam; setExam: (exam: LevelExam) => void}) => {
|
||||
const DIFFICULTIES: Difficulty[] = ["easy", "medium", "hard"];
|
||||
|
||||
const TaskTab = ({exam, difficulty, setExam}: {exam?: LevelExam; difficulty: Difficulty; setExam: (exam: LevelExam) => void}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const generate = () => {
|
||||
const url = new URLSearchParams();
|
||||
url.append("difficulty", difficulty);
|
||||
|
||||
setIsLoading(true);
|
||||
axios
|
||||
.get(`/api/exam/level/generate/level`)
|
||||
.get(`/api/exam/level/generate/level?${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.");
|
||||
@@ -107,6 +114,7 @@ const LevelGeneration = () => {
|
||||
const [generatedExam, setGeneratedExam] = useState<LevelExam>();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [resultingExam, setResultingExam] = useState<LevelExam>();
|
||||
const [difficulty, setDifficulty] = useState<Difficulty>(sample(DIFFICULTIES)!);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -163,6 +171,16 @@ const LevelGeneration = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex gap-4 w-1/2">
|
||||
<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)}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Tab.Group>
|
||||
<Tab.List className="flex space-x-1 rounded-xl bg-ielts-level/20 p-1">
|
||||
<Tab
|
||||
@@ -178,7 +196,7 @@ const LevelGeneration = () => {
|
||||
</Tab>
|
||||
</Tab.List>
|
||||
<Tab.Panels>
|
||||
<TaskTab exam={generatedExam} setExam={setGeneratedExam} />
|
||||
<TaskTab difficulty={difficulty} exam={generatedExam} setExam={setGeneratedExam} />
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
<div className="w-full flex justify-end gap-4">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Input from "@/components/Low/Input";
|
||||
import {Exercise, ListeningExam} from "@/interfaces/exam";
|
||||
import Select from "@/components/Low/Select";
|
||||
import {Difficulty, Exercise, ListeningExam} from "@/interfaces/exam";
|
||||
import useExamStore from "@/stores/examStore";
|
||||
import {getExamById} from "@/utils/exams";
|
||||
import {playSound} from "@/utils/sound";
|
||||
@@ -7,17 +8,34 @@ import {convertCamelCaseToReadable} from "@/utils/string";
|
||||
import {Tab} from "@headlessui/react";
|
||||
import axios from "axios";
|
||||
import clsx from "clsx";
|
||||
import {capitalize, sample} from "lodash";
|
||||
import {useRouter} from "next/router";
|
||||
import {useEffect, useState} from "react";
|
||||
import {BsArrowRepeat, BsCheck} from "react-icons/bs";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
const PartTab = ({part, types, index, setPart}: {part?: ListeningPart; types: string[]; index: number; setPart: (part?: ListeningPart) => void}) => {
|
||||
const DIFFICULTIES: Difficulty[] = ["easy", "medium", "hard"];
|
||||
|
||||
const PartTab = ({
|
||||
part,
|
||||
types,
|
||||
difficulty,
|
||||
index,
|
||||
setPart,
|
||||
}: {
|
||||
part?: ListeningPart;
|
||||
difficulty: Difficulty;
|
||||
types: string[];
|
||||
index: number;
|
||||
setPart: (part?: ListeningPart) => void;
|
||||
}) => {
|
||||
const [topic, setTopic] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const generate = () => {
|
||||
const url = new URLSearchParams();
|
||||
url.append("difficulty", difficulty);
|
||||
|
||||
if (topic) url.append("topic", topic);
|
||||
if (types) types.forEach((t) => url.append("exercises", t));
|
||||
|
||||
@@ -115,6 +133,7 @@ const ListeningGeneration = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [resultingExam, setResultingExam] = useState<ListeningExam>();
|
||||
const [types, setTypes] = useState<string[]>([]);
|
||||
const [difficulty, setDifficulty] = useState<Difficulty>(sample(DIFFICULTIES)!);
|
||||
|
||||
useEffect(() => {
|
||||
const part1Timer = part1 ? 5 : 0;
|
||||
@@ -148,7 +167,7 @@ const ListeningGeneration = () => {
|
||||
setIsLoading(true);
|
||||
|
||||
axios
|
||||
.post(`/api/exam/listening/generate/listening`, {parts, minTimer})
|
||||
.post(`/api/exam/listening/generate/listening`, {parts, minTimer, difficulty})
|
||||
.then((result) => {
|
||||
playSound("sent");
|
||||
console.log(`Generated Exam ID: ${result.data.id}`);
|
||||
@@ -159,6 +178,7 @@ const ListeningGeneration = () => {
|
||||
setPart2(undefined);
|
||||
setPart3(undefined);
|
||||
setPart4(undefined);
|
||||
setDifficulty(sample(DIFFICULTIES)!);
|
||||
setTypes([]);
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -186,15 +206,26 @@ const ListeningGeneration = () => {
|
||||
|
||||
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) < 15 ? 15 : 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) < 15 ? 15 : 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 || !!part4}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
@@ -271,7 +302,7 @@ const ListeningGeneration = () => {
|
||||
{part: part3, setPart: setPart3},
|
||||
{part: part4, setPart: setPart4},
|
||||
].map(({part, setPart}, index) => (
|
||||
<PartTab part={part} types={types} index={index + 1} key={index} setPart={setPart} />
|
||||
<PartTab part={part} difficulty={difficulty} types={types} index={index + 1} key={index} setPart={setPart} />
|
||||
))}
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Input from "@/components/Low/Input";
|
||||
import {ReadingExam, ReadingPart} from "@/interfaces/exam";
|
||||
import Select from "@/components/Low/Select";
|
||||
import {Difficulty, ReadingExam, ReadingPart} from "@/interfaces/exam";
|
||||
import useExamStore from "@/stores/examStore";
|
||||
import {getExamById} from "@/utils/exams";
|
||||
import {playSound} from "@/utils/sound";
|
||||
@@ -7,18 +8,35 @@ import {convertCamelCaseToReadable} from "@/utils/string";
|
||||
import {Tab} from "@headlessui/react";
|
||||
import axios from "axios";
|
||||
import clsx from "clsx";
|
||||
import {capitalize, sample} from "lodash";
|
||||
import {useRouter} from "next/router";
|
||||
import {useEffect, useState} from "react";
|
||||
import {BsArrowRepeat, BsCheck} from "react-icons/bs";
|
||||
import {toast} from "react-toastify";
|
||||
import {v4} from "uuid";
|
||||
|
||||
const PartTab = ({part, types, index, setPart}: {part?: ReadingPart; types: string[]; index: number; setPart: (part?: ReadingPart) => void}) => {
|
||||
const DIFFICULTIES: Difficulty[] = ["easy", "medium", "hard"];
|
||||
|
||||
const PartTab = ({
|
||||
part,
|
||||
types,
|
||||
difficulty,
|
||||
index,
|
||||
setPart,
|
||||
}: {
|
||||
part?: ReadingPart;
|
||||
types: string[];
|
||||
index: number;
|
||||
difficulty: Difficulty;
|
||||
setPart: (part?: ReadingPart) => void;
|
||||
}) => {
|
||||
const [topic, setTopic] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const generate = () => {
|
||||
const url = new URLSearchParams();
|
||||
url.append("difficulty", difficulty);
|
||||
|
||||
if (topic) url.append("topic", topic);
|
||||
if (types) types.forEach((t) => url.append("exercises", t));
|
||||
|
||||
@@ -92,6 +110,7 @@ const ReadingGeneration = () => {
|
||||
const [types, setTypes] = useState<string[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [resultingExam, setResultingExam] = useState<ReadingExam>();
|
||||
const [difficulty, setDifficulty] = useState<Difficulty>(sample(DIFFICULTIES)!);
|
||||
|
||||
useEffect(() => {
|
||||
const parts = [part1, part2, part3].filter((x) => !!x);
|
||||
@@ -144,6 +163,7 @@ const ReadingGeneration = () => {
|
||||
id: v4(),
|
||||
type: "academic",
|
||||
variant: parts.length === 3 ? "full" : "partial",
|
||||
difficulty,
|
||||
};
|
||||
|
||||
axios
|
||||
@@ -157,6 +177,7 @@ const ReadingGeneration = () => {
|
||||
setPart1(undefined);
|
||||
setPart2(undefined);
|
||||
setPart3(undefined);
|
||||
setDifficulty(sample(DIFFICULTIES)!);
|
||||
setMinTimer(60);
|
||||
setTypes([]);
|
||||
})
|
||||
@@ -169,15 +190,26 @@ const ReadingGeneration = () => {
|
||||
|
||||
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) < 15 ? 15 : 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) < 15 ? 15 : 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>
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
@@ -240,7 +272,7 @@ const ReadingGeneration = () => {
|
||||
{part: part2, setPart: setPart2},
|
||||
{part: part3, setPart: setPart3},
|
||||
].map(({part, setPart}, index) => (
|
||||
<PartTab part={part} types={types} index={index + 1} key={index} setPart={setPart} />
|
||||
<PartTab part={part} types={types} difficulty={difficulty} index={index + 1} key={index} setPart={setPart} />
|
||||
))}
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
import Input from "@/components/Low/Input";
|
||||
import {WritingExam, WritingExercise} from "@/interfaces/exam";
|
||||
import Select from "@/components/Low/Select";
|
||||
import {Difficulty, WritingExam, WritingExercise} from "@/interfaces/exam";
|
||||
import useExamStore from "@/stores/examStore";
|
||||
import {getExamById} from "@/utils/exams";
|
||||
import {playSound} from "@/utils/sound";
|
||||
import {Tab} from "@headlessui/react";
|
||||
import axios from "axios";
|
||||
import clsx from "clsx";
|
||||
import {capitalize, sample} from "lodash";
|
||||
import {useRouter} from "next/router";
|
||||
import {useEffect, useState} from "react";
|
||||
import {BsArrowRepeat, BsCheck} from "react-icons/bs";
|
||||
import {toast} from "react-toastify";
|
||||
import {v4} from "uuid";
|
||||
|
||||
const TaskTab = ({task, index, setTask}: {task?: string; index: number; setTask: (task: string) => void}) => {
|
||||
const DIFFICULTIES: Difficulty[] = ["easy", "medium", "hard"];
|
||||
|
||||
const TaskTab = ({task, index, difficulty, setTask}: {task?: string; difficulty: Difficulty; index: number; setTask: (task: string) => void}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const generate = () => {
|
||||
setIsLoading(true);
|
||||
|
||||
const url = new URLSearchParams();
|
||||
url.append("difficulty", difficulty);
|
||||
|
||||
axios
|
||||
.get(`/api/exam/writing/generate/writing_task${index}_general`)
|
||||
.get(`/api/exam/writing/generate/writing_task${index}_general?${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.");
|
||||
@@ -72,6 +80,7 @@ const WritingGeneration = () => {
|
||||
const [minTimer, setMinTimer] = useState(60);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [resultingExam, setResultingExam] = useState<WritingExam>();
|
||||
const [difficulty, setDifficulty] = useState<Difficulty>(sample(DIFFICULTIES)!);
|
||||
|
||||
useEffect(() => {
|
||||
const task1Timer = task1 ? 20 : 0;
|
||||
@@ -144,6 +153,7 @@ const WritingGeneration = () => {
|
||||
exercises: [...(exercise1 ? [exercise1] : []), ...(exercise2 ? [exercise2] : [])],
|
||||
id: v4(),
|
||||
variant: exercise1 && exercise2 ? "full" : "partial",
|
||||
difficulty,
|
||||
};
|
||||
|
||||
axios
|
||||
@@ -156,6 +166,7 @@ const WritingGeneration = () => {
|
||||
|
||||
setTask1(undefined);
|
||||
setTask2(undefined);
|
||||
setDifficulty(sample(DIFFICULTIES)!);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
@@ -166,15 +177,26 @@ const WritingGeneration = () => {
|
||||
|
||||
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) < 15 ? 15 : 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) < 15 ? 15 : 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={!!task1 || !!task2}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Tab.Group>
|
||||
@@ -207,7 +229,7 @@ const WritingGeneration = () => {
|
||||
{task: task1, setTask: setTask1},
|
||||
{task: task2, setTask: setTask2},
|
||||
].map(({task, setTask}, index) => (
|
||||
<TaskTab task={task} index={index + 1} key={index} setTask={setTask} />
|
||||
<TaskTab difficulty={difficulty} task={task} index={index + 1} key={index} setTask={setTask} />
|
||||
))}
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
|
||||
@@ -5,7 +5,7 @@ import {getFirestore, collection, getDocs, query, where} from "firebase/firestor
|
||||
import {withIronSessionApiRoute} from "iron-session/next";
|
||||
import {sessionOptions} from "@/lib/session";
|
||||
import {shuffle} from "lodash";
|
||||
import {Exam} from "@/interfaces/exam";
|
||||
import {Difficulty, Exam} from "@/interfaces/exam";
|
||||
import {Stat} from "@/interfaces/user";
|
||||
import {Module} from "@/interfaces";
|
||||
import axios from "axios";
|
||||
@@ -25,10 +25,21 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (!req.session.user) return res.status(401).json({ok: false});
|
||||
if (req.session.user.type !== "developer") return res.status(403).json({ok: false});
|
||||
|
||||
const {endpoint, topic, exercises} = req.query as {module: Module; endpoint: string; topic?: string; exercises?: string[]};
|
||||
const {endpoint, topic, exercises, difficulty} = req.query as {
|
||||
module: Module;
|
||||
endpoint: string;
|
||||
topic?: string;
|
||||
exercises?: string[];
|
||||
difficulty?: Difficulty;
|
||||
};
|
||||
const url = `${process.env.BACKEND_URL}/${endpoint}`;
|
||||
|
||||
const result = await axios.get(`${url}${topic && exercises ? `?topic=${topic.toLowerCase()}&exercises=${exercises.join("&exercises=")}` : ""}`, {
|
||||
const params = new URLSearchParams();
|
||||
if (topic) params.append("topic", topic);
|
||||
if (exercises) exercises.forEach((exercise) => params.append("exercises", exercise));
|
||||
if (difficulty) params.append("difficulty", difficulty);
|
||||
|
||||
const result = await axios.get(`${url}${params.toString().length > 0 ? `?${params.toString()}` : ""}`, {
|
||||
headers: {Authorization: `Bearer ${process.env.BACKEND_JWT}`},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user