feat(student): add learning tabs and Lab hint/assessment UX

StudentDashboard is now tabbed: My Learning (the original Phase 2A/2B flow, extracted
unchanged into MyLearningTab and extended with an overall percent-complete bar), Practice,
Assessments (available/active-with-live-countdown/history), Capstone (locked checklist ->
unlocked -> start/resume -> completed), Achievements (a flat dated list, not a leaderboard).

Inside the Lab UI: ProgressiveHints replaces the static hint array render when the Gateway has
stripped hints (detected via scenario.hints being undefined but hint_count present - standalone
dev mode never sees this, so it keeps the original behavior); a new top-level AssessmentBanner
shows a live countdown and completion count whenever a Platform assessment is running,
rendered alongside (not replacing) the pre-existing Lab-local exam-mode UI, which is untouched.
This commit is contained in:
2026-08-18 14:35:59 -05:00
parent 7e5f357b6f
commit d4db8f99f5
12 changed files with 680 additions and 140 deletions
+13
View File
@@ -66,8 +66,21 @@ export const api = {
whoami: () => fetch('/api/session/whoami').then(json),
curriculumPath: () => fetch('/api/curriculum/path').then(json),
curriculumState: () => fetch('/api/curriculum/state').then(json),
environmentStatus: () => fetch('/api/environment/status').then(json),
launchEnvironment: () => mutate('/api/environment/launch'),
resetEnvironment: () => mutate('/api/environment/reset'),
recentAttempts: () => fetch('/api/attempts/recent').then(json),
assessments: () => fetch('/api/assessments').then(json),
activeAssessment: () => fetch('/api/assessments/active').then(json),
assessmentDetail: (sessionId) => fetch(`/api/assessments/${sessionId}`).then(json),
startAssessment: (definitionId) => mutate(`/api/assessments/${definitionId}/start`),
submitAssessment: (sessionId) => mutate(`/api/assessments/${sessionId}/submit`),
capstone: () => fetch('/api/capstone').then(json),
achievements: () => fetch('/api/achievements').then(json),
}