import { Exam, ExerciseOnlyExam, PartExam } from "@/interfaces/exam"; import defaultModuleSettings, { defaultSectionSettings, defaultSettings, sectionLabels } from "../defaults"; import ExamEditorStore, { SectionState } from "../types"; import { MODULE_ACTIONS, ModuleActions, moduleReducer } from "./moduleReducer"; import { SECTION_ACTIONS, SectionActions, sectionReducer } from "./sectionReducer"; import { Module } from "@/interfaces"; import { updateExamWithUserSolutions } from "@/stores/exam/utils"; import { defaultExamUserSolutions } from "@/utils/exams"; type RootActions = { type: 'FULL_RESET' } | { type: 'INIT_EXAM_EDIT', payload: { exam: Exam; examModule: Module; id: string } } | { type: 'UPDATE_ROOT'; payload: { updates: Partial } } | { type: 'RESET_MODULE'; payload: { module: Module } }; export type Action = ModuleActions | SectionActions | RootActions; export const rootReducer = ( state: ExamEditorStore, action: Action ): Partial => { if (MODULE_ACTIONS.includes(action.type as any)) { if (action.type === "REORDER_EXERCISES") { const updatedState = sectionReducer(state, action as SectionActions); if (!updatedState.modules) return state; return moduleReducer({ ...state, modules: updatedState.modules }, { type: "REORDER_EXERCISES" }); } return moduleReducer(state, action as ModuleActions); } if (SECTION_ACTIONS.includes(action.type as any)) { if (action.type === "UPDATE_SECTION_STATE") { const updatedState = sectionReducer(state, action as SectionActions); if (!updatedState.modules) return state; return moduleReducer({ ...state, modules: updatedState.modules }, { type: "REORDER_EXERCISES" }); } return sectionReducer(state, action as SectionActions); } switch (action.type) { case 'UPDATE_ROOT': const { updates } = action.payload; return { ...state, ...updates }; case 'RESET_MODULE': const { module } = action.payload; const timer = ["reading", "writing", "level"].includes(module) ? 60 : (module === "speaking" ? 14 : 30); return { modules: { ...state.modules, [module]: defaultModuleSettings(module, timer, true), }, }; case 'FULL_RESET': return { title: "", currentModule: "reading", speakingAvatars: [], modules: { reading: defaultModuleSettings("reading", 60), writing: defaultModuleSettings("writing", 60), speaking: defaultModuleSettings("speaking", 14), listening: defaultModuleSettings("listening", 30), level: defaultModuleSettings("level", 60) }, }; case 'INIT_EXAM_EDIT': { const { exam, id, examModule } = action.payload; let typedExam; let examState; if (["reading", "listening", "level"].includes(examModule)) { typedExam = updateExamWithUserSolutions(exam, defaultExamUserSolutions(exam)) as PartExam; examState = typedExam.parts.map((part, index) => { return { ...defaultSectionSettings(examModule, index + 1, part), sectionId: index + 1, settings: { ...defaultSettings(examModule), category: part.category, introOption: { label: 'Custom', value: 'Custom' }, currentIntro: part.intro }, } }) } else { typedExam = updateExamWithUserSolutions(exam, defaultExamUserSolutions(exam)) as ExerciseOnlyExam; examState = typedExam.exercises.map((exercise, index) => { return { ...defaultSectionSettings(examModule, index + 1), sectionId: index + 1, settings: { ...defaultSettings(examModule), category: exercise.category, introOption: { label: 'Custom', value: 'Custom' }, currentIntro: exercise.intro }, state: exercise, } }) } return { title: id, modules: { ...state.modules, [examModule]: { ...defaultModuleSettings(examModule, exam.minTimer), examLabel: exam.label, difficulty: exam.difficulty, isPrivate: exam.private, sections: examState, importModule: false, sectionLabels: exam.module === "level" ? sectionLabels(examModule, exam.parts.length) : sectionLabels(examModule) } } } } default: return {}; } };