musora-content-services 2.28.2 → 2.28.4

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 (63) hide show
  1. package/CHANGELOG.md +9 -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 +23 -16
  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 +9 -9
  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 +591 -2988
  23. package/docs/module-Sanity-Services.html +228 -680
  24. package/docs/module-Sessions.html +2 -2
  25. package/docs/module-UserActivity.html +50 -24
  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 -210
  31. package/docs/sanity.js.html +110 -256
  32. package/docs/userActivity.js.html +112 -88
  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/contentMetaData.js +0 -24
  44. package/src/contentTypeConfig.js +2 -41
  45. package/src/index.d.ts +0 -30
  46. package/src/index.js +1 -31
  47. package/src/services/content.js +2 -2
  48. package/src/services/railcontent.js +5 -199
  49. package/src/services/sanity.js +3 -168
  50. package/src/services/userActivity.js +0 -1
  51. package/test/live/railcontentLive.test.js +0 -7
  52. package/test/sanityQueryService.test.js +3 -55
  53. package/.claude/settings.local.json +0 -8
  54. package/docs/Content-Organization.html +0 -245
  55. package/docs/UserManagement.html +0 -269
  56. package/docs/global.html#User +0 -293
  57. package/docs/module-Notifications.html +0 -1183
  58. package/docs/module-Session-Management.html +0 -575
  59. package/docs/module-User-Activity.html +0 -4410
  60. package/docs/module-User-Management.html +0 -490
  61. package/docs/module-User-Permissions.html +0 -406
  62. package/docs/types.js.html +0 -122
  63. package/docs/user_user-management.js.html +0 -78
@@ -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#.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#.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#.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#.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#.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></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
 
@@ -56,16 +56,15 @@ import {
56
56
  fetchUserPracticeNotes,
57
57
  fetchHandler,
58
58
  fetchRecentUserActivities,
59
- fetchChallengeLessonData,
60
59
  fetchLastInteractedChild,
61
60
  } from './railcontent'
62
61
  import { DataContext, UserActivityVersionKey } from './dataContext.js'
63
62
  import { fetchByRailContentIds, fetchShows } from './sanity'
64
63
  import {fetchPlaylist, fetchUserPlaylists} from "./content-org/playlists"
65
64
  import {pinnedGuidedCourses} from "./content-org/guided-courses"
66
- import {convertToTimeZone, getMonday, getWeekNumber, isSameDate, isNextDay, getTimeRemainingUntilLocal} from './dateUtils.js'
65
+ import {convertToTimeZone, getMonday, getWeekNumber, isSameDate, isNextDay, getTimeRemainingUntilLocal, toDayjs} from './dateUtils.js'
67
66
  import { globalConfig } from './config'
68
- import {collectionLessonTypes, lessonTypesMapping, progressTypesMapping, showsLessonTypes, songs} from "../contentTypeConfig";
67
+ import {collectionLessonTypes, lessonTypesMapping, progressTypesMapping, recentTypes, showsLessonTypes, songs} from "../contentTypeConfig";
69
68
  import {
70
69
  getAllStartedOrCompleted,
71
70
  getProgressPercentageByIds,
@@ -74,6 +73,9 @@ import {
74
73
  } from "./contentProgress";
75
74
  import {TabResponseType} from "../contentMetaData";
76
75
  import {isContentLikedByIds} from "./contentLikes.js";
76
+ import dayjs from 'dayjs'
77
+ import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
78
+ import weekOfYear from 'dayjs/plugin/weekOfYear'
77
79
 
78
80
  const DATA_KEY_PRACTICES = 'practices'
79
81
  const DATA_KEY_LAST_UPDATED_TIME = 'u'
@@ -133,24 +135,21 @@ export let userActivityContext = new DataContext(UserActivityVersionKey, fetchUs
133
135
  * .catch(error => console.error(error));
134
136
  */
135
137
  export async function getUserWeeklyStats() {
138
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
136
139
  let data = await userActivityContext.getData()
137
140
  let practices = data?.[DATA_KEY_PRACTICES] ?? {}
138
141
  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
142
+ .map((date) => toDayjs(date)) // Convert to dayjs instance
143
+ .sort((a, b) => b.valueOf() - a.valueOf())
144
+ let today = dayjs()
145
+ let startOfWeek = getMonday(today, timeZone) // Get last Monday
145
146
  let dailyStats = []
146
-
147
147
  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))
148
+ const day = startOfWeek.add(i, 'day')
149
+ let hasPractice = sortedPracticeDays.some((practiceDate) => isSameDate(practiceDate, day.format('YYYY-MM-DD')))
151
150
  let isActive = isSameDate(today, day)
152
151
  let type = hasPractice ? 'tracked' : isActive ? 'active' : 'none'
153
- dailyStats.push({ key: i, label: DAYS[i], isActive, inStreak: hasPractice, type })
152
+ dailyStats.push({ key: i, label: DAYS[i], isActive, inStreak: hasPractice, type, day: day.format('YYYY-MM-DD') })
154
153
  }
155
154
 
156
155
  let { streakMessage } = getStreaksAndMessage(practices)
@@ -189,83 +188,77 @@ export async function getUserWeeklyStats() {
189
188
  * getUserMonthlyStats({ userId: 123 }).then(console.log);
190
189
  */
191
190
  export async function getUserMonthlyStats(params = {}) {
192
- const now = new Date()
191
+ const now = dayjs()
193
192
  const {
194
- year = now.getFullYear(),
195
- month = now.getMonth(),
196
- day = 1,
193
+ year = now.year(),
194
+ month = now.month(), // 0-indexed
197
195
  userId = globalConfig.sessionConfig.userId,
198
196
  } = 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)
197
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
198
+ const practices = await getUserPractices(userId)
205
199
 
206
- let startOfGrid = getMonday(firstDayOfMonth)
200
+ const firstDayOfMonth = dayjs.tz(`${year}-${month + 1}-01`, timeZone).startOf('day')
201
+ const endOfMonth = firstDayOfMonth.endOf('month')
202
+ const today = dayjs().tz(timeZone).startOf('day')
207
203
 
208
- let previousWeekStart = new Date(startOfGrid)
209
- previousWeekStart.setDate(previousWeekStart.getDate() - 7)
204
+ let startOfGrid = getMonday(firstDayOfMonth, timeZone)
210
205
 
211
- let previousWeekEnd = new Date(startOfGrid)
212
- previousWeekEnd.setDate(previousWeekEnd.getDate() - 1)
206
+ // Previous week range
207
+ const previousWeekStart = startOfGrid.subtract(7, 'day')
208
+ const previousWeekEnd = startOfGrid.subtract(1, 'day')
213
209
 
214
210
  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]) {
211
+ for (let d = previousWeekStart.clone(); d.isSameOrBefore(previousWeekEnd); d = d.add(1, 'day')) {
212
+ const key = d.format('YYYY-MM-DD')
213
+ if (practices[key]) {
218
214
  hadStreakBeforeMonth = true
219
215
  break
220
216
  }
221
217
  }
222
218
 
223
- let endOfMonth = new Date(year, month + 1, 0)
224
- while (endOfMonth.getDay() !== 0) {
225
- endOfMonth.setDate(endOfMonth.getDate() + 1)
219
+ // let endOfMonth = new Date(year, month + 1, 0)
220
+ let endOfGrid = endOfMonth.clone()
221
+ while (endOfGrid.day() !== 0) {
222
+ endOfGrid = endOfGrid.add(1, 'day')
226
223
  }
227
-
228
- let daysInMonth = Math.ceil((endOfMonth - startOfGrid) / (1000 * 60 * 60 * 24)) + 1
229
-
224
+ const daysInMonth = endOfGrid.diff(startOfGrid, 'day') + 1
230
225
  let dailyStats = []
231
226
  let practiceDuration = 0
232
227
  let daysPracticed = 0
233
228
  let weeklyStats = {}
234
229
 
235
230
  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
231
+ let day = startOfGrid.add(i, 'day')
232
+ let key = day.format('YYYY-MM-DD')
233
+ let activity = practices[key] ?? null
242
234
  let weekKey = getWeekNumber(day)
243
235
 
244
236
  if (!weeklyStats[weekKey]) {
245
237
  weeklyStats[weekKey] = { key: weekKey, inStreak: false }
246
238
  }
247
239
 
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)
240
+ if (activity &amp;&amp; day.isBetween(firstDayOfMonth, endOfMonth, null, '[]')) {
241
+ practiceDuration += activity.reduce((sum, entry) => sum + entry.duration_seconds, 0)
250
242
  daysPracticed++
251
243
  }
252
244
 
253
- let isActive = isSameDate(today, day)
254
- let type = dayActivity !== null ? 'tracked' : isActive ? 'active' : 'none'
255
- let isInStreak = dayActivity !== null
256
- if (isInStreak) {
245
+ if (activity) {
257
246
  weeklyStats[weekKey].inStreak = true
258
247
  }
259
248
 
249
+ const isActive = day.isSame(today, 'day')
250
+ const type = activity ? 'tracked' : isActive ? 'active' : 'none'
251
+
260
252
  dailyStats.push({
261
253
  key: i,
262
- label: dayKey,
254
+ label: key,
263
255
  isActive,
264
- inStreak: dayActivity !== null,
256
+ inStreak: !!activity,
265
257
  type,
266
258
  })
267
259
  }
268
260
 
261
+ // Continue streak into month
269
262
  if (hadStreakBeforeMonth) {
270
263
  const firstWeekKey = getWeekNumber(startOfGrid)
271
264
  if (weeklyStats[firstWeekKey]) {
@@ -273,14 +266,15 @@ export async function getUserMonthlyStats(params = {}) {
273
266
  }
274
267
  }
275
268
 
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
269
+ // Filter past practices only
270
+ let filteredPractices = Object.entries(practices)
271
+ .filter(([date]) => dayjs.tz(date, timeZone).isSameOrBefore(endOfMonth))
272
+ .reduce((acc, [date, val]) => {
273
+ acc[date] = val
274
+ return acc
281
275
  }, {})
282
276
 
283
- let { currentDailyStreak, currentWeeklyStreak } = calculateStreaks(filteredPractices)
277
+ const { currentDailyStreak, currentWeeklyStreak } = calculateStreaks(filteredPractices)
284
278
 
285
279
  return {
286
280
  data: {
@@ -319,7 +313,9 @@ export async function getUserMonthlyStats(params = {}) {
319
313
  * auto: false,
320
314
  * category_id: 5,
321
315
  * title: "Guitar Warm-up",
322
- * thumbnail_url: "https://example.com/thumbnail.jpg"
316
+ * thumbnail_url: "https://example.com/thumbnail.jpg",
317
+ * instrument_id: 1,
318
+ * instrument_id: 2,
323
319
  * })
324
320
  * .then(response => console.log(response))
325
321
  * .catch(error => console.error(error));
@@ -405,9 +401,14 @@ export async function removeUserPractice(id) {
405
401
  async function (localContext) {
406
402
  if (localContext.data?.[DATA_KEY_PRACTICES]) {
407
403
  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)
404
+ const filtered = localContext.data[DATA_KEY_PRACTICES][date].filter(
405
+ (practice) => practice.id !== id
406
+ )
407
+ if (filtered.length > 0) {
408
+ localContext.data[DATA_KEY_PRACTICES][date] = filtered
409
+ } else {
410
+ delete localContext.data[DATA_KEY_PRACTICES][date]
411
+ }
411
412
  })
412
413
  }
413
414
  },
@@ -437,12 +438,7 @@ export async function restoreUserPractice(id) {
437
438
  if (restoredPractice) {
438
439
  await userActivityContext.updateLocal(async function (localContext) {
439
440
  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')
441
+ const date = convertToTimeZone(restoredPractice.day, userTimeZone)
446
442
  if (localContext.data[DATA_KEY_PRACTICES][date]) {
447
443
  localContext.data[DATA_KEY_PRACTICES][date] = []
448
444
  }
@@ -666,7 +662,7 @@ function getStreaksAndMessage(practices) {
666
662
  }
667
663
  }
668
664
 
669
- async function getUserPracticeIds(day = new Date().toISOString().split('T')[0], userId = null) {
665
+ async function getUserPracticeIds(day = dayjs().format('YYYY-MM-DD'), userId = null) {
670
666
  let practices = {}
671
667
  if (userId !== globalConfig.sessionConfig.userId) {
672
668
  let data = await fetchUserPractices(0, { userId: userId })
@@ -696,6 +692,7 @@ function calculateStreaks(practices, includeStreakMessage = false) {
696
692
  let lastActiveDay = null
697
693
  let streakMessage = ''
698
694
 
695
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
699
696
  let sortedPracticeDays = Object.keys(practices)
700
697
  .map((dateStr) => {
701
698
  const [year, month, day] = dateStr.split('-').map(Number)
@@ -747,9 +744,8 @@ function calculateStreaks(practices, includeStreakMessage = false) {
747
744
  let yesterday = new Date(today)
748
745
  yesterday.setDate(today.getDate() - 1)
749
746
 
750
- let currentWeekStart = getMonday(today)
751
- let lastWeekStart = new Date(currentWeekStart)
752
- lastWeekStart.setDate(currentWeekStart.getDate() - 7)
747
+ let currentWeekStart = getMonday(today, timeZone)
748
+ let lastWeekStart = currentWeekStart.subtract(7, 'days')
753
749
 
754
750
  let hasYesterdayPractice = sortedPracticeDays.some((date) => isSameDate(date, yesterday))
755
751
  let hasCurrentWeekPractice = sortedPracticeDays.some((date) => date >= currentWeekStart)
@@ -882,7 +878,6 @@ async function formatPracticeMeta(practices) {
882
878
  const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
883
879
 
884
880
  return practices.map((practice) => {
885
- const utcDate = new Date(practice.created_at)
886
881
  const content = contents.find((c) => c.id === practice.content_id) || {}
887
882
 
888
883
  return {
@@ -899,7 +894,9 @@ async function formatPracticeMeta(practices) {
899
894
  content_type: getFormattedType(content.type || '', content.brand),
900
895
  content_id: practice.content_id || null,
901
896
  content_brand: content.brand || null,
902
- created_at: convertToTimeZone(utcDate, userTimeZone),
897
+ created_at: convertToTimeZone(dayjs(practice.created_at), userTimeZone),
898
+ sanity_type: content.type || null,
899
+ content_slug: content.slug || null,
903
900
  }
904
901
  })
905
902
  }
@@ -1016,11 +1013,15 @@ export async function getProgressRows({ brand = null, limit = 8 } = {}) {
1016
1013
  childToParentMap[content.id] = content.parent_content_data[content.parent_content_data.length - 1];
1017
1014
  }
1018
1015
  });
1016
+
1017
+ const allRecentTypeSet = new Set(
1018
+ Object.values(recentTypes).flat()
1019
+ )
1019
1020
  const progressMap = new Map();
1020
1021
  for (const [idStr, progress] of Object.entries(progressContents)) {
1021
1022
  const id = parseInt(idStr);
1022
1023
  const content = contentsMap[id];
1023
- if (!content || excludedTypes.has(content.type)) continue;
1024
+ if (!content || excludedTypes.has(content.type) || !allRecentTypeSet.has(content.type) ) continue;
1024
1025
  const parentId = childToParentMap[id];
1025
1026
  // Handle children with parents
1026
1027
  if (parentId) {
@@ -1118,10 +1119,11 @@ async function processContentItem(item) {
1118
1119
  let data = item.raw;
1119
1120
  const contentType = getFormattedType(data.type, data.brand);
1120
1121
  const status = item.state;
1122
+ const isLive = data.isLive ?? false
1121
1123
  let ctaText = 'Continue';
1122
1124
  if (contentType === 'transcription' || contentType === 'play-along' || contentType === 'jam-track') ctaText = 'Replay Song';
1123
1125
  if (contentType === 'lesson') ctaText = status === 'completed' ? 'Revisit Lesson' : 'Continue';
1124
- if ((contentType === 'song tutorial' || collectionLessonTypes.includes(contentType)) &amp;&amp; status === 'completed') ctaText = 'Revisit Lessons' ;
1126
+ if ((contentType === 'song-tutorial' || collectionLessonTypes.includes(contentType)) &amp;&amp; status === 'completed') ctaText = 'Revisit Lessons' ;
1125
1127
  if (contentType === 'pack' &amp;&amp; status === 'completed') {
1126
1128
  ctaText = 'View Lessons';
1127
1129
  }
@@ -1204,13 +1206,14 @@ async function processContentItem(item) {
1204
1206
  header: contentType,
1205
1207
  pinned: item.pinned ?? false,
1206
1208
  body: {
1207
- progressPercent: item.percent,
1209
+ progressPercent: isLive ? undefined: item.percent,
1208
1210
  thumbnail: data.thumbnail,
1209
1211
  title: data.title,
1212
+ isLive: isLive,
1210
1213
  badge: data.badge ?? null,
1211
1214
  isLocked: data.is_locked ?? false,
1212
1215
  subtitle: !data.child_count || data.lesson_count === 1
1213
- ? (contentType === 'lesson') ? `${item.percent}% Complete`: `${data.difficulty_string} • ${data.artist_name}`
1216
+ ? (contentType === 'lesson' &amp;&amp; isLive === false) ? `${item.percent}% Complete`: `${data.difficulty_string} • ${data.artist_name}`
1214
1217
  : `${data.completed_children} of ${data.lesson_count ?? data.child_count} Lessons Complete`
1215
1218
  },
1216
1219
  cta: {
@@ -1280,6 +1283,8 @@ async function processPlaylistItem(item) {
1280
1283
  brand: playlist.brand,
1281
1284
  id: playlist.id,
1282
1285
  itemId: nextItem.id,
1286
+ lastEngagedOn: playlist.last_engaged_on,
1287
+ lastEngagedOnItem: playlist.last_engaged_on_item,
1283
1288
  type: 'playlists',
1284
1289
  }
1285
1290
  }
@@ -1391,8 +1396,8 @@ export function findIncompleteLesson(progressOnItems, currentContentId, contentT
1391
1396
  export async function pinProgressRow(brand, id, progressType) {
1392
1397
  const url = `/api/user-management-system/v1/progress/pin?brand=${brand}&amp;id=${id}&amp;progressType=${progressType}`;
1393
1398
  const response = await fetchHandler(url, 'PUT', null)
1394
- if (response &amp;&amp; !response.error) {
1395
- await updatePinnedProgressRow(brand, {
1399
+ if (response &amp;&amp; !response.error &amp;&amp; response['action'] === 'update_user_pin') {
1400
+ await updateUserPinnedProgressRow(brand, {
1396
1401
  id,
1397
1402
  progressType,
1398
1403
  pinnedAt: new Date().toISOString(),
@@ -1404,23 +1409,25 @@ export async function pinProgressRow(brand, id, progressType) {
1404
1409
  * Unpins the current pinned progress row for a user, scoped by brand.
1405
1410
  *
1406
1411
  * @param {string} brand - The brand context for the unpin action.
1412
+ * @param {string} id - The content or playlist id to unpin.
1407
1413
  * @returns {Promise&lt;Object>} - A promise resolving to the response from the unpin API.
1408
1414
  *
1409
1415
  * @example
1410
- * unpinProgressRow('drumeo')
1416
+ * unpinProgressRow('drumeo', 123456)
1411
1417
  * .then(response => console.log(response))
1412
1418
  * .catch(error => console.error(error));
1413
1419
  */
1414
- export async function unpinProgressRow(brand) {
1415
- const url = `/api/user-management-system/v1/progress/unpin?brand=${brand}`
1420
+ export async function unpinProgressRow(brand, id) {
1421
+ if (!(brand &amp;&amp; id)) throw new Error(`undefined parameter brand: ${brand} or id: ${id}`)
1422
+ const url = `/api/user-management-system/v1/progress/unpin?brand=${brand}&amp;id=${id}`
1416
1423
  const response = await fetchHandler(url, 'PUT', null)
1417
- if (response &amp;&amp; !response.error) {
1418
- await updatePinnedProgressRow(brand, null)
1424
+ if (response &amp;&amp; !response.error &amp;&amp; response['action'] === 'clear_user_pin') {
1425
+ await updateUserPinnedProgressRow(brand, null)
1419
1426
  }
1420
1427
  return response
1421
1428
  }
1422
1429
 
1423
- async function updatePinnedProgressRow(brand, pinnedData) {
1430
+ async function updateUserPinnedProgressRow(brand, pinnedData) {
1424
1431
  const userRaw = await globalConfig.localStorage.getItem('user');
1425
1432
  const user = userRaw ? JSON.parse(userRaw) : {};
1426
1433
  user.brand_pinned_progress = user.brand_pinned_progress || {}
@@ -1513,6 +1520,23 @@ function getFirstLeafLessonId(data) {
1513
1520
  return data.lessons ? findFirstLeaf(data.lessons) : null
1514
1521
  }
1515
1522
 
1523
+ export async function fetchRecentActivitiesActiveTabs() {
1524
+ const url = `/api/user-management-system/v1/activities/tabs`
1525
+ try {
1526
+ const tabs = await fetchHandler(url, 'GET');
1527
+ const activitiesTabs = [];
1528
+
1529
+ tabs.forEach(tab => {
1530
+ activitiesTabs.push({ name: tab.label, short_name:tab.label });
1531
+ });
1532
+
1533
+ return activitiesTabs;
1534
+ } catch (error) {
1535
+ console.error('Error fetching activity tabs:', error);
1536
+ return [];
1537
+ }
1538
+ }
1539
+
1516
1540
 
1517
1541
  </code></pre>
1518
1542
  </article>
@@ -1528,7 +1552,7 @@ function getFirstLeafLessonId(data) {
1528
1552
  <br class="clear">
1529
1553
 
1530
1554
  <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.
1555
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Fri Jul 25 2025 21:19:12 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1532
1556
  </footer>
1533
1557
 
1534
1558
  <script>prettyPrint();</script>