From ea73323fce89c532b37097457af4e826473c7b68 Mon Sep 17 00:00:00 2001
From: Yared Yemane
Date: Tue, 14 Apr 2026 08:06:48 -0700
Subject: [PATCH] fix lesson intro video flow and polish review layout
Auto-process intro video URLs on blur with preview support, improve local upload reliability, and refine Step 1 + Review styling for the lesson creation wizard.
Made-with: Cursor
---
.../content-management/AddNewLessonPage.tsx | 102 ++++++++++--------
1 file changed, 55 insertions(+), 47 deletions(-)
diff --git a/src/pages/content-management/AddNewLessonPage.tsx b/src/pages/content-management/AddNewLessonPage.tsx
index 8aca90b..1ec97b5 100644
--- a/src/pages/content-management/AddNewLessonPage.tsx
+++ b/src/pages/content-management/AddNewLessonPage.tsx
@@ -1,4 +1,4 @@
-import { useMemo, useRef, useState, type ChangeEvent } from "react"
+import { useMemo, useState, type ChangeEvent } from "react"
import { ArrowLeft, ArrowRight, Check, GripVertical, Loader2, Plus, Rocket, Trash2, Upload } from "lucide-react"
import { Link, useLocation, useNavigate, useParams } from "react-router-dom"
import { toast } from "sonner"
@@ -103,7 +103,6 @@ export function AddNewLessonPage() {
const { categoryId, courseId, subModuleId } = useParams()
const navigate = useNavigate()
const location = useLocation()
- const introVideoFileInputRef = useRef(null)
const backTo = useMemo(() => {
if (location.pathname.includes("/content/human-language/") && location.pathname.includes("/sub-module/")) {
@@ -121,7 +120,6 @@ export function AddNewLessonPage() {
const [lessonDescription, setLessonDescription] = useState("")
const [introVideoUrl, setIntroVideoUrl] = useState("")
const [uploadingIntroVideo, setUploadingIntroVideo] = useState(false)
- const [importingIntroVideoUrl, setImportingIntroVideoUrl] = useState(false)
const [questions, setQuestions] = useState([createEmptyQuestion("1")])
const handleNext = () => setCurrentStep((s) => (s < 3 ? ((s + 1) as Step) : s))
@@ -149,7 +147,7 @@ export function AddNewLessonPage() {
}
}
- const handleImportIntroVideoFromUrl = async () => {
+ const handleIntroVideoUrlBlur = async () => {
const source = introVideoUrl.trim()
if (!source || !/^https?:\/\//i.test(source)) return
const vimeoEmbed = toVimeoEmbedUrl(source)
@@ -157,8 +155,13 @@ export function AddNewLessonPage() {
setIntroVideoUrl(vimeoEmbed)
return
}
+ if (isDirectVideoFile(source)) {
+ setIntroVideoUrl(source)
+ return
+ }
- setImportingIntroVideoUrl(true)
+ // For non-direct URLs, automatically try server-side import via /files/upload.
+ setUploadingIntroVideo(true)
try {
const uploadRes = await uploadVideoFile(source, {
title: lessonTitle.trim() || "Lesson intro",
@@ -167,12 +170,12 @@ export function AddNewLessonPage() {
const finalUrl = introVideoUrlFromUploadResponse(uploadRes.data?.data)
if (!finalUrl) throw new Error("Missing uploaded video url")
setIntroVideoUrl(finalUrl)
- toast.success("Intro video URL imported", { description: "Processed via /files/upload." })
+ toast.success("Intro video URL imported")
} catch (error) {
console.error("Failed to import intro video URL:", error)
toast.error("Failed to import intro video URL")
} finally {
- setImportingIntroVideoUrl(false)
+ setUploadingIntroVideo(false)
}
}
@@ -307,7 +310,8 @@ export function AddNewLessonPage() {
-
+
+
+
@@ -487,11 +487,19 @@ export function AddNewLessonPage() {
Step 3: Review & publish
-
-
Question set title: {lessonTitle || "Untitled Lesson"}
-
Question set description: {lessonDescription || "—"}
-
Sub-module lesson intro video: {introVideoUrl || "—"}
-
Questions: {questions.length}
+
+
+
Question set
+
Title: {lessonTitle || "Untitled Lesson"}
+
Description: {lessonDescription || "—"}
+
Status: Draft/Published (selected on save)
+
+
+
Lesson link
+
Sub-module: {subModuleId ?? "—"}
+
Intro video: {introVideoUrl || "—"}
+
Questions: {questions.length}
+