From 153d7f54484c868c97e249e8a4aae6b9677b85c9 Mon Sep 17 00:00:00 2001 From: Carlos-Mesquita Date: Tue, 12 Nov 2024 17:53:16 +0000 Subject: [PATCH] isPractice hotfix --- .../ExamEditor/ExercisePicker/exercises.ts | 30 +++++++++++++++++-- .../Exercises/Blanks/Letters/index.tsx | 1 + .../Exercises/Blanks/MultipleChoice/index.tsx | 11 +++---- .../Exercises/Blanks/WriteBlankFill/index.tsx | 1 + .../Exercises/MatchSentences/index.tsx | 1 + .../MultipleChoice/Underline/index.tsx | 1 + .../MultipleChoice/Vanilla/index.tsx | 1 + .../Speaking/InteractiveSpeaking.tsx | 1 + .../Exercises/Speaking/Speaking1.tsx | 1 + .../Exercises/Speaking/Speaking2.tsx | 1 + .../ExamEditor/Exercises/Speaking/index.tsx | 17 ++++++++--- .../ExamEditor/Exercises/TrueFalse/index.tsx | 4 ++- .../Exercises/WriteBlanks/index.tsx | 1 + .../Exercises/WriteBlanksForm/index.tsx | 1 + .../ExamEditor/Exercises/Writing/index.tsx | 1 + .../SectionExercises/exercises.tsx | 29 ++++++++++++++++++ .../SectionExercises/index.tsx | 2 +- .../SettingsEditor/Shared/SectionPicker.tsx | 24 ++++++++------- .../ExamEditor/SettingsEditor/level.tsx | 4 +-- src/stores/examEditor/defaults.ts | 3 +- src/stores/examEditor/types.ts | 2 +- 21 files changed, 109 insertions(+), 28 deletions(-) diff --git a/src/components/ExamEditor/ExercisePicker/exercises.ts b/src/components/ExamEditor/ExercisePicker/exercises.ts index 16216b9e..158f695a 100644 --- a/src/components/ExamEditor/ExercisePicker/exercises.ts +++ b/src/components/ExamEditor/ExercisePicker/exercises.ts @@ -351,7 +351,19 @@ const EXERCISES: ExerciseGen[] = [ type: "speaking_1", icon: FaComments, extra: [ - generate() + generate(), + { + label: "First Topic", + param: "first_topic", + value: "", + type: "text" + }, + { + label: "Second Topic", + param: "second_topic", + value: "", + type: "text" + }, ], module: "speaking" }, @@ -360,7 +372,13 @@ const EXERCISES: ExerciseGen[] = [ type: "speaking_2", icon: FaUserFriends, extra: [ - generate() + generate(), + { + label: "Topic", + param: "topic", + value: "", + type: "text" + }, ], module: "speaking" }, @@ -369,7 +387,13 @@ const EXERCISES: ExerciseGen[] = [ type: "speaking_3", icon: FaHandshake, extra: [ - generate() + generate(), + { + label: "Topic", + param: "topic", + value: "", + type: "text" + }, ], module: "speaking" }, diff --git a/src/components/ExamEditor/Exercises/Blanks/Letters/index.tsx b/src/components/ExamEditor/Exercises/Blanks/Letters/index.tsx index ef2fff68..d4e1ad76 100644 --- a/src/components/ExamEditor/Exercises/Blanks/Letters/index.tsx +++ b/src/components/ExamEditor/Exercises/Blanks/Letters/index.tsx @@ -112,6 +112,7 @@ const FillBlanksLetters: React.FC<{ exercise: FillBlanksExercise; sectionId: num newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex ); + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); diff --git a/src/components/ExamEditor/Exercises/Blanks/MultipleChoice/index.tsx b/src/components/ExamEditor/Exercises/Blanks/MultipleChoice/index.tsx index e83adcbc..35b87f74 100644 --- a/src/components/ExamEditor/Exercises/Blanks/MultipleChoice/index.tsx +++ b/src/components/ExamEditor/Exercises/Blanks/MultipleChoice/index.tsx @@ -108,6 +108,7 @@ const FillBlanksMC: React.FC<{ exercise: FillBlanksExercise; sectionId: number } newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex ); + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); @@ -200,7 +201,7 @@ const FillBlanksMC: React.FC<{ exercise: FillBlanksExercise; sectionId: number } useEffect(() => { validateBlanks(blanksState.blanks, answers, alerts, setAlerts); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, [answers, blanksState.blanks, blanksState.textMode]); useEffect(() => { @@ -226,16 +227,16 @@ const FillBlanksMC: React.FC<{ exercise: FillBlanksExercise; sectionId: number } solution ]) )); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleBlankRemove = (blankId: number) => { if (!editing) setEditing(true); - + const newAnswers = new Map(answers); newAnswers.delete(blankId.toString()); setAnswers(newAnswers); - + setLocal(prev => ({ ...prev, words: (prev.words as FillBlanksMCOption[]).filter(w => w.id !== blankId.toString()), @@ -244,7 +245,7 @@ const FillBlanksMC: React.FC<{ exercise: FillBlanksExercise; sectionId: number } solution })) })); - + blanksDispatcher({ type: "REMOVE_BLANK", payload: blankId }); }; diff --git a/src/components/ExamEditor/Exercises/Blanks/WriteBlankFill/index.tsx b/src/components/ExamEditor/Exercises/Blanks/WriteBlankFill/index.tsx index 9acf2018..833747b0 100644 --- a/src/components/ExamEditor/Exercises/Blanks/WriteBlankFill/index.tsx +++ b/src/components/ExamEditor/Exercises/Blanks/WriteBlankFill/index.tsx @@ -79,6 +79,7 @@ const WriteBlanksFill: React.FC<{ exercise: WriteBlanksExercise; sectionId: numb newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex ); + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); diff --git a/src/components/ExamEditor/Exercises/MatchSentences/index.tsx b/src/components/ExamEditor/Exercises/MatchSentences/index.tsx index a2f25889..52a6ee3f 100644 --- a/src/components/ExamEditor/Exercises/MatchSentences/index.tsx +++ b/src/components/ExamEditor/Exercises/MatchSentences/index.tsx @@ -76,6 +76,7 @@ const MatchSentences: React.FC<{ exercise: MatchSentencesExercise, sectionId: nu newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex ); + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); diff --git a/src/components/ExamEditor/Exercises/MultipleChoice/Underline/index.tsx b/src/components/ExamEditor/Exercises/MultipleChoice/Underline/index.tsx index 0f5cc199..b3e366c3 100644 --- a/src/components/ExamEditor/Exercises/MultipleChoice/Underline/index.tsx +++ b/src/components/ExamEditor/Exercises/MultipleChoice/Underline/index.tsx @@ -107,6 +107,7 @@ const UnderlineMultipleChoice: React.FC<{exercise: MultipleChoiceExercise, secti newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex ); + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); diff --git a/src/components/ExamEditor/Exercises/MultipleChoice/Vanilla/index.tsx b/src/components/ExamEditor/Exercises/MultipleChoice/Vanilla/index.tsx index 1b2ab49b..26f50f8c 100644 --- a/src/components/ExamEditor/Exercises/MultipleChoice/Vanilla/index.tsx +++ b/src/components/ExamEditor/Exercises/MultipleChoice/Vanilla/index.tsx @@ -186,6 +186,7 @@ const MultipleChoice: React.FC = ({ exercise, sectionId, op newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex ); + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); diff --git a/src/components/ExamEditor/Exercises/Speaking/InteractiveSpeaking.tsx b/src/components/ExamEditor/Exercises/Speaking/InteractiveSpeaking.tsx index 0db5214a..d9c2f8da 100644 --- a/src/components/ExamEditor/Exercises/Speaking/InteractiveSpeaking.tsx +++ b/src/components/ExamEditor/Exercises/Speaking/InteractiveSpeaking.tsx @@ -55,6 +55,7 @@ const InteractiveSpeaking: React.FC = ({ sectionId, exercise, module = "s ...state, isPractice: !local.isPractice }; + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: updatedExercise, module: module } }); }, }); diff --git a/src/components/ExamEditor/Exercises/Speaking/Speaking1.tsx b/src/components/ExamEditor/Exercises/Speaking/Speaking1.tsx index eabdb02f..d8a6e8ca 100644 --- a/src/components/ExamEditor/Exercises/Speaking/Speaking1.tsx +++ b/src/components/ExamEditor/Exercises/Speaking/Speaking1.tsx @@ -67,6 +67,7 @@ const Speaking1: React.FC = ({ sectionId, exercise, module = "speaking" } ...state, isPractice: !local.isPractice }; + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: updatedExercise, module: module } }); }, }); diff --git a/src/components/ExamEditor/Exercises/Speaking/Speaking2.tsx b/src/components/ExamEditor/Exercises/Speaking/Speaking2.tsx index 50dbf003..85918188 100644 --- a/src/components/ExamEditor/Exercises/Speaking/Speaking2.tsx +++ b/src/components/ExamEditor/Exercises/Speaking/Speaking2.tsx @@ -54,6 +54,7 @@ const Speaking2: React.FC = ({ sectionId, exercise, module = "speaking" } ...state, isPractice: !local.isPractice }; + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: updatedExercise, module: module } }); }, }); diff --git a/src/components/ExamEditor/Exercises/Speaking/index.tsx b/src/components/ExamEditor/Exercises/Speaking/index.tsx index 0874b526..a54ee966 100644 --- a/src/components/ExamEditor/Exercises/Speaking/index.tsx +++ b/src/components/ExamEditor/Exercises/Speaking/index.tsx @@ -3,21 +3,30 @@ import { SpeakingExercise, InteractiveSpeakingExercise } from "@/interfaces/exam import Speaking2 from "./Speaking2"; import InteractiveSpeaking from "./InteractiveSpeaking"; import Speaking1 from "./Speaking1"; +import { Module } from "@/interfaces"; interface Props { sectionId: number; exercise: SpeakingExercise | InteractiveSpeakingExercise; + qId?: number; + module: Module; } -const Speaking: React.FC = ({ sectionId, exercise }) => { - const { currentModule } = useExamEditorStore(); +const Speaking: React.FC = ({ sectionId, exercise, qId, module = "speaking" }) => { + const { dispatch } = useExamEditorStore(); const { state } = useExamEditorStore( - (state) => state.modules[currentModule].sections.find((section) => section.sectionId === sectionId)! + (state) => state.modules[module].sections.find((section) => section.sectionId === sectionId)! ); + const onFocus = () => { + if (qId) { + dispatch({ type: "UPDATE_SECTION_SINGLE_FIELD", payload: { module, sectionId, field: "focusedExercise", value: { questionId: qId, id: exercise.id } } }) + } + } + return ( <> -
+
{sectionId === 1 && } diff --git a/src/components/ExamEditor/Exercises/TrueFalse/index.tsx b/src/components/ExamEditor/Exercises/TrueFalse/index.tsx index a5dc9bc1..be850a86 100644 --- a/src/components/ExamEditor/Exercises/TrueFalse/index.tsx +++ b/src/components/ExamEditor/Exercises/TrueFalse/index.tsx @@ -107,12 +107,13 @@ const TrueFalse: React.FC<{ exercise: TrueFalseExercise, sectionId: number }> = onPractice: () => { const updatedExercise = { ...local, - isPractice: !local.isPractice + isPractice: false }; const newState = { ...section }; newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex ); + updateLocal({...local, isPractice: !local.isPractice}) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); @@ -140,6 +141,7 @@ const TrueFalse: React.FC<{ exercise: TrueFalseExercise, sectionId: number }> = handleDelete={handleDelete} handleDiscard={handleDiscard} handlePractice={handlePractice} + isEvaluationEnabled={!local.isPractice} /> {alerts.length > 0 && } ex.id === exercise.id ? updatedExercise : ex ); + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); diff --git a/src/components/ExamEditor/Exercises/WriteBlanksForm/index.tsx b/src/components/ExamEditor/Exercises/WriteBlanksForm/index.tsx index 92271aad..d6011e84 100644 --- a/src/components/ExamEditor/Exercises/WriteBlanksForm/index.tsx +++ b/src/components/ExamEditor/Exercises/WriteBlanksForm/index.tsx @@ -71,6 +71,7 @@ const WriteBlanksForm: React.FC<{ sectionId: number; exercise: WriteBlanksExerci newState.exercises = newState.exercises.map((ex) => ex.id === exercise.id ? updatedExercise : ex ); + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); diff --git a/src/components/ExamEditor/Exercises/Writing/index.tsx b/src/components/ExamEditor/Exercises/Writing/index.tsx index 2370e562..231b6198 100644 --- a/src/components/ExamEditor/Exercises/Writing/index.tsx +++ b/src/components/ExamEditor/Exercises/Writing/index.tsx @@ -68,6 +68,7 @@ const Writing: React.FC = ({ sectionId, exercise, module, index }) => { ...state, isPractice: !local.isPractice }; + setLocal((prev) => ({...prev, isPractice: !local.isPractice})) dispatch({ type: 'UPDATE_SECTION_STATE', payload: { sectionId, update: newState, module: currentModule } }); } }); diff --git a/src/components/ExamEditor/SectionRenderer/SectionExercises/exercises.tsx b/src/components/ExamEditor/SectionRenderer/SectionExercises/exercises.tsx index 5e6a7ce8..93de63e7 100644 --- a/src/components/ExamEditor/SectionRenderer/SectionExercises/exercises.tsx +++ b/src/components/ExamEditor/SectionRenderer/SectionExercises/exercises.tsx @@ -7,6 +7,7 @@ import TrueFalse from "../../Exercises/TrueFalse"; import fillBlanks from "./fillBlanks"; import MatchSentences from "../../Exercises/MatchSentences"; import Writing from "../../Exercises/Writing"; +import Speaking from "../../Exercises/Speaking"; const getExerciseItems = (exercises: Exercise[], sectionId: number): ExerciseItem[] => { const items: ExerciseItem[] = exercises.map((exercise, index) => { @@ -78,6 +79,34 @@ const getExerciseItems = (exercises: Exercise[], sectionId: number): ExerciseIte ), content: }; + case "speaking": + return { + id: index.toString(), + sectionId, + label: ( + + ), + content: + }; + case "interactiveSpeaking": + return { + id: index.toString(), + sectionId, + label: ( + + ), + content: + }; default: return {} as unknown as ExerciseItem; } diff --git a/src/components/ExamEditor/SectionRenderer/SectionExercises/index.tsx b/src/components/ExamEditor/SectionRenderer/SectionExercises/index.tsx index abed5be5..df3a01a3 100644 --- a/src/components/ExamEditor/SectionRenderer/SectionExercises/index.tsx +++ b/src/components/ExamEditor/SectionRenderer/SectionExercises/index.tsx @@ -181,7 +181,7 @@ const SectionExercises: React.FC<{ sectionId: number; }> = ({ sectionId }) => { } if (currentModule == "writing") return background(); - if (currentModule == "speaking") return background(); + if (currentModule == "speaking") return background(); const questions = questionItems(); diff --git a/src/components/ExamEditor/SettingsEditor/Shared/SectionPicker.tsx b/src/components/ExamEditor/SettingsEditor/Shared/SectionPicker.tsx index b27198f4..eeac2904 100644 --- a/src/components/ExamEditor/SettingsEditor/Shared/SectionPicker.tsx +++ b/src/components/ExamEditor/SettingsEditor/Shared/SectionPicker.tsx @@ -18,12 +18,12 @@ const SectionPicker: React.FC = ({ updateLocalAndScheduleGlobal }) => { const { dispatch } = useExamEditorStore(); - const [selectedValue, setSelectedValue] = React.useState(null); + const [selectedValue, setSelectedValue] = React.useState(undefined); const sectionState = useExamEditorStore(state => state.modules["level"].sections.find((s) => s.sectionId === sectionId) ); - + if (sectionState === undefined) return null; const { readingSection, listeningSection } = sectionState; @@ -32,14 +32,16 @@ const SectionPicker: React.FC = ({ const openPicker = module === "reading" ? "isReadingPickerOpen" : "isListeningPickerOpen"; const handleSectionChange = (value: number) => { - setSelectedValue(value); + const newValue = currentValue === value ? undefined : value; + setSelectedValue(newValue); + dispatch({ type: "UPDATE_SECTION_SINGLE_FIELD", payload: { sectionId, module: "level", field: module === "reading" ? "readingSection" : "listeningSection", - value: value + value: newValue } }); }; @@ -67,17 +69,19 @@ const SectionPicker: React.FC = ({ className={` flex items-center space-x-3 font-semibold cursor-pointer p-2 rounded transition-colors duration-200 - ${currentValue === num + ${currentValue === num ? `bg-ielts-${module}/90 text-white` : `hover:bg-ielts-${module}/70 text-gray-700`} `} + onClick={(e) => { + e.preventDefault(); + handleSectionChange(num); + }} > handleSectionChange(num)} + onChange={() => {}} className={` h-5 w-5 cursor-pointer accent-ielts-${module} @@ -95,4 +99,4 @@ const SectionPicker: React.FC = ({ ); }; -export default SectionPicker; \ No newline at end of file +export default SectionPicker; diff --git a/src/components/ExamEditor/SettingsEditor/level.tsx b/src/components/ExamEditor/SettingsEditor/level.tsx index 50c86664..cca0c2eb 100644 --- a/src/components/ExamEditor/SettingsEditor/level.tsx +++ b/src/components/ExamEditor/SettingsEditor/level.tsx @@ -114,7 +114,7 @@ const LevelSettings: React.FC = () => { openDetachedTab("popout?type=Exam&module=level", router) } - const speakingExercise = focusedExercise === undefined ? undefined : currentSection.exercises[focusedExercise] as SpeakingExercise | InteractiveSpeakingExercise; + const speakingExercise = focusedExercise === undefined ? undefined : currentSection.exercises.find((ex) => ex.id === focusedExercise.id) as SpeakingExercise | InteractiveSpeakingExercise; return ( { {speakingExercise !== undefined && - { +const defaultModuleSettings = (module: Module, minTimer: number): ModuleState => { const state: ModuleState = { examLabel: defaultExamLabel(module), minTimer, diff --git a/src/stores/examEditor/types.ts b/src/stores/examEditor/types.ts index 8d481600..91f032f7 100644 --- a/src/stores/examEditor/types.ts +++ b/src/stores/examEditor/types.ts @@ -92,7 +92,7 @@ export interface SectionState { genResult: {generating: string, result: Record[], module: Module} | undefined; levelGenerating: Generating[]; levelGenResults: {generating: string, result: Record[], module: Module}[]; - focusedExercise?: number; + focusedExercise?: {questionId: number; id: string} | undefined; writingSection?: number; speakingSection?: number; readingSection?: number;