Listening preview and some more patches
This commit is contained in:
@@ -80,10 +80,6 @@ const SettingsEditor: React.FC<SettingsEditorProps> = ({
|
||||
});
|
||||
}, [updateLocalAndScheduleGlobal]);
|
||||
|
||||
const submitExam = () => {
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`flex flex-col gap-8 border bg-ielts-${module}/20 rounded-3xl p-8 w-1/3 h-fit`}>
|
||||
<div className={`w-full flex justify-center text-ielts-${module} font-bold text-xl`}>{sectionLabel} Settings</div>
|
||||
@@ -92,7 +88,7 @@ const SettingsEditor: React.FC<SettingsEditorProps> = ({
|
||||
title="Category"
|
||||
module={module}
|
||||
open={localSettings.isCategoryDropdownOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isCategoryDropdownOpen: isOpen })}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isCategoryDropdownOpen: isOpen }, false)}
|
||||
>
|
||||
<Input
|
||||
key={`section-${sectionId}`}
|
||||
@@ -108,7 +104,7 @@ const SettingsEditor: React.FC<SettingsEditorProps> = ({
|
||||
title="Divider"
|
||||
module={module}
|
||||
open={localSettings.isIntroDropdownOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isIntroDropdownOpen: isOpen })}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isIntroDropdownOpen: isOpen }, false)}
|
||||
>
|
||||
<div className="flex flex-col gap-3 w-full">
|
||||
<Select
|
||||
|
||||
@@ -74,7 +74,7 @@ const LevelSettings: React.FC = () => {
|
||||
}
|
||||
contentWrapperClassName={"pt-4 px-2 bg-white rounded-b-lg shadow-md transition-all duration-300 ease-in-out"}
|
||||
open={localSettings.isExerciseDropdownOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen })}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen }, false)}
|
||||
>
|
||||
<ExercisePicker
|
||||
module="level"
|
||||
|
||||
@@ -8,17 +8,33 @@ import { Generating, ListeningSectionSettings } from "@/stores/examEditor/types"
|
||||
import Option from "@/interfaces/option";
|
||||
import useExamEditorStore from "@/stores/examEditor";
|
||||
import useSettingsState from "../Hooks/useSettingsState";
|
||||
import { ListeningPart } from "@/interfaces/exam";
|
||||
import { ListeningExam, ListeningPart } from "@/interfaces/exam";
|
||||
import Input from "@/components/Low/Input";
|
||||
import openDetachedTab from "@/utils/popout";
|
||||
import { useRouter } from "next/router";
|
||||
import axios from "axios";
|
||||
import { usePersistentExamStore } from "@/stores/examStore";
|
||||
import { playSound } from "@/utils/sound";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
const ListeningSettings: React.FC = () => {
|
||||
const {currentModule } = useExamEditorStore();
|
||||
const router = useRouter();
|
||||
const {currentModule, title } = useExamEditorStore();
|
||||
const {
|
||||
focusedSection,
|
||||
difficulty,
|
||||
sections,
|
||||
minTimer,
|
||||
isPrivate
|
||||
} = useExamEditorStore(state => state.modules[currentModule]);
|
||||
|
||||
const {
|
||||
setExam,
|
||||
setExerciseIndex,
|
||||
setPartIndex,
|
||||
setQuestionIndex,
|
||||
} = usePersistentExamStore();
|
||||
|
||||
const { localSettings, updateLocalAndScheduleGlobal } = useSettingsState<ListeningSectionSettings>(
|
||||
currentModule,
|
||||
focusedSection
|
||||
@@ -61,22 +77,90 @@ const ListeningSettings: React.FC = () => {
|
||||
updateLocalAndScheduleGlobal({ topic });
|
||||
}, [updateLocalAndScheduleGlobal]);
|
||||
|
||||
const submitListening = () => {
|
||||
if (title === "") {
|
||||
toast.error("Enter a title for the exam!");
|
||||
return;
|
||||
}
|
||||
const exam: ListeningExam = {
|
||||
parts: sections.map((s) => {
|
||||
const exercise = s.state as ListeningPart;
|
||||
return {
|
||||
...exercise,
|
||||
intro: localSettings.currentIntro,
|
||||
category: localSettings.category
|
||||
};
|
||||
}),
|
||||
isDiagnostic: false,
|
||||
minTimer,
|
||||
module: "listening",
|
||||
id: title,
|
||||
variant: sections.length === 4 ? "full" : "partial",
|
||||
difficulty,
|
||||
private: isPrivate,
|
||||
};
|
||||
|
||||
axios.post(`/api/exam/listening`, exam)
|
||||
.then((result) => {
|
||||
playSound("sent");
|
||||
toast.success(`Submitted Exam ID: ${result.data.id}`);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
toast.error(error.response.data.error || "Something went wrong while submitting, please try again later.");
|
||||
})
|
||||
}
|
||||
|
||||
const preview = () => {
|
||||
setExam({
|
||||
parts: sections.map((s) => {
|
||||
const exercise = s.state as ListeningPart;
|
||||
return {
|
||||
...exercise,
|
||||
intro: localSettings.currentIntro,
|
||||
category: localSettings.category
|
||||
};
|
||||
}),
|
||||
minTimer,
|
||||
module: "listening",
|
||||
id: title,
|
||||
isDiagnostic: false,
|
||||
variant: undefined,
|
||||
difficulty,
|
||||
private: isPrivate,
|
||||
} as ListeningExam);
|
||||
setExerciseIndex(0);
|
||||
setQuestionIndex(0);
|
||||
setPartIndex(0);
|
||||
openDetachedTab("popout?type=Exam&module=listening", router)
|
||||
}
|
||||
|
||||
const canPreview = sections.some(
|
||||
(s) => (s.state as ListeningPart).exercises && (s.state as ListeningPart).exercises.length > 0
|
||||
);
|
||||
|
||||
const canSubmit = sections.every(
|
||||
(s) => (s.state as ListeningPart).exercises &&
|
||||
(s.state as ListeningPart).exercises.length > 0 &&
|
||||
(s.state as ListeningPart).audio !== undefined
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingsEditor
|
||||
sectionLabel={`Section ${focusedSection}`}
|
||||
sectionId={focusedSection}
|
||||
module="listening"
|
||||
introPresets={[defaultPresets[focusedSection - 1]]}
|
||||
preview={()=> {}}
|
||||
canPreview={false}
|
||||
canSubmit={false}
|
||||
submitModule={()=> {}}
|
||||
canPreview={canPreview}
|
||||
canSubmit={canSubmit}
|
||||
preview={preview}
|
||||
submitModule={submitListening}
|
||||
>
|
||||
<Dropdown
|
||||
title="Audio Context"
|
||||
module={currentModule}
|
||||
open={localSettings.isAudioContextOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isAudioContextOpen: isOpen })}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isAudioContextOpen: isOpen }, false)}
|
||||
>
|
||||
<div className="flex flex-row gap-2 items-center px-2 pb-4">
|
||||
<div className="flex flex-col flex-grow gap-4 px-2">
|
||||
@@ -105,7 +189,7 @@ const ListeningSettings: React.FC = () => {
|
||||
title="Add Exercises"
|
||||
module={currentModule}
|
||||
open={localSettings.isExerciseDropdownOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen })}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen }, false)}
|
||||
disabled={currentSection.script === undefined && currentSection.audio === undefined}
|
||||
>
|
||||
<ExercisePicker
|
||||
|
||||
@@ -85,6 +85,10 @@ const ReadingSettings: React.FC = () => {
|
||||
);
|
||||
|
||||
const submitReading = () => {
|
||||
if (title === "") {
|
||||
toast.error("Enter a title for the exam!");
|
||||
return;
|
||||
}
|
||||
const exam: ReadingExam = {
|
||||
parts: sections.map((s) => {
|
||||
const exercise = s.state as ReadingPart;
|
||||
@@ -154,7 +158,7 @@ const ReadingSettings: React.FC = () => {
|
||||
title="Generate Passage"
|
||||
module={currentModule}
|
||||
open={localSettings.isPassageOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isPassageOpen: isOpen })}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isPassageOpen: isOpen }, false)}
|
||||
>
|
||||
<div className="flex flex-row gap-2 items-center px-2 pb-4">
|
||||
<div className="flex flex-col flex-grow gap-4 px-2">
|
||||
@@ -184,7 +188,7 @@ const ReadingSettings: React.FC = () => {
|
||||
module={currentModule}
|
||||
open={localSettings.isExerciseDropdownOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen })}
|
||||
disabled={currentSection.text.content === "" || currentSection.text.title === ""}
|
||||
disabled={currentSection.text === undefined || currentSection.text.content === "" || currentSection.text.title === ""}
|
||||
>
|
||||
<ExercisePicker
|
||||
module="reading"
|
||||
|
||||
@@ -113,7 +113,7 @@ const SpeakingSettings: React.FC = () => {
|
||||
title="Generate Script"
|
||||
module={currentModule}
|
||||
open={localSettings.isExerciseDropdownOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen })}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen }, false)}
|
||||
>
|
||||
|
||||
<div className={clsx("gap-2 px-2 pb-4", focusedSection === 1 ? "flex flex-col w-full" : "flex flex-row items-center" )}>
|
||||
|
||||
@@ -149,7 +149,7 @@ const WritingSettings: React.FC = () => {
|
||||
title="Generate Instructions"
|
||||
module={currentModule}
|
||||
open={localSettings.isExerciseDropdownOpen}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen })}
|
||||
setIsOpen={(isOpen: boolean) => updateLocalAndScheduleGlobal({ isExerciseDropdownOpen: isOpen }, false)}
|
||||
>
|
||||
|
||||
<div className="flex flex-row gap-2 items-center px-2 pb-4">
|
||||
|
||||
Reference in New Issue
Block a user