diff --git a/src/modules/client/pages/UnitList.jsx b/src/modules/client/pages/UnitList.jsx
index c887d66..6de4ea1 100644
--- a/src/modules/client/pages/UnitList.jsx
+++ b/src/modules/client/pages/UnitList.jsx
@@ -336,9 +336,13 @@ const UnitList = () => {
const resetCompletion = () => setSelectedCompletion(false);
- // ── No-assessment notice — shown once per course visit, informational only ──
- // Gated behind the "Course notices" toggle in Account Settings.
+ // ── Course-readiness notices — shown once per course visit, informational only ──
+ // Gated behind the "Course notices" toggle in Account Settings. Sequenced so at
+ // most one is open at a time: missing-quiz notice (unit-level) takes priority,
+ // then no-assessment (course-level) once that one is dismissed.
+ const [missingQuizDialogOpen, setMissingQuizDialogOpen] = useState(false);
const [noAssessmentDialogOpen, setNoAssessmentDialogOpen] = useState(false);
+ const missingQuizNoticeShown = useRef(false);
const noAssessmentNoticeShown = useRef(false);
useEffect(() => {
@@ -346,18 +350,27 @@ const UnitList = () => {
}, []); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => {
+ missingQuizNoticeShown.current = false;
noAssessmentNoticeShown.current = false;
}, [courseId]);
useEffect(() => {
- const shouldShow =
+ const noticesEnabled =
course && !courseBlocked && course.duration_seconds &&
- !course.assessment && !noAssessmentNoticeShown.current &&
profile && (profile.personal_info?.show_course_notices ?? true);
- if (!shouldShow) return;
- noAssessmentNoticeShown.current = true;
- setNoAssessmentDialogOpen(true);
- }, [course, courseBlocked, profile]);
+ if (!noticesEnabled) return;
+
+ if (!missingQuizNoticeShown.current && (course.units ?? []).some((u) => !u.quiz)) {
+ missingQuizNoticeShown.current = true;
+ setMissingQuizDialogOpen(true);
+ return; // let the assessment notice wait until this one is dismissed
+ }
+ if (missingQuizDialogOpen) return;
+ if (!noAssessmentNoticeShown.current && !course.assessment) {
+ noAssessmentNoticeShown.current = true;
+ setNoAssessmentDialogOpen(true);
+ }
+ }, [course, courseBlocked, profile, missingQuizDialogOpen]);
// ── Session guard — block navigation while a quiz/assessment is in progress ─
const quizActiveRef = useRef(false); // sync check inside handlers
@@ -847,6 +860,14 @@ const UnitList = () => {
+ {/* ── Missing-quiz notice — informational, shown once per course visit ── */}
+
+
{/* ── No-assessment notice — informational, shown once per course visit ── */}