From 909a2f42bc6641189deb2c05d6961b53a132823c Mon Sep 17 00:00:00 2001 From: Yared Yemane Date: Tue, 14 Apr 2026 05:51:55 -0700 Subject: [PATCH] fix second module creation in human language paths Create additional modules/sub-modules directly under existing level and module IDs instead of re-running the lesson bootstrap flow, which prevented adding a second module. Made-with: Cursor --- src/api/courses.api.ts | 32 +++++++++++++++- .../content-management/HumanLanguagePage.tsx | 38 +++++++++++-------- src/types/course.types.ts | 1 + 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/api/courses.api.ts b/src/api/courses.api.ts index 314c817..2b03358 100644 --- a/src/api/courses.api.ts +++ b/src/api/courses.api.ts @@ -689,6 +689,7 @@ export const getHumanLanguageHierarchy = () => const levelMap = new Map< string, { + level_id?: number level: string modules: Map< number, @@ -705,7 +706,7 @@ export const getHumanLanguageHierarchy = () => if (!row.level_id || !row.cefr_level) return const levelKey = String(row.cefr_level).toUpperCase() if (!levelMap.has(levelKey)) { - levelMap.set(levelKey, { level: levelKey, modules: new Map() }) + levelMap.set(levelKey, { level_id: Number(row.level_id), level: levelKey, modules: new Map() }) } if (!row.module_id) return @@ -736,6 +737,7 @@ export const getHumanLanguageHierarchy = () => course_id: course.course_id, course_name: course.course_name, levels: Array.from(levelMap.values()).map((levelNode) => ({ + level_id: levelNode.level_id, level: levelNode.level, modules: Array.from(levelNode.modules.values()).map((moduleNode) => ({ id: moduleNode.id, @@ -787,6 +789,34 @@ export const createHumanLanguageLesson = (data: CreateHumanLanguageLessonRequest }), ) +export const createModuleInLevel = ( + levelId: number, + title: string, + description: string, + displayOrder = 0, +) => + http.post("/course-management/modules", { + level_id: levelId, + title, + description, + display_order: displayOrder, + is_active: true, + }) + +export const createSubModuleInModule = ( + moduleId: number, + title: string, + description: string, + displayOrder = 0, +) => + http.post("/course-management/sub-modules", { + module_id: moduleId, + title, + description, + display_order: displayOrder, + is_active: true, + }) + export const getSubModuleEntryAssessment = (subModuleId: number) => http.get( `/question-sets/sub-courses/${subModuleId}/entry-assessment`, diff --git a/src/pages/content-management/HumanLanguagePage.tsx b/src/pages/content-management/HumanLanguagePage.tsx index 48843d1..92c980e 100644 --- a/src/pages/content-management/HumanLanguagePage.tsx +++ b/src/pages/content-management/HumanLanguagePage.tsx @@ -35,6 +35,8 @@ import { createCourse, createCourseCategory, createHumanLanguageLesson, + createModuleInLevel, + createSubModuleInModule, deleteCourse, deleteCourseSubCategory, deleteQuestionSet, @@ -502,7 +504,16 @@ export function HumanLanguagePage() { return { module, sub } } - const handleCreateModule = async (courseId: number, level: string, modules: { title: string }[]) => { + const handleCreateModule = async ( + courseId: number, + levelNode: HumanLanguageCourseTree["levels"][number] | undefined, + modules: { title: string }[], + ) => { + if (!levelNode?.level_id) { + toast.error("Cannot create module: missing level identifier") + return + } + const level = levelNode.level const key = `module-${courseId}-${level}` setCreatingKey(key) try { @@ -511,12 +522,7 @@ export function HumanLanguagePage() { .filter((v): v is number => v !== null && v > 0) const next = nextMissingPositive(usedNumbers) const title = `Module-${next}` - await createHumanLanguageLesson({ - course_id: courseId, - cefr_level: level, - title, - description: `${level} ${title}`, - }) + await createModuleInLevel(levelNode.level_id, title, `${level} ${title}`, next) toast.success(`${title} created`) await loadHierarchy() } catch (error) { @@ -530,6 +536,7 @@ export function HumanLanguagePage() { const handleCreateSubModule = async ( courseId: number, level: string, + moduleId: number, moduleTitle: string, existingSubModules: { title: string }[], ) => { @@ -547,12 +554,7 @@ export function HumanLanguagePage() { .map((item) => item.sub) const next = nextMissingPositive(usedNumbers) const title = `Module-${moduleNo}.${next}` - await createHumanLanguageLesson({ - course_id: courseId, - cefr_level: level, - title, - description: `${level} ${title}`, - }) + await createSubModuleInModule(moduleId, title, `${level} ${title}`, next) toast.success(`Sub-module ${moduleNo}.${next} created`) await loadHierarchy() } catch (error) { @@ -1399,7 +1401,7 @@ export function HumanLanguagePage() { size="sm" variant="outline" className="h-8 border-grayScale-200 bg-white text-xs hover:border-brand-200 hover:bg-brand-50/40" - onClick={() => handleCreateModule(course.course_id, level, modules)} + onClick={() => handleCreateModule(course.course_id, levelNode, modules)} disabled={creatingKey === `module-${course.course_id}-${level}`} > {creatingKey === `module-${course.course_id}-${level}` ? ( @@ -1441,7 +1443,13 @@ export function HumanLanguagePage() { variant="outline" className="h-8 border-grayScale-200 bg-white text-xs hover:border-brand-200 hover:bg-brand-50/40" onClick={() => - handleCreateSubModule(course.course_id, level, module.title, module.sub_modules) + handleCreateSubModule( + course.course_id, + level, + module.id, + module.title, + module.sub_modules, + ) } disabled={creatingKey === `submodule-${course.course_id}-${level}-${parseModuleNumber(module.title) ?? 0}`} > diff --git a/src/types/course.types.ts b/src/types/course.types.ts index cb33048..5b6c62d 100644 --- a/src/types/course.types.ts +++ b/src/types/course.types.ts @@ -729,6 +729,7 @@ export interface HumanLanguageModule { } export interface HumanLanguageLevelTree { + level_id?: number level: string modules: HumanLanguageModule[] }