working on course details again

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-04 06:09:01 +08:00
parent 530da0b49d
commit 1d7d778a98
2 changed files with 36 additions and 9 deletions
+15 -8
View File
@@ -348,17 +348,21 @@ const CertCard = ({ courseTitle, courseLevel, badgeColor, badgeImageUrl, pending
// ─── Course Units (spine + cards) ───────────────────────────────────────────── // ─── Course Units (spine + cards) ─────────────────────────────────────────────
const CourseUnits = ({ units = [], courseId, courseTitle, courseLevel, badgeColor, badgeImageUrl, onToggle, isCompleted, pendingCert, certificate, assessment }) => { const CourseUnits = ({ units = [], courseId, courseTitle, courseLevel, badgeColor, badgeImageUrl, onToggle, isCompleted, pendingCert, certificate, assessment, contentNotReady }) => {
const wrapRef = useRef(null); const wrapRef = useRef(null);
const cardRefs = useRef([]); const cardRefs = useRef([]);
// Build a flat ordered list of nodes: [unit, unit, ..., assessment?, cert] // Build a flat ordered list of nodes: [unit, unit, ..., assessment?, cert]
// Quiz is rendered inside each unit accordion, not as a separate spine node. // Quiz is rendered inside each unit accordion, not as a separate spine node.
const nodes = [ // While content isn't ready yet, no unit/lesson/assessment titles are shown —
...units.map((unit) => ({ type: "unit", unit })), // only the Rewards (cert) card, as a preview of what's to come.
...(assessment ? [{ type: "assessment", assessment }] : []), const nodes = contentNotReady
{ type: "cert" }, ? [{ type: "cert" }]
]; : [
...units.map((unit) => ({ type: "unit", unit })),
...(assessment ? [{ type: "assessment", assessment }] : []),
{ type: "cert" },
];
const totalNodes = nodes.length; const totalNodes = nodes.length;
const visibleNodes = useVisibleNodes(cardRefs, totalNodes); const visibleNodes = useVisibleNodes(cardRefs, totalNodes);
const [mids, setMids] = useState([]); const [mids, setMids] = useState([]);
@@ -702,10 +706,12 @@ const CourseDetails = () => {
</> </>
)} )}
{/* Units */} {/* Units — while content isn't ready, only Rewards is shown */}
{course?.units?.length > 0 && ( {course?.units?.length > 0 && (
<> <>
<div className="font-bold text-2xl">Course content</div> <div className="font-bold text-2xl">
{contentNotReady ? "Rewards" : "Course content"}
</div>
<CourseUnits <CourseUnits
units={course.units} units={course.units}
courseId={courseId} courseId={courseId}
@@ -717,6 +723,7 @@ const CourseDetails = () => {
pendingCert={course.pending_certificate ?? null} pendingCert={course.pending_certificate ?? null}
certificate={course.certificate ?? null} certificate={course.certificate ?? null}
assessment={course.assessment ?? null} assessment={course.assessment ?? null}
contentNotReady={contentNotReady}
/> />
</> </>
)} )}
+21 -1
View File
@@ -1,7 +1,7 @@
import { useState, useCallback, useEffect, useRef } from "react"; import { useState, useCallback, useEffect, useRef } from "react";
import AppBreadcrumb from "@/components/generic/Breadcrumb/AppBreadcrumb"; import AppBreadcrumb from "@/components/generic/Breadcrumb/AppBreadcrumb";
import { useParams, useNavigate, useLocation, useBlocker } from "react-router-dom"; import { useParams, useNavigate, useLocation, useBlocker } from "react-router-dom";
import { House, TableOfContents, ArrowRight, ClipboardList, GraduationCap, Trophy, Lock, CheckCircle2, Circle, Zap, ListChecks, ChevronsLeft, ChevronsRight } from "lucide-react"; import { House, TableOfContents, ArrowRight, ClipboardList, GraduationCap, Trophy, Lock, CheckCircle2, Circle, Zap, ListChecks, ChevronsLeft, ChevronsRight, Hourglass } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Accordion, Accordion,
@@ -726,6 +726,26 @@ const UnitList = () => {
); );
} }
// ── Content not ready (duration_seconds === 0 — no lesson content authored yet) ──
if (!courseLoading && course && !course.duration_seconds) {
return (
<div className="flex flex-col items-center gap-6 py-32 text-center px-4">
<div className="h-16 w-16 rounded-full bg-muted flex items-center justify-center">
<Hourglass className="size-7 text-muted-foreground" />
</div>
<div className="space-y-2 max-w-sm">
<h2 className="text-xl font-semibold">Course Not Yet Available</h2>
<p className="text-sm text-muted-foreground leading-relaxed">
This course is currently being prepared. Please check back later.
</p>
</div>
<Button variant="outline" onClick={() => navigate(`/course/${courseId}`)} className="gap-1.5">
Back to Course Details
</Button>
</div>
);
}
return ( return (
<> <>
<PageMeta title={pageTitle} /> <PageMeta title={pageTitle} />