musora-content-services 2.28.1 → 2.28.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/docs/ContentOrganization.html +2 -2
  3. package/docs/Gamification.html +2 -2
  4. package/docs/UserManagementSystem.html +2 -2
  5. package/docs/api_types.js.html +2 -2
  6. package/docs/config.js.html +2 -2
  7. package/docs/content-org_content-org.js.html +2 -2
  8. package/docs/content-org_playlists-types.js.html +2 -2
  9. package/docs/content-org_playlists.js.html +2 -2
  10. package/docs/content.js.html +21 -14
  11. package/docs/gamification_awards.js.html +4 -522
  12. package/docs/gamification_gamification.js.html +2 -2
  13. package/docs/gamification_types.js.html +2 -2
  14. package/docs/global.html +2 -2
  15. package/docs/index.html +2 -2
  16. package/docs/module-Awards.html +2 -2
  17. package/docs/module-Config.html +2 -2
  18. package/docs/module-Content-Services-V2.html +7 -7
  19. package/docs/module-Interests.html +2 -2
  20. package/docs/module-Permissions.html +2 -2
  21. package/docs/module-Playlists.html +2 -2
  22. package/docs/module-Railcontent-Services.html +42 -42
  23. package/docs/module-Sanity-Services.html +228 -46
  24. package/docs/module-Sessions.html +2 -2
  25. package/docs/module-UserActivity.html +49 -23
  26. package/docs/module-UserChat.html +2 -2
  27. package/docs/module-UserManagement.html +8 -8
  28. package/docs/module-UserNotifications.html +465 -21
  29. package/docs/module-UserProfile.html +106 -2
  30. package/docs/railcontent.js.html +13 -16
  31. package/docs/sanity.js.html +95 -49
  32. package/docs/userActivity.js.html +110 -87
  33. package/docs/user_chat.js.html +2 -2
  34. package/docs/user_interests.js.html +2 -2
  35. package/docs/user_management.js.html +5 -3
  36. package/docs/user_notifications.js.html +63 -15
  37. package/docs/user_permissions.js.html +2 -2
  38. package/docs/user_profile.js.html +18 -2
  39. package/docs/user_sessions.js.html +2 -2
  40. package/docs/user_types.js.html +2 -2
  41. package/docs/user_user-management-system.js.html +2 -2
  42. package/package.json +1 -1
  43. package/src/services/imageSRCVerify.js +0 -0
  44. package/src/services/railcontent.js +5 -5
  45. package/src/services/sanity.js +2 -2
  46. package/src/services/userActivity.js +2 -0
  47. package/.claude/settings.local.json +0 -8
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Awards.html">Awards</a><ul class='methods'><li data-type='method'><a href="module-Awards.html#.fetchAwardsForUser">fetchAwardsForUser</a></li></ul></li><li><a href="module-Config.html">Config</a><ul class='methods'><li data-type='method'><a href="module-Config.html#.initializeService">initializeService</a></li></ul></li><li><a href="module-Content-Services-V2.html">Content-Services-V2</a><ul class='methods'><li data-type='method'><a href="module-Content-Services-V2.html#.getContentRows">getContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getNewAndUpcoming">getNewAndUpcoming</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecent">getRecent</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecommendedForYou">getRecommendedForYou</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getScheduleContentRows">getScheduleContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getTabResults">getTabResults</a></li></ul></li><li><a href="module-Interests.html">Interests</a><ul class='methods'><li data-type='method'><a href="module-Interests.html#.fetchInterests">fetchInterests</a></li><li data-type='method'><a href="module-Interests.html#.fetchUninterests">fetchUninterests</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsInterested">markContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsNotInterested">markContentAsNotInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsInterested">removeContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsNotInterested">removeContentAsNotInterested</a></li></ul></li><li><a href="module-Permissions.html">Permissions</a><ul class='methods'><li data-type='method'><a href="module-Permissions.html#.fetchUserPermissions">fetchUserPermissions</a></li><li data-type='method'><a href="module-Permissions.html#.reset">reset</a></li></ul></li><li><a href="module-Playlists.html">Playlists</a><ul class='methods'><li data-type='method'><a href="module-Playlists.html#.addItemToPlaylist">addItemToPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.createPlaylist">createPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.deletePlaylist">deletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.duplicatePlaylist">duplicatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylist">fetchPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylistItems">fetchPlaylistItems</a></li><li data-type='method'><a href="module-Playlists.html#.fetchUserPlaylists">fetchUserPlaylists</a></li><li data-type='method'><a href="module-Playlists.html#.togglePlaylistPrivate">togglePlaylistPrivate</a></li><li data-type='method'><a href="module-Playlists.html#.undeletePlaylist">undeletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.updatePlaylist">updatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~deleteItemsFromPlaylist">deleteItemsFromPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~likePlaylist">likePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~reportPlaylist">reportPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~restoreItemFromPlaylist">restoreItemFromPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~unlikePlaylist">unlikePlaylist</a></li></ul></li><li><a href="module-Railcontent-Services.html">Railcontent-Services</a><ul class='methods'><li data-type='method'><a href="module-Railcontent-Services.html#.assignModeratorToComment">assignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.closeComment">closeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.createComment">createComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deleteComment">deleteComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.editComment">editComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchAllCompletedStates">fetchAllCompletedStates</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCarouselCardData">fetchCarouselCardData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeIndexMetadata">fetchChallengeIndexMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeLessonData">fetchChallengeLessonData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeMetadata">fetchChallengeMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeUserActiveChallenges">fetchChallengeUserActiveChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComment">fetchComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCommentRelies">fetchCommentRelies</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComments">fetchComments</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedChallenges">fetchCompletedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedContent">fetchCompletedContent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedState">fetchCompletedState</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentInProgress">fetchContentInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentPageUserData">fetchContentPageUserData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchNextContentDataForParent">fetchNextContentDataForParent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchOwnedChallenges">fetchOwnedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchRecentUserActivities">fetchRecentUserActivities</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchSongsInProgress">fetchSongsInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchTopComment">fetchTopComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserAward">fetchUserAward</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserBadges">fetchUserBadges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserChallengeProgress">fetchUserChallengeProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserPracticeNotes">fetchUserPracticeNotes</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.likeComment">likeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.openComment">openComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesCommunityNotification">postChallengesCommunityNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnroll">postChallengesEnroll</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnrollmentNotification">postChallengesEnrollmentNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesHideCompletedBanner">postChallengesHideCompletedBanner</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesLeave">postChallengesLeave</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSetStartDate">postChallengesSetStartDate</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSoloNotification">postChallengesSoloNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesUnlock">postChallengesUnlock</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.replyToComment">replyToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.reportComment">reportComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.restoreComment">restoreComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.setStudentViewForUser">setStudentViewForUser</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unassignModeratorToComment">unassignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unlikeComment">unlikeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#~fetchLastInteractedChild">fetchLastInteractedChild</a></li></ul></li><li><a href="module-Sanity-Services.html">Sanity-Services</a><ul class='methods'><li data-type='method'><a href="module-Sanity-Services.html#.fetchAll">fetchAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllFilterOptions">fetchAllFilterOptions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllPacks">fetchAllPacks</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtistLessons">fetchArtistLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtists">fetchArtists</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentId">fetchByRailContentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentIds">fetchByRailContentIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByReference">fetchByReference</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCoachLessons">fetchCoachLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchComingSoon">fetchComingSoon</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCommentModContentData">fetchCommentModContentData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchFoundation">fetchFoundation</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchGenreLessons">fetchGenreLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLeaving">fetchLeaving</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonContent">fetchLessonContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonsFeaturingThisContent">fetchLessonsFeaturingThisContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMetadata">fetchMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethod">fetchMethod</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildren">fetchMethodChildren</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildrenIds">fetchMethodChildrenIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodPreviousNextLesson">fetchMethodPreviousNextLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNewReleases">fetchNewReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNextPreviousLesson">fetchNextPreviousLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchOtherSongVersions">fetchOtherSongVersions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackAll">fetchPackAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackData">fetchPackData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchParentForDownload">fetchParentForDownload</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedLessons">fetchRelatedLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedRecommendedContent">fetchRelatedRecommendedContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedSongs">fetchRelatedSongs</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchReturning">fetchReturning</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSanity">fetchSanity</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchScheduledReleases">fetchScheduledReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchShowsData">fetchShowsData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongArtistCount">fetchSongArtistCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongById">fetchSongById</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchUpcomingEvents">fetchUpcomingEvents</a></li><li data-type='method'><a href="module-Sanity-Services.html#.jumpToContinueContent">jumpToContinueContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#~fetchRelatedByLicense">fetchRelatedByLicense</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getNextAndPreviousQuarterDates">getNextAndPreviousQuarterDates</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getQueryFromPage">getQueryFromPage</a></li><li data-type='method'><a href="module-Sanity-Services.html#~handleCustomFetchAll">handleCustomFetchAll</a></li></ul></li><li><a href="module-Sessions.html">Sessions</a><ul class='methods'><li data-type='method'><a href="module-Sessions.html#.login">login</a></li><li data-type='method'><a href="module-Sessions.html#.logout">logout</a></li></ul></li><li><a href="module-UserActivity.html">UserActivity</a><ul class='methods'><li data-type='method'><a href="module-UserActivity.html#.calculateLongestStreaks">calculateLongestStreaks</a></li><li data-type='method'><a href="module-UserActivity.html#.createPracticeNotes">createPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.deletePracticeSession">deletePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.deleteUserActivity">deleteUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeNotes">getPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeSessions">getPracticeSessions</a></li><li data-type='method'><a href="module-UserActivity.html#.getProgressRows">getProgressRows</a></li><li data-type='method'><a href="module-UserActivity.html#.getRecentActivity">getRecentActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserMonthlyStats">getUserMonthlyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserWeeklyStats">getUserWeeklyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.pinProgressRow">pinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserActivity">recordUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserPractice">recordUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.removeUserPractice">removeUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.restorePracticeSession">restorePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.restoreUserPractice">restoreUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.unpinProgressRow">unpinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.updatePracticeNotes">updatePracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.updateUserPractice">updateUserPractice</a></li></ul></li><li><a href="module-UserChat.html">UserChat</a><ul class='methods'><li data-type='method'><a href="module-UserChat.html#.fetchChatSettings">fetchChatSettings</a></li></ul></li><li><a href="module-UserManagement.html">UserManagement</a><ul class='methods'><li data-type='method'><a href="module-UserManagement.html#.blockUser">blockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.deletePicture">deletePicture</a></li><li data-type='method'><a href="module-UserManagement.html#.getUserData">getUserData</a></li><li data-type='method'><a href="module-UserManagement.html#.unblockUser">unblockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPicture">uploadPicture</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPictureFromS3">uploadPictureFromS3</a></li></ul></li><li><a href="module-UserNotifications.html">UserNotifications</a><ul class='methods'><li data-type='method'><a href="module-UserNotifications.html#.deleteNotification">deleteNotification</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotificationSettings">fetchNotificationSettings</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotifications">fetchNotifications</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchUnreadCount">fetchUnreadCount</a></li><li data-type='method'><a href="module-UserNotifications.html#.markAllNotificationsAsRead">markAllNotificationsAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsRead">markNotificationAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsUnread">markNotificationAsUnread</a></li><li data-type='method'><a href="module-UserNotifications.html#.updateNotificationSetting">updateNotificationSetting</a></li></ul></li><li><a href="module-UserProfile.html">UserProfile</a><ul class='methods'><li data-type='method'><a href="module-UserProfile.html#.otherStats">otherStats</a></li></ul></li></ul><h3>Namespaces</h3><ul><li><a href="ContentOrganization.html">ContentOrganization</a></li><li><a href="Gamification.html">Gamification</a></li><li><a href="UserManagementSystem.html">UserManagementSystem</a></li></ul><h3><a href="global.html">Global</a></h3>
32
+ <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Awards.html">Awards</a><ul class='methods'><li data-type='method'><a href="module-Awards.html#.fetchAwardsForUser">fetchAwardsForUser</a></li></ul></li><li><a href="module-Config.html">Config</a><ul class='methods'><li data-type='method'><a href="module-Config.html#.initializeService">initializeService</a></li></ul></li><li><a href="module-Content-Services-V2.html">Content-Services-V2</a><ul class='methods'><li data-type='method'><a href="module-Content-Services-V2.html#.getContentRows">getContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getNewAndUpcoming">getNewAndUpcoming</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecent">getRecent</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecommendedForYou">getRecommendedForYou</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getScheduleContentRows">getScheduleContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getTabResults">getTabResults</a></li></ul></li><li><a href="module-Interests.html">Interests</a><ul class='methods'><li data-type='method'><a href="module-Interests.html#.fetchInterests">fetchInterests</a></li><li data-type='method'><a href="module-Interests.html#.fetchUninterests">fetchUninterests</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsInterested">markContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsNotInterested">markContentAsNotInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsInterested">removeContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsNotInterested">removeContentAsNotInterested</a></li></ul></li><li><a href="module-Permissions.html">Permissions</a><ul class='methods'><li data-type='method'><a href="module-Permissions.html#.fetchUserPermissions">fetchUserPermissions</a></li><li data-type='method'><a href="module-Permissions.html#.reset">reset</a></li></ul></li><li><a href="module-Playlists.html">Playlists</a><ul class='methods'><li data-type='method'><a href="module-Playlists.html#.addItemToPlaylist">addItemToPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.createPlaylist">createPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.deletePlaylist">deletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.duplicatePlaylist">duplicatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylist">fetchPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylistItems">fetchPlaylistItems</a></li><li data-type='method'><a href="module-Playlists.html#.fetchUserPlaylists">fetchUserPlaylists</a></li><li data-type='method'><a href="module-Playlists.html#.togglePlaylistPrivate">togglePlaylistPrivate</a></li><li data-type='method'><a href="module-Playlists.html#.undeletePlaylist">undeletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.updatePlaylist">updatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~deleteItemsFromPlaylist">deleteItemsFromPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~likePlaylist">likePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~reportPlaylist">reportPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~restoreItemFromPlaylist">restoreItemFromPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~unlikePlaylist">unlikePlaylist</a></li></ul></li><li><a href="module-Railcontent-Services.html">Railcontent-Services</a><ul class='methods'><li data-type='method'><a href="module-Railcontent-Services.html#.assignModeratorToComment">assignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.closeComment">closeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.createComment">createComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deleteComment">deleteComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.editComment">editComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchAllCompletedStates">fetchAllCompletedStates</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCarouselCardData">fetchCarouselCardData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeIndexMetadata">fetchChallengeIndexMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeLessonData">fetchChallengeLessonData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeMetadata">fetchChallengeMetadata</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchChallengeUserActiveChallenges">fetchChallengeUserActiveChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComment">fetchComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCommentRelies">fetchCommentRelies</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComments">fetchComments</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedChallenges">fetchCompletedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedContent">fetchCompletedContent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedState">fetchCompletedState</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentInProgress">fetchContentInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentPageUserData">fetchContentPageUserData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchNextContentDataForParent">fetchNextContentDataForParent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchOwnedChallenges">fetchOwnedChallenges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchRecentUserActivities">fetchRecentUserActivities</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchSongsInProgress">fetchSongsInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchTopComment">fetchTopComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserAward">fetchUserAward</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserBadges">fetchUserBadges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserChallengeProgress">fetchUserChallengeProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserPracticeNotes">fetchUserPracticeNotes</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.likeComment">likeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.openComment">openComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesCommunityNotification">postChallengesCommunityNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnroll">postChallengesEnroll</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesEnrollmentNotification">postChallengesEnrollmentNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesHideCompletedBanner">postChallengesHideCompletedBanner</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesLeave">postChallengesLeave</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSetStartDate">postChallengesSetStartDate</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesSoloNotification">postChallengesSoloNotification</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postChallengesUnlock">postChallengesUnlock</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.replyToComment">replyToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.reportComment">reportComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.restoreComment">restoreComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.setStudentViewForUser">setStudentViewForUser</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unassignModeratorToComment">unassignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unlikeComment">unlikeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#~fetchLastInteractedChild">fetchLastInteractedChild</a></li></ul></li><li><a href="module-Sanity-Services.html">Sanity-Services</a><ul class='methods'><li data-type='method'><a href="module-Sanity-Services.html#.fetchAll">fetchAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllFilterOptions">fetchAllFilterOptions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllPacks">fetchAllPacks</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtistLessons">fetchArtistLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtists">fetchArtists</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentId">fetchByRailContentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentIds">fetchByRailContentIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByReference">fetchByReference</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCoachLessons">fetchCoachLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchComingSoon">fetchComingSoon</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCommentModContentData">fetchCommentModContentData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchFoundation">fetchFoundation</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchGenreLessons">fetchGenreLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLeaving">fetchLeaving</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonContent">fetchLessonContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonsFeaturingThisContent">fetchLessonsFeaturingThisContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMetadata">fetchMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethod">fetchMethod</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildren">fetchMethodChildren</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildrenIds">fetchMethodChildrenIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodPreviousNextLesson">fetchMethodPreviousNextLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNewReleases">fetchNewReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNextPreviousLesson">fetchNextPreviousLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchOtherSongVersions">fetchOtherSongVersions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackAll">fetchPackAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackData">fetchPackData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchParentForDownload">fetchParentForDownload</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedLessons">fetchRelatedLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedRecommendedContent">fetchRelatedRecommendedContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedSongs">fetchRelatedSongs</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchReturning">fetchReturning</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSanity">fetchSanity</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchScheduledReleases">fetchScheduledReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchShowsData">fetchShowsData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSiblingContent">fetchSiblingContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongArtistCount">fetchSongArtistCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongById">fetchSongById</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchUpcomingEvents">fetchUpcomingEvents</a></li><li data-type='method'><a href="module-Sanity-Services.html#.jumpToContinueContent">jumpToContinueContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#~fetchRelatedByLicense">fetchRelatedByLicense</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getNextAndPreviousQuarterDates">getNextAndPreviousQuarterDates</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getQueryFromPage">getQueryFromPage</a></li><li data-type='method'><a href="module-Sanity-Services.html#~handleCustomFetchAll">handleCustomFetchAll</a></li></ul></li><li><a href="module-Sessions.html">Sessions</a><ul class='methods'><li data-type='method'><a href="module-Sessions.html#.login">login</a></li><li data-type='method'><a href="module-Sessions.html#.logout">logout</a></li></ul></li><li><a href="module-UserActivity.html">UserActivity</a><ul class='methods'><li data-type='method'><a href="module-UserActivity.html#.calculateLongestStreaks">calculateLongestStreaks</a></li><li data-type='method'><a href="module-UserActivity.html#.createPracticeNotes">createPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.deletePracticeSession">deletePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.deleteUserActivity">deleteUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeNotes">getPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeSessions">getPracticeSessions</a></li><li data-type='method'><a href="module-UserActivity.html#.getProgressRows">getProgressRows</a></li><li data-type='method'><a href="module-UserActivity.html#.getRecentActivity">getRecentActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserMonthlyStats">getUserMonthlyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserWeeklyStats">getUserWeeklyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.pinProgressRow">pinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserActivity">recordUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserPractice">recordUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.removeUserPractice">removeUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.restorePracticeSession">restorePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.restoreUserPractice">restoreUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.unpinProgressRow">unpinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.updatePracticeNotes">updatePracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.updateUserPractice">updateUserPractice</a></li></ul></li><li><a href="module-UserChat.html">UserChat</a><ul class='methods'><li data-type='method'><a href="module-UserChat.html#.fetchChatSettings">fetchChatSettings</a></li></ul></li><li><a href="module-UserManagement.html">UserManagement</a><ul class='methods'><li data-type='method'><a href="module-UserManagement.html#.blockUser">blockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.deletePicture">deletePicture</a></li><li data-type='method'><a href="module-UserManagement.html#.getUserData">getUserData</a></li><li data-type='method'><a href="module-UserManagement.html#.unblockUser">unblockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPicture">uploadPicture</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPictureFromS3">uploadPictureFromS3</a></li></ul></li><li><a href="module-UserNotifications.html">UserNotifications</a><ul class='methods'><li data-type='method'><a href="module-UserNotifications.html#.deleteNotification">deleteNotification</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchLiveEventPollingState">fetchLiveEventPollingState</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotificationSettings">fetchNotificationSettings</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotifications">fetchNotifications</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchUnreadCount">fetchUnreadCount</a></li><li data-type='method'><a href="module-UserNotifications.html#.markAllNotificationsAsRead">markAllNotificationsAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsRead">markNotificationAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsUnread">markNotificationAsUnread</a></li><li data-type='method'><a href="module-UserNotifications.html#.pauseLiveEventPolling">pauseLiveEventPolling</a></li><li data-type='method'><a href="module-UserNotifications.html#.startLiveEventPolling">startLiveEventPolling</a></li><li data-type='method'><a href="module-UserNotifications.html#.updateNotificationSetting">updateNotificationSetting</a></li></ul></li><li><a href="module-UserProfile.html">UserProfile</a><ul class='methods'><li data-type='method'><a href="module-UserProfile.html#.deleteProfilePicture">deleteProfilePicture</a></li><li data-type='method'><a href="module-UserProfile.html#.otherStats">otherStats</a></li></ul></li></ul><h3>Namespaces</h3><ul><li><a href="ContentOrganization.html">ContentOrganization</a></li><li><a href="Gamification.html">Gamification</a></li><li><a href="UserManagementSystem.html">UserManagementSystem</a></li></ul><h3><a href="global.html">Global</a></h3>
33
33
 
34
34
  </nav>
35
35
 
@@ -63,9 +63,9 @@ import { DataContext, UserActivityVersionKey } from './dataContext.js'
63
63
  import { fetchByRailContentIds, fetchShows } from './sanity'
64
64
  import {fetchPlaylist, fetchUserPlaylists} from "./content-org/playlists"
65
65
  import {pinnedGuidedCourses} from "./content-org/guided-courses"
66
- import {convertToTimeZone, getMonday, getWeekNumber, isSameDate, isNextDay, getTimeRemainingUntilLocal} from './dateUtils.js'
66
+ import {convertToTimeZone, getMonday, getWeekNumber, isSameDate, isNextDay, getTimeRemainingUntilLocal, toDayjs} from './dateUtils.js'
67
67
  import { globalConfig } from './config'
68
- import {collectionLessonTypes, lessonTypesMapping, progressTypesMapping, showsLessonTypes, songs} from "../contentTypeConfig";
68
+ import {collectionLessonTypes, lessonTypesMapping, progressTypesMapping, recentTypes, showsLessonTypes, songs} from "../contentTypeConfig";
69
69
  import {
70
70
  getAllStartedOrCompleted,
71
71
  getProgressPercentageByIds,
@@ -74,6 +74,9 @@ import {
74
74
  } from "./contentProgress";
75
75
  import {TabResponseType} from "../contentMetaData";
76
76
  import {isContentLikedByIds} from "./contentLikes.js";
77
+ import dayjs from 'dayjs'
78
+ import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
79
+ import weekOfYear from 'dayjs/plugin/weekOfYear'
77
80
 
78
81
  const DATA_KEY_PRACTICES = 'practices'
79
82
  const DATA_KEY_LAST_UPDATED_TIME = 'u'
@@ -133,24 +136,21 @@ export let userActivityContext = new DataContext(UserActivityVersionKey, fetchUs
133
136
  * .catch(error => console.error(error));
134
137
  */
135
138
  export async function getUserWeeklyStats() {
139
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
136
140
  let data = await userActivityContext.getData()
137
141
  let practices = data?.[DATA_KEY_PRACTICES] ?? {}
138
142
  let sortedPracticeDays = Object.keys(practices)
139
- .map((date) => new Date(date))
140
- .sort((a, b) => b - a)
141
-
142
- let today = new Date()
143
- today.setHours(0, 0, 0, 0)
144
- let startOfWeek = getMonday(today) // Get last Monday
143
+ .map((date) => toDayjs(date)) // Convert to dayjs instance
144
+ .sort((a, b) => b.valueOf() - a.valueOf())
145
+ let today = dayjs()
146
+ let startOfWeek = getMonday(today, timeZone) // Get last Monday
145
147
  let dailyStats = []
146
-
147
148
  for (let i = 0; i &lt; 7; i++) {
148
- let day = new Date(startOfWeek)
149
- day.setDate(startOfWeek.getDate() + i)
150
- let hasPractice = sortedPracticeDays.some((practiceDate) => isSameDate(practiceDate, day))
149
+ const day = startOfWeek.add(i, 'day')
150
+ let hasPractice = sortedPracticeDays.some((practiceDate) => isSameDate(practiceDate, day.format('YYYY-MM-DD')))
151
151
  let isActive = isSameDate(today, day)
152
152
  let type = hasPractice ? 'tracked' : isActive ? 'active' : 'none'
153
- dailyStats.push({ key: i, label: DAYS[i], isActive, inStreak: hasPractice, type })
153
+ dailyStats.push({ key: i, label: DAYS[i], isActive, inStreak: hasPractice, type, day: day.format('YYYY-MM-DD') })
154
154
  }
155
155
 
156
156
  let { streakMessage } = getStreaksAndMessage(practices)
@@ -189,83 +189,77 @@ export async function getUserWeeklyStats() {
189
189
  * getUserMonthlyStats({ userId: 123 }).then(console.log);
190
190
  */
191
191
  export async function getUserMonthlyStats(params = {}) {
192
- const now = new Date()
192
+ const now = dayjs()
193
193
  const {
194
- year = now.getFullYear(),
195
- month = now.getMonth(),
196
- day = 1,
194
+ year = now.year(),
195
+ month = now.month(), // 0-indexed
197
196
  userId = globalConfig.sessionConfig.userId,
198
197
  } = params
199
- let practices = await getUserPractices(userId)
200
-
201
- // Get the first day of the specified month and the number of days in that month
202
- let firstDayOfMonth = new Date(year, month, 1)
203
- let today = new Date()
204
- today.setHours(0, 0, 0, 0)
198
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
199
+ const practices = await getUserPractices(userId)
205
200
 
206
- let startOfGrid = getMonday(firstDayOfMonth)
201
+ const firstDayOfMonth = dayjs.tz(`${year}-${month + 1}-01`, timeZone).startOf('day')
202
+ const endOfMonth = firstDayOfMonth.endOf('month')
203
+ const today = dayjs().tz(timeZone).startOf('day')
207
204
 
208
- let previousWeekStart = new Date(startOfGrid)
209
- previousWeekStart.setDate(previousWeekStart.getDate() - 7)
205
+ let startOfGrid = getMonday(firstDayOfMonth, timeZone)
210
206
 
211
- let previousWeekEnd = new Date(startOfGrid)
212
- previousWeekEnd.setDate(previousWeekEnd.getDate() - 1)
207
+ // Previous week range
208
+ const previousWeekStart = startOfGrid.subtract(7, 'day')
209
+ const previousWeekEnd = startOfGrid.subtract(1, 'day')
213
210
 
214
211
  let hadStreakBeforeMonth = false
215
- for (let d = new Date(previousWeekStart); d &lt;= previousWeekEnd; d.setDate(d.getDate() + 1)) {
216
- let dayKey = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
217
- if (practices[dayKey]) {
212
+ for (let d = previousWeekStart.clone(); d.isSameOrBefore(previousWeekEnd); d = d.add(1, 'day')) {
213
+ const key = d.format('YYYY-MM-DD')
214
+ if (practices[key]) {
218
215
  hadStreakBeforeMonth = true
219
216
  break
220
217
  }
221
218
  }
222
219
 
223
- let endOfMonth = new Date(year, month + 1, 0)
224
- while (endOfMonth.getDay() !== 0) {
225
- endOfMonth.setDate(endOfMonth.getDate() + 1)
220
+ // let endOfMonth = new Date(year, month + 1, 0)
221
+ let endOfGrid = endOfMonth.clone()
222
+ while (endOfGrid.day() !== 0) {
223
+ endOfGrid = endOfGrid.add(1, 'day')
226
224
  }
227
-
228
- let daysInMonth = Math.ceil((endOfMonth - startOfGrid) / (1000 * 60 * 60 * 24)) + 1
229
-
225
+ const daysInMonth = endOfGrid.diff(startOfGrid, 'day') + 1
230
226
  let dailyStats = []
231
227
  let practiceDuration = 0
232
228
  let daysPracticed = 0
233
229
  let weeklyStats = {}
234
230
 
235
231
  for (let i = 0; i &lt; daysInMonth; i++) {
236
- let day = new Date(startOfGrid)
237
- day.setDate(startOfGrid.getDate() + i)
238
- let dayKey = `${day.getFullYear()}-${String(day.getMonth() + 1).padStart(2, '0')}-${String(day.getDate()).padStart(2, '0')}`
239
-
240
- // Check if the user has activity for the day
241
- let dayActivity = practices[dayKey] ?? null
232
+ let day = startOfGrid.add(i, 'day')
233
+ let key = day.format('YYYY-MM-DD')
234
+ let activity = practices[key] ?? null
242
235
  let weekKey = getWeekNumber(day)
243
236
 
244
237
  if (!weeklyStats[weekKey]) {
245
238
  weeklyStats[weekKey] = { key: weekKey, inStreak: false }
246
239
  }
247
240
 
248
- if (dayActivity !== null &amp;&amp; firstDayOfMonth &lt;= day &amp;&amp; day &lt;= endOfMonth) {
249
- practiceDuration += dayActivity.reduce((sum, entry) => sum + entry.duration_seconds, 0)
241
+ if (activity &amp;&amp; day.isBetween(firstDayOfMonth, endOfMonth, null, '[]')) {
242
+ practiceDuration += activity.reduce((sum, entry) => sum + entry.duration_seconds, 0)
250
243
  daysPracticed++
251
244
  }
252
245
 
253
- let isActive = isSameDate(today, day)
254
- let type = dayActivity !== null ? 'tracked' : isActive ? 'active' : 'none'
255
- let isInStreak = dayActivity !== null
256
- if (isInStreak) {
246
+ if (activity) {
257
247
  weeklyStats[weekKey].inStreak = true
258
248
  }
259
249
 
250
+ const isActive = day.isSame(today, 'day')
251
+ const type = activity ? 'tracked' : isActive ? 'active' : 'none'
252
+
260
253
  dailyStats.push({
261
254
  key: i,
262
- label: dayKey,
255
+ label: key,
263
256
  isActive,
264
- inStreak: dayActivity !== null,
257
+ inStreak: !!activity,
265
258
  type,
266
259
  })
267
260
  }
268
261
 
262
+ // Continue streak into month
269
263
  if (hadStreakBeforeMonth) {
270
264
  const firstWeekKey = getWeekNumber(startOfGrid)
271
265
  if (weeklyStats[firstWeekKey]) {
@@ -273,14 +267,15 @@ export async function getUserMonthlyStats(params = {}) {
273
267
  }
274
268
  }
275
269
 
276
- let filteredPractices = Object.keys(practices)
277
- .filter((date) => new Date(date) &lt;= endOfMonth)
278
- .reduce((obj, key) => {
279
- obj[key] = practices[key]
280
- return obj
270
+ // Filter past practices only
271
+ let filteredPractices = Object.entries(practices)
272
+ .filter(([date]) => dayjs.tz(date, timeZone).isSameOrBefore(endOfMonth))
273
+ .reduce((acc, [date, val]) => {
274
+ acc[date] = val
275
+ return acc
281
276
  }, {})
282
277
 
283
- let { currentDailyStreak, currentWeeklyStreak } = calculateStreaks(filteredPractices)
278
+ const { currentDailyStreak, currentWeeklyStreak } = calculateStreaks(filteredPractices)
284
279
 
285
280
  return {
286
281
  data: {
@@ -319,7 +314,9 @@ export async function getUserMonthlyStats(params = {}) {
319
314
  * auto: false,
320
315
  * category_id: 5,
321
316
  * title: "Guitar Warm-up",
322
- * thumbnail_url: "https://example.com/thumbnail.jpg"
317
+ * thumbnail_url: "https://example.com/thumbnail.jpg",
318
+ * instrument_id: 1,
319
+ * instrument_id: 2,
323
320
  * })
324
321
  * .then(response => console.log(response))
325
322
  * .catch(error => console.error(error));
@@ -405,9 +402,14 @@ export async function removeUserPractice(id) {
405
402
  async function (localContext) {
406
403
  if (localContext.data?.[DATA_KEY_PRACTICES]) {
407
404
  Object.keys(localContext.data[DATA_KEY_PRACTICES]).forEach((date) => {
408
- localContext.data[DATA_KEY_PRACTICES][date] = localContext.data[DATA_KEY_PRACTICES][
409
- date
410
- ].filter((practice) => practice.id !== id)
405
+ const filtered = localContext.data[DATA_KEY_PRACTICES][date].filter(
406
+ (practice) => practice.id !== id
407
+ )
408
+ if (filtered.length > 0) {
409
+ localContext.data[DATA_KEY_PRACTICES][date] = filtered
410
+ } else {
411
+ delete localContext.data[DATA_KEY_PRACTICES][date]
412
+ }
411
413
  })
412
414
  }
413
415
  },
@@ -437,12 +439,7 @@ export async function restoreUserPractice(id) {
437
439
  if (restoredPractice) {
438
440
  await userActivityContext.updateLocal(async function (localContext) {
439
441
  const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
440
- const utcDate = new Date(restoredPractice.day)
441
- const localDate = convertToTimeZone(utcDate, userTimeZone)
442
- const date =
443
- localDate.getFullYear() + '-' +
444
- String(localDate.getMonth() + 1).padStart(2, '0') + '-' +
445
- String(localDate.getDate()).padStart(2, '0')
442
+ const date = convertToTimeZone(restoredPractice.day, userTimeZone)
446
443
  if (localContext.data[DATA_KEY_PRACTICES][date]) {
447
444
  localContext.data[DATA_KEY_PRACTICES][date] = []
448
445
  }
@@ -666,7 +663,7 @@ function getStreaksAndMessage(practices) {
666
663
  }
667
664
  }
668
665
 
669
- async function getUserPracticeIds(day = new Date().toISOString().split('T')[0], userId = null) {
666
+ async function getUserPracticeIds(day = dayjs().format('YYYY-MM-DD'), userId = null) {
670
667
  let practices = {}
671
668
  if (userId !== globalConfig.sessionConfig.userId) {
672
669
  let data = await fetchUserPractices(0, { userId: userId })
@@ -696,6 +693,7 @@ function calculateStreaks(practices, includeStreakMessage = false) {
696
693
  let lastActiveDay = null
697
694
  let streakMessage = ''
698
695
 
696
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
699
697
  let sortedPracticeDays = Object.keys(practices)
700
698
  .map((dateStr) => {
701
699
  const [year, month, day] = dateStr.split('-').map(Number)
@@ -747,9 +745,8 @@ function calculateStreaks(practices, includeStreakMessage = false) {
747
745
  let yesterday = new Date(today)
748
746
  yesterday.setDate(today.getDate() - 1)
749
747
 
750
- let currentWeekStart = getMonday(today)
751
- let lastWeekStart = new Date(currentWeekStart)
752
- lastWeekStart.setDate(currentWeekStart.getDate() - 7)
748
+ let currentWeekStart = getMonday(today, timeZone)
749
+ let lastWeekStart = currentWeekStart.subtract(7, 'days')
753
750
 
754
751
  let hasYesterdayPractice = sortedPracticeDays.some((date) => isSameDate(date, yesterday))
755
752
  let hasCurrentWeekPractice = sortedPracticeDays.some((date) => date >= currentWeekStart)
@@ -882,7 +879,6 @@ async function formatPracticeMeta(practices) {
882
879
  const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
883
880
 
884
881
  return practices.map((practice) => {
885
- const utcDate = new Date(practice.created_at)
886
882
  const content = contents.find((c) => c.id === practice.content_id) || {}
887
883
 
888
884
  return {
@@ -899,7 +895,9 @@ async function formatPracticeMeta(practices) {
899
895
  content_type: getFormattedType(content.type || '', content.brand),
900
896
  content_id: practice.content_id || null,
901
897
  content_brand: content.brand || null,
902
- created_at: convertToTimeZone(utcDate, userTimeZone),
898
+ created_at: convertToTimeZone(dayjs(practice.created_at), userTimeZone),
899
+ sanity_type: content.type || null,
900
+ content_slug: content.slug || null,
903
901
  }
904
902
  })
905
903
  }
@@ -1016,11 +1014,15 @@ export async function getProgressRows({ brand = null, limit = 8 } = {}) {
1016
1014
  childToParentMap[content.id] = content.parent_content_data[content.parent_content_data.length - 1];
1017
1015
  }
1018
1016
  });
1017
+
1018
+ const allRecentTypeSet = new Set(
1019
+ Object.values(recentTypes).flat()
1020
+ )
1019
1021
  const progressMap = new Map();
1020
1022
  for (const [idStr, progress] of Object.entries(progressContents)) {
1021
1023
  const id = parseInt(idStr);
1022
1024
  const content = contentsMap[id];
1023
- if (!content || excludedTypes.has(content.type)) continue;
1025
+ if (!content || excludedTypes.has(content.type) || !allRecentTypeSet.has(content.type) ) continue;
1024
1026
  const parentId = childToParentMap[id];
1025
1027
  // Handle children with parents
1026
1028
  if (parentId) {
@@ -1118,10 +1120,11 @@ async function processContentItem(item) {
1118
1120
  let data = item.raw;
1119
1121
  const contentType = getFormattedType(data.type, data.brand);
1120
1122
  const status = item.state;
1123
+ const isLive = data.isLive ?? false
1121
1124
  let ctaText = 'Continue';
1122
1125
  if (contentType === 'transcription' || contentType === 'play-along' || contentType === 'jam-track') ctaText = 'Replay Song';
1123
1126
  if (contentType === 'lesson') ctaText = status === 'completed' ? 'Revisit Lesson' : 'Continue';
1124
- if ((contentType === 'song tutorial' || collectionLessonTypes.includes(contentType)) &amp;&amp; status === 'completed') ctaText = 'Revisit Lessons' ;
1127
+ if ((contentType === 'song-tutorial' || collectionLessonTypes.includes(contentType)) &amp;&amp; status === 'completed') ctaText = 'Revisit Lessons' ;
1125
1128
  if (contentType === 'pack' &amp;&amp; status === 'completed') {
1126
1129
  ctaText = 'View Lessons';
1127
1130
  }
@@ -1204,13 +1207,14 @@ async function processContentItem(item) {
1204
1207
  header: contentType,
1205
1208
  pinned: item.pinned ?? false,
1206
1209
  body: {
1207
- progressPercent: item.percent,
1210
+ progressPercent: isLive ? undefined: item.percent,
1208
1211
  thumbnail: data.thumbnail,
1209
1212
  title: data.title,
1213
+ isLive: isLive,
1210
1214
  badge: data.badge ?? null,
1211
1215
  isLocked: data.is_locked ?? false,
1212
1216
  subtitle: !data.child_count || data.lesson_count === 1
1213
- ? (contentType === 'lesson') ? `${item.percent}% Complete`: `${data.difficulty_string} • ${data.artist_name}`
1217
+ ? (contentType === 'lesson' &amp;&amp; isLive === false) ? `${item.percent}% Complete`: `${data.difficulty_string} • ${data.artist_name}`
1214
1218
  : `${data.completed_children} of ${data.lesson_count ?? data.child_count} Lessons Complete`
1215
1219
  },
1216
1220
  cta: {
@@ -1391,8 +1395,8 @@ export function findIncompleteLesson(progressOnItems, currentContentId, contentT
1391
1395
  export async function pinProgressRow(brand, id, progressType) {
1392
1396
  const url = `/api/user-management-system/v1/progress/pin?brand=${brand}&amp;id=${id}&amp;progressType=${progressType}`;
1393
1397
  const response = await fetchHandler(url, 'PUT', null)
1394
- if (response &amp;&amp; !response.error) {
1395
- await updatePinnedProgressRow(brand, {
1398
+ if (response &amp;&amp; !response.error &amp;&amp; response['action'] === 'update_user_pin') {
1399
+ await updateUserPinnedProgressRow(brand, {
1396
1400
  id,
1397
1401
  progressType,
1398
1402
  pinnedAt: new Date().toISOString(),
@@ -1404,23 +1408,25 @@ export async function pinProgressRow(brand, id, progressType) {
1404
1408
  * Unpins the current pinned progress row for a user, scoped by brand.
1405
1409
  *
1406
1410
  * @param {string} brand - The brand context for the unpin action.
1411
+ * @param {string} id - The content or playlist id to unpin.
1407
1412
  * @returns {Promise&lt;Object>} - A promise resolving to the response from the unpin API.
1408
1413
  *
1409
1414
  * @example
1410
- * unpinProgressRow('drumeo')
1415
+ * unpinProgressRow('drumeo', 123456)
1411
1416
  * .then(response => console.log(response))
1412
1417
  * .catch(error => console.error(error));
1413
1418
  */
1414
- export async function unpinProgressRow(brand) {
1415
- const url = `/api/user-management-system/v1/progress/unpin?brand=${brand}`
1419
+ export async function unpinProgressRow(brand, id) {
1420
+ if (!(brand &amp;&amp; id)) throw new Error(`undefined parameter brand: ${brand} or id: ${id}`)
1421
+ const url = `/api/user-management-system/v1/progress/unpin?brand=${brand}&amp;id=${id}`
1416
1422
  const response = await fetchHandler(url, 'PUT', null)
1417
- if (response &amp;&amp; !response.error) {
1418
- await updatePinnedProgressRow(brand, null)
1423
+ if (response &amp;&amp; !response.error &amp;&amp; response['action'] === 'clear_user_pin') {
1424
+ await updateUserPinnedProgressRow(brand, null)
1419
1425
  }
1420
1426
  return response
1421
1427
  }
1422
1428
 
1423
- async function updatePinnedProgressRow(brand, pinnedData) {
1429
+ async function updateUserPinnedProgressRow(brand, pinnedData) {
1424
1430
  const userRaw = await globalConfig.localStorage.getItem('user');
1425
1431
  const user = userRaw ? JSON.parse(userRaw) : {};
1426
1432
  user.brand_pinned_progress = user.brand_pinned_progress || {}
@@ -1513,6 +1519,23 @@ function getFirstLeafLessonId(data) {
1513
1519
  return data.lessons ? findFirstLeaf(data.lessons) : null
1514
1520
  }
1515
1521
 
1522
+ export async function fetchRecentActivitiesActiveTabs() {
1523
+ const url = `/api/user-management-system/v1/activities/tabs`
1524
+ try {
1525
+ const tabs = await fetchHandler(url, 'GET');
1526
+ const activitiesTabs = [];
1527
+
1528
+ tabs.forEach(tab => {
1529
+ activitiesTabs.push({ name: tab.label, short_name:tab.label });
1530
+ });
1531
+
1532
+ return activitiesTabs;
1533
+ } catch (error) {
1534
+ console.error('Error fetching activity tabs:', error);
1535
+ return [];
1536
+ }
1537
+ }
1538
+
1516
1539
 
1517
1540
  </code></pre>
1518
1541
  </article>
@@ -1528,7 +1551,7 @@ function getFirstLeafLessonId(data) {
1528
1551
  <br class="clear">
1529
1552
 
1530
1553
  <footer>
1531
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Wed Jul 16 2025 14:58:03 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1554
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Thu Jul 24 2025 18:41:52 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1532
1555
  </footer>
1533
1556
 
1534
1557
  <script>prettyPrint();</script>