switch lesson creation to sub_module_lessons flow

Create lessons via question-set + sub-module-lesson attachment instead of video-only handling, and update new-level creation to reuse existing CEFR levels when present.

Made-with: Cursor
This commit is contained in:
Yared Yemane 2026-04-14 06:39:39 -07:00
parent 06a0daedfe
commit 6df388fb98
2 changed files with 73 additions and 18 deletions

View File

@ -349,6 +349,33 @@ export const createPractice = (data: CreatePracticeRequest) =>
.then(() => res)
})
export const createLesson = (data: {
sub_module_id: number
title: string
description?: string
intro_video_url?: string
}) =>
http
.post<CreateQuestionSetResponse>("/question-sets", {
title: data.title,
set_type: "QUIZ",
owner_type: "SUB_MODULE",
owner_id: data.sub_module_id,
...(data.description?.trim() ? { description: data.description.trim() } : {}),
...(data.intro_video_url?.trim() ? { intro_video_url: data.intro_video_url.trim() } : {}),
})
.then((res) => {
const questionSetID = res.data?.data?.id
if (!questionSetID) return res
return http
.post("/course-management/sub-module-lessons", {
sub_module_id: data.sub_module_id,
question_set_id: questionSetID,
intro_video_url: data.intro_video_url,
})
.then(() => res)
})
export const updatePractice = (practiceId: number, data: UpdatePracticeRequest) =>
http.put(`/course-management/practices/${practiceId}`, data)

View File

@ -31,6 +31,7 @@ import { SpinnerIcon } from "../../components/ui/spinner-icon"
import {
addQuestionToSet,
createPractice,
createLesson,
createQuestion,
createCourse,
createCourseCategory,
@ -565,6 +566,26 @@ export function HumanLanguagePage() {
}
}
const handleCreateLesson = async (subModuleId: number, currentLessonsCount: number) => {
const key = `lesson-${subModuleId}`
setCreatingKey(key)
try {
const next = (currentLessonsCount || 0) + 1
await createLesson({
sub_module_id: subModuleId,
title: `Lesson ${next}`,
description: `Auto-created lesson ${next}`,
})
toast.success("Lesson created")
await loadHierarchy(false)
} catch (error) {
console.error("Failed to create lesson:", error)
toast.error("Failed to create lesson")
} finally {
setCreatingKey(null)
}
}
const requestRemove = (payload: PendingRemove) => {
if (payload.ids.length === 0) return
setPendingRemove(payload)
@ -608,12 +629,17 @@ export function HumanLanguagePage() {
const key = `next-level-${courseId}-${next}`
setCreatingKey(key)
try {
await createHumanLanguageLesson({
course_id: courseId,
cefr_level: next,
title: "Module-1",
description: `${next} Module-1`,
})
const existingLevel = course.levels.find((l) => l.level.toUpperCase() === next)
if (existingLevel?.level_id) {
await createModuleInLevel(existingLevel.level_id, "Module-1", `${next} Module-1`, 1)
} else {
await createHumanLanguageLesson({
course_id: courseId,
cefr_level: next,
title: "Module-1",
description: `${next} Module-1`,
})
}
toast.success(`${next} created with Module-1`)
await loadHierarchy()
} catch (error) {
@ -1611,20 +1637,22 @@ export function HumanLanguagePage() {
<Plus className="h-3.5 w-3.5" />
New practice
</Button>
) : panelTab === "lessons" && categoryId ? (
<Link
to={`/content/human-language/${categoryId}/${course.course_id}/sub-module/${subModule.id}`}
) : panelTab === "lessons" ? (
<Button
type="button"
size="sm"
variant="outline"
className="h-8 border-grayScale-200 bg-white px-2 text-[11px] hover:border-brand-200 hover:bg-brand-50/40"
onClick={() => handleCreateLesson(subModule.id, lessonRows.length)}
disabled={creatingKey === `lesson-${subModule.id}`}
>
<Button
type="button"
size="sm"
variant="outline"
className="h-8 border-grayScale-200 bg-white px-2 text-[11px] hover:border-brand-200 hover:bg-brand-50/40"
>
{creatingKey === `lesson-${subModule.id}` ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" />
) : (
<Plus className="h-3.5 w-3.5" />
New lesson
</Button>
</Link>
)}
New lesson
</Button>
) : null}
</div>
</div>