+ {/* Back Button */}
+
+
+ Back to Human Language
+
+
+ {/* SubCourse Header */}
+
+
+
+
+ {subCourse?.title}
+
+ {subCourse?.level && (
+ {subCourse.level}
+ )}
+
+
+ {subCourse?.description || "No description available"}
+
+
+
+
+
+
+
+
+
+ Use Lesson for videos/audio and{" "}
+ Practice for question sets tied to this sub-module.
+
+
+ {/* Tabs */}
+
+
+
+
+
+
+
+
+
+ {/* Content */}
+ {activeTab === "practice" && (
+ <>
+ {practicesLoading ? (
+
+ ) : filteredPractices.length === 0 ? (
+
+
+
+
+
No practices yet
+
Create your first practice to get started
+
+
+ ) : (
+
+ {filteredPractices.map((practice) => {
+ const statusConfig: Record
= {
+ PUBLISHED: { bg: "bg-green-50 text-green-700 ring-1 ring-inset ring-green-200", dot: "bg-green-500", text: "Published" },
+ DRAFT: { bg: "bg-grayScale-50 text-grayScale-600 ring-1 ring-inset ring-grayScale-200", dot: "bg-grayScale-400", text: "Draft" },
+ ARCHIVED: { bg: "bg-amber-50 text-amber-700 ring-1 ring-inset ring-amber-200", dot: "bg-amber-500", text: "Archived" },
+ }
+ const status = statusConfig[practice.status] ?? statusConfig.DRAFT
+
+ return (
+ handlePracticeClick(practice.id)}
+ >
+
+
+
{practice.title}
+
+
+ {status.text}
+
+
+
+
{practice.description}
+
+
+
+ {practice.set_type}
+
+ {practice.persona && (
+
+ {practice.persona}
+
+ )}
+
+
+
+
+
+ {practice.owner_type.replace("_", " ")}
+
+ {practice.shuffle_questions && (
+
Shuffle ON
+ )}
+
+
+
+
+ {new Date(practice.created_at).toLocaleDateString("en-US", {
+ month: "short",
+ day: "numeric",
+ year: "numeric",
+ })}
+
+
e.stopPropagation()}>
+
+
+
+
+
+
+ )
+ })}
+
+ )}
+ >
+ )}
+
+ {activeTab === "lesson" && (
+ <>
+ {videosLoading ? (
+
+ ) : videos.length === 0 ? (
+
+
+
+
+
No videos yet
+
Upload your first video to get started
+
+
+ ) : (
+
+ {videos.map((video, index) => {
+ const gradients = [
+ "bg-gradient-to-br from-blue-100 via-blue-50 to-indigo-100",
+ "bg-gradient-to-br from-amber-100 via-yellow-50 to-orange-100",
+ "bg-gradient-to-br from-purple-100 via-fuchsia-50 to-pink-100",
+ "bg-gradient-to-br from-emerald-100 via-green-50 to-teal-100",
+ ]
+ const formatDuration = (seconds: number) => {
+ const mins = Math.floor(seconds / 60)
+ const secs = seconds % 60
+ return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
+ }
+ return (
+
+ {/* Thumbnail with duration */}
+
+ {video.thumbnail ? (
+

+ ) : (
+
+
+
+ )}
+
+ {formatDuration(video.duration || 0)}
+
+
+
+ {/* Content */}
+
+ {/* Status and menu */}
+
+
+
+ {video.is_published ? "PUBLISHED" : "DRAFT"}
+
+
+
+ {openVideoMenuId === video.id && (
+
+
+
+ )}
+
+
+
+ {/* Title */}
+
{video.title}
+
+ {/* Edit / Preview buttons */}
+
+
+
+
+
+ {/* Publish button */}
+
+
+
+ )
+ })}
+
+ )}
+ >
+ )}
+
+ {/* Delete Modal */}
+ {showDeleteModal && practiceToDelete && (
+
+
+
+
Delete Practice
+
+
+
+
+ Are you sure you want to delete{" "}
+ {practiceToDelete.title}? This action cannot be undone.
+
+
+
+
+
+
+
+
+ )}
+
+ {/* Edit Practice Modal */}
+ {showEditPracticeModal && practiceToEdit && (
+
+
+
+
Edit Practice
+
+
+
+
+
+ setTitle(e.target.value)}
+ placeholder="Enter practice title"
+ />
+
+
+
+
+
+
+ setPersona(e.target.value)}
+ placeholder="Enter persona"
+ />
+
+ {saveError &&
{saveError}
}
+
+
+
+
+
+
+
+ )}
+
+ {/* Add Video Modal */}
+ {showAddVideoModal && (
+
+
+
+
Add Video
+
+
+
+
+
+ setVideoTitle(e.target.value)}
+ placeholder="Enter video title"
+ />
+
+
+
+
+
+
+
handleVideoFileSelect(e.target.files?.[0] ?? null)}
+ />
+ {videoFile && (
+
+ Selected: {videoFile.name}
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {saveError &&
{saveError}
}
+
+
+
+
+
+
+
+ )}
+
+ {/* Edit Video Modal */}
+ {showEditVideoModal && videoToEdit && (
+
+
+
+
Edit Video
+
+
+
+
+
+ setVideoTitle(e.target.value)}
+ placeholder="Enter video title"
+ />
+
+
+
+
+
+
+ setVideoUrl(e.target.value)}
+ placeholder="Enter video URL"
+ />
+
+ {saveError &&
{saveError}
}
+
+
+
+
+
+
+
+ )}
+
+ {/* Delete Video Modal */}
+ {showDeleteVideoModal && videoToDelete && (
+
+
+
+
Delete Video
+
+
+
+
+ Are you sure you want to delete{" "}
+ {videoToDelete.title}? This action cannot be undone.
+
+
+
+
+
+
+
+
+ )}
+
+ {/* Video Preview Modal */}
+ {showPreviewModal && (
+
+
+
+
+
+ {previewVideo?.name ?? "Video Preview"}
+
+ {previewVideo && (
+
+ {Math.floor(previewVideo.duration / 60)}:{(previewVideo.duration % 60).toString().padStart(2, "0")} • {previewVideo.width}×{previewVideo.height}
+
+ )}
+
+
+
+
+ {previewLoading ? (
+
+
+
+ ) : previewIframe ? (
+
+ ) : (
+
+
Failed to load preview.
+
+ )}
+
+
+
+ )}
+
+ )
+}
diff --git a/src/pages/content-management/PracticeQuestionsPage.tsx b/src/pages/content-management/PracticeQuestionsPage.tsx
index ba3d055..55549e2 100644
--- a/src/pages/content-management/PracticeQuestionsPage.tsx
+++ b/src/pages/content-management/PracticeQuestionsPage.tsx
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useState } from "react"
-import { Link, useParams } from "react-router-dom"
+import { Link, useLocation, useParams } from "react-router-dom"
import { ArrowLeft, Plus, Edit, Trash2, X, Check, ChevronDown, ChevronUp, SlidersHorizontal, ArrowUpDown } from "lucide-react"
import practiceSrc from "../../assets/Practice.svg"
import spinnerSrc from "../../assets/Circular-indeterminate progress indicator.svg"
@@ -59,6 +59,7 @@ const typeColors: Record