feat: improve LMS course discovery and enrollment UX

- Add paginated recommended courses to LMS dashboard (top 3, list
    view)
    and explore page (12 per page); exclude courses blocking new
    students
  - Polish course preview modal: remove padding, render requirements as
    HTML, round banner image, secondary close button
  - Redirect to course start page after successful enrollment instead of
    /lms;
    keep spinner active until navigation completes
  - Auto-enable "allow new students" when a course is published
  - Move Explore after My Learning in LMS sidebar nav
  - Move Certificates after Content in course sidebar
  - Add hiddenColumns prop to CourseListRow; show "Learn more" button
    instead of actions menu in LMS explore context
This commit is contained in:
Rotimi Best
2026-06-11 14:22:18 +01:00
parent 4e24e3cb63
commit c8154409f5
15 changed files with 465 additions and 194 deletions
@@ -158,7 +158,8 @@
grading: $settings.grading,
lessonDownload: $settings.lessonDownload,
allowNewStudent: $settings.allowNewStudents ?? false,
isContentGroupingEnabled: $settings.isContentGroupingEnabled
isContentGroupingEnabled: $settings.isContentGroupingEnabled,
progressionMode: $settings.progressionMode
} as NonNullable<Course['metadata']>;
const updatedCourse = {
@@ -222,6 +223,7 @@
isPublished: !!course.isPublished,
allowNewStudents: !!course.metadata?.allowNewStudent,
isContentGroupingEnabled: course.metadata?.isContentGroupingEnabled ?? true,
progressionMode: course.metadata?.progressionMode ?? 'free',
callout: normalizeCallout(course.callout)
});
});
@@ -522,6 +524,35 @@
<Field.Separator />
<Field.Set>
<Field.Legend>{$t('course.navItem.settings.progression_mode_title')}</Field.Legend>
<Field.Description>{$t('course.navItem.settings.progression_mode_description')}</Field.Description>
<Field.Field>
<RadioGroup.Root
value={$settings.progressionMode}
onValueChange={(value) => {
if (value === 'free' || value === 'sequential') {
$settings.progressionMode = value;
hasUnsavedChanges = true;
}
}}
>
<div class="flex flex-col gap-3">
<div class="flex items-center gap-2">
<RadioGroup.Item value="free" id="progression-free" />
<Label for="progression-free">{$t('course.navItem.settings.progression_mode_free')}</Label>
</div>
<div class="flex items-center gap-2">
<RadioGroup.Item value="sequential" id="progression-sequential" />
<Label for="progression-sequential">{$t('course.navItem.settings.progression_mode_sequential')}</Label>
</div>
</div>
</RadioGroup.Root>
</Field.Field>
</Field.Set>
<Field.Separator />
<Field.Set>
<Field.Legend>{$t('course.navItem.settings.lesson_download')}</Field.Legend>
<Field.Description>{$t('course.navItem.settings.available')}</Field.Description>
@@ -737,6 +768,7 @@
checked={$settings.isPublished}
onCheckedChange={(checked) => {
$settings.isPublished = checked;
if (checked) $settings.allowNewStudents = true;
hasUnsavedChanges = true;
}}
/>