import AppBreadcrumb from "@/components/generic/Breadcrumb/AppBreadcrumb"; import { useParams, useNavigate } from "react-router-dom"; import { House, Timer, CheckCircle2, Check, CheckCheck, ClipboardList, Hourglass, } from "lucide-react"; import { cn } from "@/lib/utils"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Progress } from "@/components/ui/progress"; import { Skeleton } from "@/components/ui/skeleton"; import { motion } from "framer-motion"; import { useEffect } from "react"; import { useLibrary } from "@/contexts/ClientLibraryContext"; import { useClientTiers } from "@/contexts/ClientTiersProvider"; import { PageMeta } from "@/contexts/MetadataContext"; import LockedContentPanel from "@/modules/client/components/LockedContentPanel"; import { TYPE_DEFS } from "@/modules/admin/components/courses/completionRequirementTypes"; // ─── Helpers ────────────────────────────────────────────────────────────────── function formatDuration(seconds = 0) { if (!seconds) return null; const h = Math.floor(seconds / 3600); const m = Math.floor((seconds % 3600) / 60); if (h > 0) return `${h}hr ${m}min`; return `${m}min`; } // ─── Lessons roadmap (single unit — lessons in order + trailing quiz row) ───── const LessonsRoadmap = ({ unitDetail, currentLessonId, onLessonClick, onContinue, onQuizClick }) => { const lessons = unitDetail.lessons ?? []; const quiz = unitDetail.quiz ?? null; return (
{lessons.map((lesson, index) => { const completed = lesson.status === "completed"; const isCurrent = lesson.lesson_id === currentLessonId; return ( onLessonClick(lesson)} >
{completed ? : index + 1}
{lesson.title} {formatDuration(lesson.duration_seconds) ?? "—"} {completed && " · Completed"} {isCurrent && !completed && " · In progress"}
{isCurrent && !completed && ( )}
); })} {quiz && (
onQuizClick()} >
{quiz.has_passed ? : } {quiz.title || "Quiz"}
{quiz.has_passed ? "Passed" : "Quiz"}
)}
); }; // ─── Unit Details ─────────────────────────────────────────────────────────── const UnitDetails = () => { const { uuid } = useParams(); const navigate = useNavigate(); const { getUnitDetail, unitDetail, unitDetailLoading, unitBlocked, unitBlockedInfo, resetUnitDetail } = useLibrary(); const { tierMap, getTierCategories } = useClientTiers(); const contentNotReady = !unitDetail?.duration_seconds; useEffect(() => { getTierCategories(); getUnitDetail(uuid); return () => resetUnitDetail(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [uuid]); const items = [ { label: "Home", icon: , to: `/dashboard` }, { label: "Units", to: `/units` }, { label: unitDetail?.title ?? "Unit" }, ]; // ── Deep-link to a locked unit — inline blocked panel, not a redirect ──── if (unitBlocked) { return ( ); } if (unitDetailLoading) { return (
); } const lessons = unitDetail?.lessons ?? []; const completedCount = lessons.filter((l) => l.status === "completed").length; const currentLesson = lessons.find((l) => l.status !== "completed") ?? null; const progressPct = lessons.length > 0 ? Math.round((completedCount / lessons.length) * 100) : 0; // Admin-configured completion requirement for the unit itself (null when nothing's set). const requirementDef = unitDetail?.completion?.type ? TYPE_DEFS[unitDetail.completion.type] : null; const RequirementIcon = requirementDef?.icon; const handleLessonClick = (lesson) => { navigate(`/lessons/${lesson.uuid}`); }; const handleContinue = (lesson) => { navigate(`/units/${uuid}/read`, { state: { lessonId: lesson.lesson_id } }); }; const handleQuizClick = () => { navigate(`/units/${uuid}/read`, { state: { quizId: true } }); }; return (
Unit

{unitDetail?.title ?? "Unit"}

{unitDetail?.description ?? ""}

{contentNotReady ? (
This unit is currently being prepared. Please check back later.
) : ( <>
{lessons.length} {lessons.length === 1 ? "lesson" : "lessons"} · {formatDuration(unitDetail.duration_seconds) ?? "—"} total · {completedCount} of {lessons.length} complete {requirementDef && ( <> · {RequirementIcon && } {requirementDef.label} )}
{unitDetail.is_completed && (
Success — you've completed this unit.
)}

Lessons in this unit

)}
); }; export default UnitDetails;