import Input from "@/components/Low/Input"; import Select from "@/components/Low/Select"; import {Exercise, InteractiveSpeakingExercise, SpeakingExam, SpeakingExercise} from "@/interfaces/exam"; import {AVATARS} from "@/resources/speakingAvatars"; import useExamStore from "@/stores/examStore"; import {getExamById} from "@/utils/exams"; import {playSound} from "@/utils/sound"; import {convertCamelCaseToReadable} from "@/utils/string"; import {Tab} from "@headlessui/react"; import axios from "axios"; import clsx from "clsx"; import {capitalize, sample, uniq} from "lodash"; import moment from "moment"; 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, index, setPart}: {part?: SpeakingPart; index: number; setPart: (part?: SpeakingPart) => void}) => { const [gender, setGender] = useState<"male" | "female">("male"); const [isLoading, setIsLoading] = useState(false); const generate = () => { setPart(undefined); setIsLoading(true); axios .get(`/api/exam/speaking/generate/speaking_task_${index}`) .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."); setPart(result.data); }) .catch((error) => { console.log(error); toast.error("Something went wrong!"); }) .finally(() => setIsLoading(false)); }; const generateVideo = () => { if (!part) return toast.error("Please generate the first part before generating the video!"); toast.info("This will take quite a while, please do not leave this page or close the tab/window."); const avatar = sample(AVATARS.filter((x) => x.gender === gender)); setIsLoading(true); const initialTime = moment(); axios .post(`/api/exam/speaking/generate/speaking/generate_${index === 3 ? "interactive" : "speaking"}_video`, {...part, avatar: avatar?.id}) .then((result) => { const isError = typeof result.data === "string" || moment().diff(initialTime, "seconds") < 60; playSound(isError ? "error" : "check"); if (isError) return toast.error("Something went wrong, please try to generate the video again."); setPart({...part, result: result.data, gender, avatar}); }) .catch((e) => { toast.error("Something went wrong!"); console.log(e); }) .finally(() => setIsLoading(false)); }; return (
setMinTimer(parseInt(e) < 5 ? 5 : parseInt(e))} value={minTimer} className="max-w-[300px]" />
clsx( "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", ) }> Exercise 1 {part1 && part1.result && } clsx( "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", ) }> Exercise 2 {part2 && part2.result && } clsx( "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", ) }> Interactive {part3 && part3.result && } {[ {part: part1, setPart: setPart1}, {part: part2, setPart: setPart2}, {part: part3, setPart: setPart3}, ].map(({part, setPart}, index) => ( ))}
{resultingExam && ( )}
); }; export default SpeakingGeneration;