Improved the Generation frontend

This commit is contained in:
Tiago Ribeiro
2024-01-22 23:34:42 +00:00
parent 506ee1e0e4
commit 67c2e06575
4 changed files with 86 additions and 38 deletions

View File

@@ -8,8 +8,8 @@ import {Tab} from "@headlessui/react";
import axios from "axios";
import clsx from "clsx";
import {useRouter} from "next/router";
import {useState} from "react";
import {BsArrowRepeat} from "react-icons/bs";
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}) => {
@@ -42,7 +42,7 @@ const PartTab = ({part, types, index, setPart}: {part?: ListeningPart; types: st
<Input type="text" placeholder="Grand Canyon..." name="topic" label="Topic" onChange={setTopic} roundness="xl" defaultValue={topic} />
<button
onClick={generate}
disabled={isLoading}
disabled={isLoading || types.length === 0}
data-tip="The passage is currently being generated"
className={clsx(
"bg-ielts-listening/70 border border-ielts-listening text-white w-full max-w-[200px] rounded-xl h-[70px]",
@@ -115,6 +115,11 @@ const ListeningGeneration = () => {
const [resultingExam, setResultingExam] = useState<ListeningExam>();
const [types, setTypes] = useState<string[]>([]);
useEffect(() => {
const parts = [part1, part2, part3, part4].filter((x) => !!x);
setMinTimer(parts.length === 0 ? 60 : parts.length * 15);
}, [part1, part2, part3, part4]);
const availableTypes = [
{type: "multipleChoice", label: "Multiple Choice"},
{type: "writeBlanksQuestions", label: "Write the Blanks: Questions"},
@@ -176,7 +181,13 @@ const ListeningGeneration = () => {
<>
<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))} value={minTimer} className="max-w-[300px]" />
<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">
@@ -204,46 +215,46 @@ const ListeningGeneration = () => {
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-listening/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-listening/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-listening focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-listening",
)
}>
Section 1
Section 1 {part1 && <BsCheck />}
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-listening/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-listening/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-listening focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-listening",
)
}>
Section 2
Section 2 {part2 && <BsCheck />}
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-listening/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-listening/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-listening focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-listening",
)
}>
Section 3
Section 3 {part3 && <BsCheck />}
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-listening/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-listening/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-listening focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-listening",
)
}>
Section 4
Section 4 {part4 && <BsCheck />}
</Tab>
</Tab.List>
<Tab.Panels>

View File

@@ -8,8 +8,8 @@ import {Tab} from "@headlessui/react";
import axios from "axios";
import clsx from "clsx";
import {useRouter} from "next/router";
import {useState} from "react";
import {BsArrowRepeat} from "react-icons/bs";
import {useEffect, useState} from "react";
import {BsArrowRepeat, BsCheck} from "react-icons/bs";
import {toast} from "react-toastify";
import {v4} from "uuid";
@@ -43,7 +43,7 @@ const PartTab = ({part, types, index, setPart}: {part?: ReadingPart; types: stri
<Input type="text" placeholder="Grand Canyon..." name="topic" label="Topic" onChange={setTopic} roundness="xl" defaultValue={topic} />
<button
onClick={generate}
disabled={isLoading}
disabled={isLoading || types.length === 0}
data-tip="The passage is currently being generated"
className={clsx(
"bg-ielts-reading/70 border border-ielts-reading text-white w-full max-w-[200px] rounded-xl h-[70px]",
@@ -92,6 +92,11 @@ const ReadingGeneration = () => {
const [isLoading, setIsLoading] = useState(false);
const [resultingExam, setResultingExam] = useState<ReadingExam>();
useEffect(() => {
const parts = [part1, part2, part3].filter((x) => !!x);
setMinTimer(parts.length === 0 ? 60 : parts.length * 20);
}, [part1, part2, part3]);
const router = useRouter();
const setExams = useExamStore((state) => state.setExams);
@@ -151,6 +156,7 @@ const ReadingGeneration = () => {
setPart1(undefined);
setPart2(undefined);
setPart3(undefined);
setMinTimer(60);
setTypes([]);
})
.catch((error) => {
@@ -164,7 +170,13 @@ const ReadingGeneration = () => {
<>
<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))} value={minTimer} className="max-w-[300px]" />
<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">
@@ -190,35 +202,35 @@ const ReadingGeneration = () => {
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-reading/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-reading/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-reading focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-reading",
)
}>
Passage 1
Passage 1 {part1 && <BsCheck />}
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-reading/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-reading/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-reading focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-reading",
)
}>
Passage 2
Passage 2 {part2 && <BsCheck />}
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-reading/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-reading/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-reading focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-reading",
)
}>
Passage 3
Passage 3 {part3 && <BsCheck />}
</Tab>
</Tab.List>
<Tab.Panels>

View File

@@ -9,7 +9,7 @@ import axios from "axios";
import clsx from "clsx";
import {useRouter} from "next/router";
import {useState} from "react";
import {BsArrowRepeat} from "react-icons/bs";
import {BsArrowRepeat, BsCheck} from "react-icons/bs";
import {toast} from "react-toastify";
const PartTab = ({part, index, setPart}: {part?: SpeakingPart; index: number; setPart: (part?: SpeakingPart) => void}) => {
@@ -114,7 +114,14 @@ const SpeakingGeneration = () => {
setIsLoading(true);
axios
.post(`/api/exam/speaking/generate/speaking`, {exercises: [part1, part2, part3].filter((x) => !!x), minTimer})
.post(`/api/exam/speaking/generate/speaking`, {
exercises: [
{...part1, type: "1"},
{...part2, type: "2"},
{...part3, type: "3"},
].filter((x) => !!x),
minTimer,
})
.then((result) => {
playSound("sent");
console.log(`Generated Exam ID: ${result.data.id}`);
@@ -152,7 +159,13 @@ const SpeakingGeneration = () => {
<>
<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))} value={minTimer} className="max-w-[300px]" />
<Input
type="number"
name="minTimer"
onChange={(e) => setMinTimer(parseInt(e) < 15 ? 15 : parseInt(e))}
value={minTimer}
className="max-w-[300px]"
/>
</div>
<Tab.Group>
@@ -160,35 +173,35 @@ const SpeakingGeneration = () => {
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Task 1
Task 1 {part1 && <BsCheck />}
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Task 2
Task 2 {part2 && <BsCheck />}
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Task 3
Task 3 {part3 && <BsCheck />}
</Tab>
</Tab.List>
<Tab.Panels>

View File

@@ -7,8 +7,8 @@ import {Tab} from "@headlessui/react";
import axios from "axios";
import clsx from "clsx";
import {useRouter} from "next/router";
import {useState} from "react";
import {BsArrowRepeat} from "react-icons/bs";
import {useEffect, useState} from "react";
import {BsArrowRepeat, BsCheck} from "react-icons/bs";
import {toast} from "react-toastify";
import {v4} from "uuid";
@@ -72,6 +72,12 @@ const WritingGeneration = () => {
const [isLoading, setIsLoading] = useState(false);
const [resultingExam, setResultingExam] = useState<WritingExam>();
useEffect(() => {
const task1Timer = task1 ? 20 : 0;
const task2Timer = task2 ? 40 : 0;
setMinTimer(task1Timer > 0 || task2Timer > 0 ? task1Timer + task2Timer : 20);
}, [task1, task2]);
const router = useRouter();
const setExams = useExamStore((state) => state.setExams);
@@ -161,7 +167,13 @@ const WritingGeneration = () => {
<>
<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))} value={minTimer} className="max-w-[300px]" />
<Input
type="number"
name="minTimer"
onChange={(e) => setMinTimer(parseInt(e) < 15 ? 15 : parseInt(e))}
value={minTimer}
className="max-w-[300px]"
/>
</div>
<Tab.Group>
@@ -169,24 +181,24 @@ const WritingGeneration = () => {
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-writing/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-writing/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-writing focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-writing",
)
}>
Task 1
Task 1 {task1 && <BsCheck />}
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-writing/70",
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-writing/70 flex gap-2 items-center justify-center",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-writing focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-writing",
)
}>
Task 2
Task 2 {task2 && <BsCheck />}
</Tab>
</Tab.List>
<Tab.Panels>