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
This commit is contained in:
Yared Yemane 2026-04-14 05:51:55 -07:00
parent bfbdf0fc19
commit 909a2f42bc
3 changed files with 55 additions and 16 deletions

View File

@ -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<GetSubCourseEntryAssessmentResponse>(
`/question-sets/sub-courses/${subModuleId}/entry-assessment`,

View File

@ -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}`}
>

View File

@ -729,6 +729,7 @@ export interface HumanLanguageModule {
}
export interface HumanLanguageLevelTree {
level_id?: number
level: string
modules: HumanLanguageModule[]
}