From 7c3f2192efbe34c69e24dba4b06888a012a0b60d Mon Sep 17 00:00:00 2001 From: Yared Yemane Date: Thu, 16 Apr 2026 04:29:54 -0700 Subject: [PATCH] Fix edit-lesson question editing UI Embed lesson question editor inside the 'Edit lesson' dialog, remove extra inline lesson question panel, and fix lesson card question counts. Made-with: Cursor --- .../content-management/HumanLanguagePage.tsx | 422 ++++++++---------- 1 file changed, 180 insertions(+), 242 deletions(-) diff --git a/src/pages/content-management/HumanLanguagePage.tsx b/src/pages/content-management/HumanLanguagePage.tsx index 3419790..3b8da01 100644 --- a/src/pages/content-management/HumanLanguagePage.tsx +++ b/src/pages/content-management/HumanLanguagePage.tsx @@ -1042,6 +1042,9 @@ export function HumanLanguagePage() { }) toast.error("Could not load full lesson details") } + + // Preload questions so the lesson edit dialog can show the question bank immediately. + if (lesson.question_set_id > 0) void loadLessonQuestionsIfNeeded(lesson.question_set_id) } const handleSaveLesson = async () => { @@ -1845,11 +1848,9 @@ export function HumanLanguagePage() { const selectedLessonFetch = cardSel.lessonId !== null ? lessonDetailState[cardSel.lessonId] : undefined const selectedLessonDetail = - selectedLessonFetch?.status === "ok" ? selectedLessonFetch.data : null - const selectedLessonQuestionSetId = - selectedLessonDetail?.question_set_id ?? selectedLesson?.question_set_id ?? 0 - const lessonFetch = - selectedLessonQuestionSetId > 0 ? lessonQuestionsState[selectedLessonQuestionSetId] : undefined + selectedLessonFetch && selectedLessonFetch.status === "ok" + ? selectedLessonFetch.data + : null const selectedLessonIds = selectedLessonIdsBySubModule[smKey] ?? [] const selectedLessonRows = lessonRows.filter((row) => selectedLessonIds.includes(row.id)) const selectedPracticeMeta = @@ -2006,6 +2007,16 @@ export function HumanLanguagePage() {
{lessonRows.map((v, idx) => { const isActive = cardSel.lessonId === v.id + const fetchedLessonCount = (() => { + const detailFetch = lessonDetailState[v.id] + if (detailFetch?.status === "ok") return detailFetch.data.question_count + + const questionFetch = lessonQuestionsState[v.question_set_id] + if (questionFetch?.status === "ok") return questionFetch.questions.length + + return undefined + })() + const questionCountToShow = fetchedLessonCount ?? v.question_count return (
@@ -2148,242 +2159,7 @@ export function HumanLanguagePage() { - {selectedLessonQuestionSetId > 0 && ( -
-
-
-
-

- Question bank -

-

- {selectedLessonDetail?.title ?? selectedLesson?.title} -

-

- {selectedLessonDetail?.question_count ?? selectedLesson?.question_count ?? 0}{" "} - {Number( - selectedLessonDetail?.question_count ?? selectedLesson?.question_count ?? 0, - ) === 1 - ? "question" - : "questions"}{" "} - in this lesson -

-
-
- - {lessonFetch?.status === "ok" ? ( - - {lessonFetch.questions.length} loaded - - ) : null} -
-
-
-
- {!lessonFetch || lessonFetch.status === "loading" ? ( -
- - Loading questions… -
- ) : null} - {lessonFetch?.status === "error" ? ( -
-
- -
-

{lessonFetch.message}

- -
-
-
- ) : null} - {lessonFetch?.status === "ok" && lessonFetch.questions.length === 0 ? ( -
- -

No questions in this lesson yet.

-

- Add them via Open editor. -

-
- ) : null} - {lessonFetch?.status === "ok" && lessonFetch.questions.length > 0 ? ( -
    - {lessonFetch.questions.map((q, qIdx) => { - const qType = String(q.question_type ?? "—") - const embeddedUrls = extractUrls(q.question_text || "") - return ( -
  • -
    -
    -
    - {qIdx + 1} -
    -
    -
    -
    - - {formatQuestionTypeLabel(qType)} - - {q.points != null && q.points > 0 ? ( - - {q.points} pts - - ) : null} - {q.difficulty_level ? ( - - {q.difficulty_level} - - ) : null} -
    -
    - - -
    -
    -
    -

    - Prompt -

    -

    - {q.question_text?.trim() || ( - No prompt text - )} -

    -
    - {embeddedUrls.length > 0 ? ( -
    -

    - - Media in prompt -

    -
    - {embeddedUrls.map((u) => ( -
    - {renderMediaPreview(u, undefined, "", "Embedded link")} -
    - ))} -
    -
    - ) : null} - {q.tips ? ( -
    -

    - - Learner tip -

    -

    {q.tips}

    -
    - ) : null} - {q.image_url || - q.voice_prompt || - q.sample_answer_voice_prompt ? ( -
    -

    - Assets -

    -
    - {q.image_url - ? renderMediaPreview(q.image_url, "image", "", "Image") - : null} - {q.voice_prompt - ? renderMediaPreview(q.voice_prompt, "audio", "", "Voice prompt") - : null} - {q.sample_answer_voice_prompt - ? renderMediaPreview( - q.sample_answer_voice_prompt, - "audio", - "", - "Sample answer (audio)", - ) - : null} -
    -
    - ) : null} - {q.audio_correct_answer_text ? ( -
    -

    - Sample answer text -

    -

    - {q.audio_correct_answer_text} -

    -
    - ) : null} -
    -
    -
  • - ) - })} -
- ) : null} -
-
- )} + {/* Question bank for lessons is shown inside the Edit lesson dialog. */} ) : (

@@ -2980,6 +2756,168 @@ export function HumanLanguagePage() { ? renderMediaPreview(lessonForm.introVideoUrl, "video", "", "Intro video") : null} + + {lessonDialog.open && lessonDialog.questionSetId > 0 ? ( + (() => { + const lessonQuestionSetId = lessonDialog.questionSetId + const lessonId = lessonDialog.lessonId + const lessonFetch = lessonQuestionsState[lessonQuestionSetId] + const lessonDetailFetch = lessonDetailState[lessonId] + const questionCount = + lessonDetailFetch?.status === "ok" + ? lessonDetailFetch.data.question_count + : lessonFetch?.status === "ok" + ? lessonFetch.questions.length + : 0 + + return ( +

+
+
+
+

+ Question bank +

+

+ {lessonForm.title} +

+

+ {questionCount} {questionCount === 1 ? "question" : "questions"} in this lesson +

+
+
+ +
+
+
+ +
+ {lessonFetch?.status !== "ok" ? ( +
+ + Loading questions… +
+ ) : lessonFetch.questions.length === 0 ? ( +
+ +

No questions in this lesson yet.

+

+ Add them via Open editor. +

+
+ ) : ( +
    + {lessonFetch.questions.map((q, qIdx) => { + const qType = String(q.question_type ?? "—") + const embeddedUrls = extractUrls(q.question_text || "") + return ( +
  • +
    +
    +
    + {qIdx + 1} +
    +
    +
    +
    + + {formatQuestionTypeLabel(qType)} + + {q.points != null && q.points > 0 ? ( + + {q.points} pts + + ) : null} + {q.difficulty_level ? ( + + {q.difficulty_level} + + ) : null} +
    +
    + + +
    +
    +
    +

    + Prompt +

    +

    + {q.question_text?.trim() || ( + No prompt text + )} +

    +
    + {embeddedUrls.length > 0 ? ( +
    +

    + + Media in prompt +

    +
    + {embeddedUrls.map((u) => ( +
    {renderMediaPreview(u, undefined, "", "Embedded link")}
    + ))} +
    +
    + ) : null} +
    +
    +
  • + ) + })} +
+ )} +
+
+ ) + })() + ) : null}