Completed studies: finishing a study keeps access after leaving; certificates always shown; no reminders for finished studies; v2.11.0
Publish Container / build (push) Successful in 15m31s
Publish Container / build (push) Successful in 15m31s
- Completion is stored on the user (completedStudySlugs, sticky) when every lesson is done; backfilled at startup - Lessons, notes, progress, quiz, community and certificate stay open for completed studies after leaving the enrollment - Dashboard/My Account list completed studies with Review Lessons and certificate access - Study page shows a completed banner - Lesson-release reminders, weekly digest and re-engagement emails skip finished studies - Fix: streak fields (current/longest/last studied) and firstCompletionAt were dropped on every restart when users were loaded - Tests for completion/access/re-engagement Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7301982bb1
commit
bb83f3e8c5
13 files changed
+221
-52
No files matched your search
@@ -1489,6 +1489,9 @@ export function sanitizeStudyUsers(value) {
|
||||
const enrolledStudySlugs = Array.isArray(item?.enrolledStudySlugs)
|
||||
? Array.from(new Set(item.enrolledStudySlugs.map(normalizeStudySlug).filter(Boolean))).slice(0, MAX_STUDY_ENROLLMENTS_PER_USER)
|
||||
: []
|
||||
const completedStudySlugs = Array.isArray(item?.completedStudySlugs)
|
||||
? Array.from(new Set(item.completedStudySlugs.map(normalizeStudySlug).filter(Boolean))).slice(0, MAX_STUDY_ENROLLMENTS_PER_USER * 4)
|
||||
: []
|
||||
const displayName = typeof item?.displayName === 'string' ? item.displayName.trim().slice(0, 80) : ''
|
||||
const subscribeNewsletter = item?.subscribeNewsletter !== false
|
||||
const studyRemindersEnabled = item?.studyRemindersEnabled === true
|
||||
@@ -1523,6 +1526,11 @@ export function sanitizeStudyUsers(value) {
|
||||
subscribeNewsletter,
|
||||
studyRemindersEnabled,
|
||||
enrolledStudySlugs,
|
||||
completedStudySlugs,
|
||||
currentStreak: Number.isFinite(item?.currentStreak) && item.currentStreak > 0 ? Math.floor(item.currentStreak) : 0,
|
||||
longestStreak: Number.isFinite(item?.longestStreak) && item.longestStreak > 0 ? Math.floor(item.longestStreak) : 0,
|
||||
lastStudiedDate: typeof item?.lastStudiedDate === 'string' ? item.lastStudiedDate : null,
|
||||
firstCompletionAt: typeof item?.firstCompletionAt === 'string' ? item.firstCompletionAt : null,
|
||||
avatarUrl: typeof item?.avatarUrl === 'string' ? item.avatarUrl.trim() : '',
|
||||
createdAt: typeof item?.createdAt === 'string' ? item.createdAt : null,
|
||||
updatedAt: typeof item?.updatedAt === 'string' ? item.updatedAt : null,
|
||||
|
||||
Reference in new issue
Block a user