ENCOA-307

This commit is contained in:
Carlos-Mesquita
2025-01-05 17:46:11 +00:00
parent af9f70880a
commit 0739e044a1
5 changed files with 135 additions and 129 deletions

View File

@@ -1,4 +1,3 @@
import useExamEditorStore from "@/stores/examEditor"; import useExamEditorStore from "@/stores/examEditor";
import ListeningContext from "./listening"; import ListeningContext from "./listening";
import ReadingContext from "./reading"; import ReadingContext from "./reading";
@@ -30,7 +29,7 @@ const LevelContext: React.FC<Props> = ({ sectionId }) => {
)} )}
{(readingSection || listeningSection || hasReadingContext) && ( {(readingSection || listeningSection || hasReadingContext) && (
<div className="space-y-4 mb-4"> <div className="space-y-4 mb-4">
{readingSection || hasReadingContext && <ReadingContext sectionId={sectionId} module="level" />} {(readingSection !== undefined || hasReadingContext) && <ReadingContext sectionId={sectionId} module="level" />}
{listeningSection && <ListeningContext sectionId={sectionId} listeningSection={listeningSection} module="level" level={true} />} {listeningSection && <ListeningContext sectionId={sectionId} listeningSection={listeningSection} module="level" level={true} />}
</div> </div>
)} )}

View File

@@ -11,11 +11,10 @@ import { Module } from "@/interfaces";
interface Props { interface Props {
module: Module; module: Module;
sectionId: number; sectionId: number;
level?: boolean;
} }
const ReadingContext: React.FC<Props> = ({ sectionId, module, level = false }) => { const ReadingContext: React.FC<Props> = ({ sectionId, module }) => {
const { dispatch } = useExamEditorStore(); const { dispatch } = useExamEditorStore();
const sectionState = useExamEditorStore( const sectionState = useExamEditorStore(
(state) => state.modules[module].sections.find((section) => section.sectionId === sectionId)! (state) => state.modules[module].sections.find((section) => section.sectionId === sectionId)!
@@ -55,7 +54,7 @@ const ReadingContext: React.FC<Props> = ({ sectionId, module, level = false }) =
} }
}); });
useEffect(()=> { useEffect(() => {
if (readingPart.text === undefined) { if (readingPart.text === undefined) {
setTitle(''); setTitle('');
setContent(''); setContent('');
@@ -74,7 +73,9 @@ const ReadingContext: React.FC<Props> = ({ sectionId, module, level = false }) =
useEffect(() => { useEffect(() => {
const passageRes = levelGenResults.find((res) => res.generating === "passage"); const passageRes = [...levelGenResults].reverse()
.find((res) => res.generating === "passage");
if (levelGenResults && passageRes) { if (levelGenResults && passageRes) {
setEditing(true); setEditing(true);
setTitle(passageRes.result[0].title); setTitle(passageRes.result[0].title);

View File

@@ -6,7 +6,7 @@ import Dropdown from "@/components/Dropdown";
import useExamEditorStore from "@/stores/examEditor"; import useExamEditorStore from "@/stores/examEditor";
import Writing from "../../Exercises/Writing"; import Writing from "../../Exercises/Writing";
import Speaking from "../../Exercises/Speaking"; import Speaking from "../../Exercises/Speaking";
import { ReactElement, ReactNode, useEffect, useState } from "react"; import { ReactNode, useEffect } from "react";
import { import {
DndContext, DndContext,
PointerSensor, PointerSensor,
@@ -43,7 +43,7 @@ const SectionExercises: React.FC<{ sectionId: number; }> = ({ sectionId }) => {
const genResult = section?.genResult; const genResult = section?.genResult;
const generating = section?.generating; const generating = section?.generating;
const levelGenResults = section?.levelGenResults const levelGenResults = section?.levelGenResults;
const levelGenerating = section?.levelGenerating; const levelGenerating = section?.levelGenerating;
const sectionState = section?.state; const sectionState = section?.state;
@@ -66,134 +66,146 @@ const SectionExercises: React.FC<{ sectionId: number; }> = ({ sectionId }) => {
}, [genResult, dispatch, sectionId, currentModule]); }, [genResult, dispatch, sectionId, currentModule]);
useEffect(() => { const handleExerciseGen = (
if (levelGenResults && levelGenResults.some(res => res.generating.startsWith("exercises"))) { results: any[],
const newExercises = levelGenResults assignExercisesFn: (results: any[]) => any[],
.filter(res => res.generating.startsWith("exercises")) {
.map(res => res.result[0].exercises) sectionId,
.flat(); currentModule,
sectionState,
levelGenerating,
levelGenResults
}: {
sectionId: number;
currentModule: string;
sectionState: ExamPart;
levelGenerating?: Generating[];
levelGenResults: any[];
}
) => {
const nonWritingOrSpeaking = results[0]?.generating.startsWith("exercises");
const updates = [ const updates = [
{ {
type: "UPDATE_SECTION_STATE", type: "UPDATE_SECTION_STATE",
payload: { payload: {
sectionId, sectionId,
module: "level", module: "level",
update: { update: {
exercises: [...(sectionState as ExamPart).exercises, ...newExercises] exercises: [
} ...sectionState.exercises,
} ...assignExercisesFn(results)
}, ]
{
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "levelGenerating",
value: levelGenerating?.filter(g => !g?.startsWith("exercises"))
}
},
{
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "levelGenResults",
value: levelGenResults.filter(res => !res.generating.startsWith("exercises"))
} }
} }
] as Action[]; },
{
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "levelGenerating",
value: levelGenerating?.filter(g =>
nonWritingOrSpeaking
? !g?.startsWith("exercises")
: !results.flatMap(res => res.generating as Generating).includes(g)
)
}
},
{
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "levelGenResults",
value: levelGenResults.filter(res =>
nonWritingOrSpeaking
? !res.generating.startsWith("exercises")
: !results.flatMap(res => res.generating as Generating).includes(res.generating)
)
}
}
] as Action[];
updates.forEach(update => dispatch(update)); updates.forEach(update => dispatch(update));
};
useEffect(() => {
if (levelGenResults && levelGenResults?.some(res => res.generating.startsWith("exercises"))) {
const results = levelGenResults.filter(res =>
res.generating.startsWith("exercises")
);
const assignExercises = (results: any[]) =>
results
.map(res => res.result[0].exercises)
.flat();
handleExerciseGen(
results,
assignExercises,
{
sectionId,
currentModule,
sectionState: sectionState as ExamPart,
levelGenerating,
levelGenResults
}
);
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]); }, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
useEffect(() => { useEffect(() => {
if (levelGenResults && levelGenResults.some(res => res.generating === "writing_letter" || res.generating === "writing_2")) { if (levelGenResults && levelGenResults?.some(res =>
const results = levelGenResults.filter(res => res.generating === "writing_letter" || res.generating === "writing_2"); res.generating === "writing_letter" || res.generating === "writing_2"
)) {
const results = levelGenResults.filter(res =>
res.generating === "writing_letter" || res.generating === "writing_2"
);
const updates = [ const assignExercises = (results: any[]) =>
results.map(res => ({
...writingTask(res.generating === "writing_letter" ? 1 : 2),
prompt: res.result[0].prompt,
variant: res.generating === "writing_letter" ? "letter" : "essay"
}) as WritingExercise);
handleExerciseGen(
results,
assignExercises,
{ {
type: "UPDATE_SECTION_STATE", sectionId,
payload: { currentModule,
sectionId, sectionState: sectionState as ExamPart,
module: "level", levelGenerating,
update: { levelGenResults
exercises: [...(sectionState as ExamPart).exercises,
...results.map((res) => {
return {
...writingTask(res.generating === "writing_letter" ? 1 : 2),
prompt: res.result[0].prompt,
variant: res.generating === "writing_letter" ? "letter" : "essay"
} as WritingExercise;
})
]
}
}
},
{
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "levelGenerating",
value: levelGenerating?.filter(g => !results.flatMap(res => res.generating as Generating).includes(g))
}
},
{
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "levelGenResults",
value: levelGenResults.filter(res => !results.flatMap(res => res.generating as Generating).includes(res.generating))
}
} }
] as Action[]; );
updates.forEach(update => dispatch(update));
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]); }, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
useEffect(() => { useEffect(() => {
if (levelGenResults && levelGenResults.some(res => res.generating.startsWith("speaking"))) { if (levelGenResults && levelGenResults?.some(res => res.generating.startsWith("speaking"))) {
const results = levelGenResults.filter(res => res.generating.startsWith("speaking")); const results = levelGenResults.filter(res =>
const updates = [ res.generating.startsWith("speaking")
{ );
type: "UPDATE_SECTION_STATE",
payload: {
sectionId,
module: "level",
update: {
exercises: [...(sectionState as ExamPart).exercises,
...results.map(createSpeakingExercise)
]
}
}
},
{
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "levelGenerating",
value: levelGenerating?.filter(g => !results.flatMap(res => res.generating as Generating).includes(g))
}
},
{
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "levelGenResults",
value: levelGenResults.filter(res => !results.flatMap(res => res.generating as Generating).includes(res.generating))
}
}
] as Action[];
updates.forEach(update => dispatch(update)); const assignExercises = (results: any[]) =>
results.map(createSpeakingExercise);
handleExerciseGen(
results,
assignExercises,
{
sectionId,
currentModule,
sectionState: sectionState as ExamPart,
levelGenerating,
levelGenResults
}
);
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]); }, [levelGenResults, sectionState, levelGenerating, sectionId, currentModule]);
@@ -243,7 +255,7 @@ const SectionExercises: React.FC<{ sectionId: number; }> = ({ sectionId }) => {
const onFocus = (questionId: string, id: string | undefined) => { const onFocus = (questionId: string, id: string | undefined) => {
if (id) { if (id) {
dispatch({ type: "UPDATE_SECTION_SINGLE_FIELD", payload: { module: currentModule, sectionId, field: "focusedExercise", value: { questionId, id} } }) dispatch({ type: "UPDATE_SECTION_SINGLE_FIELD", payload: { module: currentModule, sectionId, field: "focusedExercise", value: { questionId, id } } })
} }
} }
@@ -284,9 +296,9 @@ const SectionExercises: React.FC<{ sectionId: number; }> = ({ sectionId }) => {
{currentModule === "level" && ( {currentModule === "level" && (
<> <>
{ {
questions.ids?.length === 0 && !levelGenerating?.some((g) => g?.startsWith("exercises") || g?.startsWith("writing") || g?.startsWith("speaking")) && generating !== "exercises" questions.ids?.length === 0 && !levelGenerating?.some((g) => g?.startsWith("exercises") || g?.startsWith("writing") || g?.startsWith("speaking")) && generating !== "exercises"
&& background(<span className="flex justify-center">Generated exercises will appear here!</span>)} && background(<span className="flex justify-center">Generated exercises will appear here!</span>)}
{levelGenerating?.some((g) => g?.startsWith("exercises") || g?.startsWith("writing") || g?.startsWith("speaking")) && <GenLoader module={currentModule} className="mt-4" />} {levelGenerating?.some((g) => g?.startsWith("exercises") || g?.startsWith("writing") || g?.startsWith("speaking")) && <GenLoader module={currentModule} className="mt-4" />}
</>) </>)
} }
</DndContext > </DndContext >

View File

@@ -38,11 +38,7 @@ const SectionPicker: React.FC<Props> = ({
const newValue = currentValue === value ? undefined : value; const newValue = currentValue === value ? undefined : value;
setSelectedValue(newValue); setSelectedValue(newValue);
let update = {}; let update = {};
if (module == "reading") { if (module === "listening") {
update = {
text: undefined
}
} else {
if (state.audio?.source) { if (state.audio?.source) {
URL.revokeObjectURL(state.audio.source) URL.revokeObjectURL(state.audio.source)
} }

View File

@@ -15,10 +15,8 @@ import { usePersistentExamStore } from "@/stores/exam";
import openDetachedTab from "@/utils/popout"; import openDetachedTab from "@/utils/popout";
import ListeningComponents from "./listening/components"; import ListeningComponents from "./listening/components";
import ReadingComponents from "./reading/components"; import ReadingComponents from "./reading/components";
import WritingComponents from "./writing/components";
import SpeakingComponents from "./speaking/components"; import SpeakingComponents from "./speaking/components";
import SectionPicker from "./Shared/SectionPicker"; import SectionPicker from "./Shared/SectionPicker";
import SettingsDropdown from "./Shared/SettingsDropdown";
const LevelSettings: React.FC = () => { const LevelSettings: React.FC = () => {