import EXERCISES from "./exercises"; import clsx from "clsx"; import { ExerciseGen, GeneratedExercises, GeneratorState } from "./generatedExercises"; import Modal from "@/components/Modal"; import { useCallback, useState } from "react"; import ExerciseWizard, { ExerciseConfig } from "./ExerciseWizard"; import { generate } from "../SettingsEditor/Shared/Generate"; import { Module } from "@/interfaces"; import useExamEditorStore from "@/stores/examEditor"; import { LevelPart, ListeningPart, Message, ReadingPart } from "@/interfaces/exam"; import { BsArrowRepeat } from "react-icons/bs"; interface ExercisePickerProps { module: string; sectionId: number; difficulty: string; extraArgs?: Record; levelSectionId?: number; level?: boolean; } const ExercisePicker: React.FC = ({ module, sectionId, extraArgs = undefined, levelSectionId, level = false }) => { const { currentModule, dispatch } = useExamEditorStore(); const { difficulty, sections } = useExamEditorStore((store) => store.modules[level ? "level" : currentModule]); const section = sections.find((s) => s.sectionId === (level ? levelSectionId : sectionId)); const [pickerOpen, setPickerOpen] = useState(false); const [localSelectedExercises, setLocalSelectedExercises] = useState([]); const state = section?.state; const getFullExerciseType = (exercise: ExerciseGen): string => { if (exercise.extra && exercise.extra.length > 0) { const extraValue = exercise.extra.find(e => e.param === 'name')?.value; return extraValue ? `${exercise.type}/?name=${extraValue}` : exercise.type; } return exercise.type; }; const handleChange = (exercise: ExerciseGen) => { const fullType = getFullExerciseType(exercise); setLocalSelectedExercises(prev => { const newSelected = prev.includes(fullType) ? prev.filter(type => type !== fullType) : [...prev, fullType]; return newSelected; }); }; const moduleExercises = (sectionId && !["level", "writing", "speaking"].includes(module) ? EXERCISES.filter((ex) => ex.module === module && ex.sectionId == sectionId) : EXERCISES.filter((ex) => ex.module === module)); const onModuleSpecific = useCallback((configurations: ExerciseConfig[]) => { const exercises = configurations.map(config => { const exerciseType = config.type.split('name=')[1]; return { type: exerciseType, quantity: Number(config.params.quantity || 1), ...(config.params.num_random_words !== undefined && { num_random_words: Number(config.params.num_random_words) }), ...(config.params.max_words !== undefined && { max_words: Number(config.params.max_words) }) }; }); let context = {}; if (module === 'reading') { const readingState = state as ReadingPart | LevelPart; context = { text: readingState.text!.content }; } else if (module === 'listening') { const listeningState = state as ListeningPart | LevelPart; const script = listeningState.script; if (sectionId === 1 || sectionId === 3) { const dialog = script as Message[]; context = { text: dialog.map((d) => `${d.name}: ${d.text}`).join("\n") }; } else if (sectionId === 2 || sectionId === 4) { context = { text: script as string }; } } if (!["speaking", "writing"].includes(module)) { generate( sectionId, module as Module, level ? `exercises-${module}` : "exercises", { method: 'POST', body: { ...context, exercises: exercises, difficulty: difficulty } }, (data: any) => [{ exercises: data.exercises }], levelSectionId, level ); } else if (module === "writing") { configurations.forEach((config) => { let queryParams = config.params.topic !== '' ? { topic: config.params.topic as string } : undefined; generate( config.type === 'writing_letter' ? 1 : 2, "writing", config.type, { method: 'GET', queryParams }, (data: any) => [{ prompt: data.question }], levelSectionId, level ); }); } else { configurations.forEach((config) => { let queryParams = Object.fromEntries( Object.entries({ topic: config.params.topic as string, first_topic: config.params.first_topic as string, second_topic: config.params.second_topic as string, }).filter(([_, value]) => value && value !== '') ); let query = Object.keys(queryParams).length === 0 ? undefined : queryParams; generate( Number(config.type.split('_')[1]), "speaking", config.type, { method: 'GET', queryParams: query }, (data: any) => { switch (Number(config.type.split('_')[1])) { case 1: return [{ prompts: data.questions, first_topic: data.first_topic, second_topic: data.second_topic }]; case 2: return [{ topic: data.topic, question: data.question, prompts: data.prompts, suffix: data.suffix }]; case 3: return [{ topic: data.topic, questions: data.questions }]; default: return [data]; } }, levelSectionId, level ); }); } setLocalSelectedExercises([]); setPickerOpen(false); }, [ sectionId, levelSectionId, level, module, state, difficulty, setPickerOpen ]); if (section === undefined) return <>; return ( <> setPickerOpen(false)} title="Exercise Wizard" titleClassName={clsx( "text-2xl font-semibold text-center py-4", `bg-ielts-${module} text-white`, "shadow-sm", "-mx-6 -mt-6", "mb-6" )} > setPickerOpen(false)} extraArgs={extraArgs} />
{moduleExercises.map((exercise) => { const fullType = getFullExerciseType(exercise); return ( ); })}
); }; export default ExercisePicker;