diff --git a/apps/dashboard/src/lib/features/course/components/course-progress-card.svelte b/apps/dashboard/src/lib/features/course/components/course-progress-card.svelte index 515a34ed..eb70e97d 100644 --- a/apps/dashboard/src/lib/features/course/components/course-progress-card.svelte +++ b/apps/dashboard/src/lib/features/course/components/course-progress-card.svelte @@ -4,27 +4,33 @@ import type { ContentProgress } from '$features/course/utils/content'; interface Props { - progress: ContentProgress; + progress?: ContentProgress; class?: string; } let { progress, class: className = '' }: Props = $props(); + + const percent = $derived(progress?.percent ?? 0); + const lessonsComplete = $derived(progress?.lessonsComplete ?? 0); + const lessonsTotal = $derived(progress?.lessonsTotal ?? 0); + const exercisesComplete = $derived(progress?.exercisesComplete ?? 0); + const exercisesTotal = $derived(progress?.exercisesTotal ?? 0);
{$t('course.sidebar.progress.title')} - {progress.percent}% + {percent}%
- +

{$t('course.sidebar.progress.lessons', { - completed: progress.lessonsComplete, - total: progress.lessonsTotal - })}{#if progress.exercisesTotal > 0} + completed: lessonsComplete, + total: lessonsTotal + })}{#if exercisesTotal > 0} · {$t('course.sidebar.progress.exercises', { - completed: progress.exercisesComplete, - total: progress.exercisesTotal + completed: exercisesComplete, + total: exercisesTotal })}{/if}

diff --git a/apps/dashboard/src/lib/features/course/components/lesson/content-navigation-actions.svelte b/apps/dashboard/src/lib/features/course/components/lesson/content-navigation-actions.svelte index 5806c72e..96177c31 100644 --- a/apps/dashboard/src/lib/features/course/components/lesson/content-navigation-actions.svelte +++ b/apps/dashboard/src/lib/features/course/components/lesson/content-navigation-actions.svelte @@ -29,9 +29,11 @@ courseId: string; /** When on an exercise page, pass this to show prev/next content in content order (no mark-complete). */ exerciseId?: string; + /** When false, hide prev/next chevrons (mobile bottom nav already has them). */ + showPrevNext?: boolean; } - let { lessonId, courseId, exerciseId }: Props = $props(); + let { lessonId, courseId, exerciseId, showPrevNext = true }: Props = $props(); let isMarkingComplete = $state(false); @@ -229,7 +231,7 @@ {watchProgressTooltip} - {:else if showMarkComplete && lessonId && !isLessonLocked && (showVideoWatchCompleteState || !isVideoWatchLesson)} + {:else if showMarkComplete && lessonId && !isLessonLocked && !isLessonComplete && !isVideoWatchLesson} - - - {prevNavTooltip} - - + {#if showPrevNext} +
+ + + + + + {prevNavTooltip} + + - - - - - - {nextNavTooltip} - - -
+ + + + + + {nextNavTooltip} + + + + {/if} diff --git a/apps/dashboard/src/lib/features/course/components/mobile/course-mobile-bottom-nav.svelte b/apps/dashboard/src/lib/features/course/components/mobile/course-mobile-bottom-nav.svelte index 7eb1e5a2..0b96c577 100644 --- a/apps/dashboard/src/lib/features/course/components/mobile/course-mobile-bottom-nav.svelte +++ b/apps/dashboard/src/lib/features/course/components/mobile/course-mobile-bottom-nav.svelte @@ -77,6 +77,7 @@ goToContent(previousItem)} diff --git a/apps/dashboard/src/lib/features/course/components/mobile/course-mobile-outline-sheet.svelte b/apps/dashboard/src/lib/features/course/components/mobile/course-mobile-outline-sheet.svelte index aa240a2f..561401f0 100644 --- a/apps/dashboard/src/lib/features/course/components/mobile/course-mobile-outline-sheet.svelte +++ b/apps/dashboard/src/lib/features/course/components/mobile/course-mobile-outline-sheet.svelte @@ -52,7 +52,7 @@
- +
diff --git a/apps/dashboard/src/lib/features/course/pages/lesson.svelte b/apps/dashboard/src/lib/features/course/pages/lesson.svelte index a30a4636..f10c5540 100644 --- a/apps/dashboard/src/lib/features/course/pages/lesson.svelte +++ b/apps/dashboard/src/lib/features/course/pages/lesson.svelte @@ -433,8 +433,8 @@
- {#if mode === MODES.view && $isCourseLearnerView && !showMobileBottomNav} - + {#if mode === MODES.view && $isCourseLearnerView} + {/if} diff --git a/packages/storybook/src/molecules/public-course/public-course.stories.svelte b/packages/storybook/src/molecules/public-course/public-course.stories.svelte index 26b0217c..e12da58a 100644 --- a/packages/storybook/src/molecules/public-course/public-course.stories.svelte +++ b/packages/storybook/src/molecules/public-course/public-course.stories.svelte @@ -124,6 +124,25 @@ {/snippet} + + {#snippet template()} +
+ console.log('prev')} + onNext={() => console.log('next')} + onOpenSheet={() => console.log('open sheet')} + /> +
+ {/snippet} +
+ {#snippet template()} {@const activeSlug = 'module-10-lesson-4'} diff --git a/packages/ui/src/custom/public-course/bottom-nav.svelte b/packages/ui/src/custom/public-course/bottom-nav.svelte index f9930d59..ca14f6ea 100644 --- a/packages/ui/src/custom/public-course/bottom-nav.svelte +++ b/packages/ui/src/custom/public-course/bottom-nav.svelte @@ -8,6 +8,8 @@ /** Current position — e.g. "3 of 12" — plus a subline — e.g. "Hallucination & limitations". */ positionLabel: string; sublineLabel?: string; + /** When true, a filled check is shown to the right of `sublineLabel`. */ + sublineComplete?: boolean; hasPrev: boolean; hasNext: boolean; onPrev: () => void; @@ -27,6 +29,7 @@ let { positionLabel, sublineLabel, + sublineComplete = false, hasPrev, hasNext, onPrev, @@ -98,7 +101,21 @@ {positionLabel} {#if sublineLabel} - {sublineLabel} + + {sublineLabel} + {#if sublineComplete} + + {/if} + {/if}