musora-content-services 2.27.2 → 2.27.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 (167) hide show
  1. package/.coderabbit.yaml +0 -0
  2. package/.editorconfig +0 -0
  3. package/.github/pull_request_template.md +0 -0
  4. package/.github/workflows/conventional-commits.yaml +0 -0
  5. package/.github/workflows/docs.js.yml +0 -0
  6. package/.github/workflows/node.js.yml +0 -0
  7. package/.prettierignore +0 -0
  8. package/.prettierrc +0 -0
  9. package/.yarnrc.yml +1 -0
  10. package/CHANGELOG.md +13 -0
  11. package/README.md +0 -0
  12. package/babel.config.cjs +0 -0
  13. package/docs/Content-Organization.html +0 -0
  14. package/docs/ContentOrganization.html +0 -0
  15. package/docs/Gamification.html +0 -0
  16. package/docs/UserManagement.html +0 -0
  17. package/docs/UserManagementSystem.html +0 -0
  18. package/docs/api_types.js.html +0 -0
  19. package/docs/config.js.html +0 -0
  20. package/docs/content-org_content-org.js.html +0 -0
  21. package/docs/content-org_playlists-types.js.html +0 -0
  22. package/docs/content-org_playlists.js.html +0 -0
  23. package/docs/content.js.html +0 -0
  24. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  25. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  26. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  27. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  28. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  29. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  30. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  31. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  32. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  33. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
  34. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  35. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  36. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  37. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  38. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
  39. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  40. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  41. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  42. package/docs/gamification_awards.js.html +0 -0
  43. package/docs/gamification_gamification.js.html +0 -0
  44. package/docs/gamification_types.js.html +0 -0
  45. package/docs/global.html +0 -0
  46. package/docs/global.html#User +0 -0
  47. package/docs/index.html +0 -0
  48. package/docs/module-Awards.html +0 -0
  49. package/docs/module-Config.html +0 -0
  50. package/docs/module-Content-Services-V2.html +0 -0
  51. package/docs/module-Interests.html +0 -0
  52. package/docs/module-Notifications.html +0 -0
  53. package/docs/module-Permissions.html +0 -0
  54. package/docs/module-Playlists.html +0 -0
  55. package/docs/module-Railcontent-Services.html +0 -0
  56. package/docs/module-Sanity-Services.html +0 -0
  57. package/docs/module-Session-Management.html +0 -0
  58. package/docs/module-Sessions.html +0 -0
  59. package/docs/module-User-Activity.html +0 -0
  60. package/docs/module-User-Management.html +0 -0
  61. package/docs/module-User-Permissions.html +0 -0
  62. package/docs/module-UserActivity.html +0 -0
  63. package/docs/module-UserChat.html +0 -0
  64. package/docs/module-UserManagement.html +0 -0
  65. package/docs/module-UserNotifications.html +0 -0
  66. package/docs/module-UserProfile.html +0 -0
  67. package/docs/railcontent.js.html +0 -0
  68. package/docs/sanity.js.html +0 -0
  69. package/docs/scripts/collapse.js +0 -0
  70. package/docs/scripts/commonNav.js +0 -0
  71. package/docs/scripts/linenumber.js +0 -0
  72. package/docs/scripts/nav.js +0 -0
  73. package/docs/scripts/polyfill.js +0 -0
  74. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
  75. package/docs/scripts/prettify/lang-css.js +0 -0
  76. package/docs/scripts/prettify/prettify.js +0 -0
  77. package/docs/scripts/search.js +0 -0
  78. package/docs/styles/jsdoc.css +0 -0
  79. package/docs/styles/prettify.css +0 -0
  80. package/docs/types.js.html +0 -0
  81. package/docs/userActivity.js.html +0 -0
  82. package/docs/user_chat.js.html +0 -0
  83. package/docs/user_interests.js.html +0 -0
  84. package/docs/user_management.js.html +0 -0
  85. package/docs/user_notifications.js.html +0 -0
  86. package/docs/user_permissions.js.html +0 -0
  87. package/docs/user_profile.js.html +0 -0
  88. package/docs/user_sessions.js.html +0 -0
  89. package/docs/user_types.js.html +0 -0
  90. package/docs/user_user-management-system.js.html +0 -0
  91. package/docs/user_user-management.js.html +0 -0
  92. package/jest.config.js +0 -0
  93. package/jsdoc.json +0 -0
  94. package/package.json +2 -1
  95. package/src/contentMetaData.js +1 -0
  96. package/src/contentTypeConfig.js +6 -5
  97. package/src/filterBuilder.js +0 -0
  98. package/src/index.d.ts +5 -1
  99. package/src/index.js +5 -1
  100. package/src/infrastructure/http/HttpClient.ts +0 -0
  101. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  102. package/src/infrastructure/http/index.ts +0 -0
  103. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  104. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  105. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  106. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  107. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  108. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  109. package/src/lib/httpHelper.js +0 -0
  110. package/src/lib/lastUpdated.js +0 -0
  111. package/src/services/api/types.js +0 -0
  112. package/src/services/config.js +0 -0
  113. package/src/services/content-org/content-org.js +0 -0
  114. package/src/services/content-org/guided-courses.ts +0 -0
  115. package/src/services/content-org/playlists-types.js +0 -0
  116. package/src/services/content-org/playlists.js +0 -0
  117. package/src/services/content.js +0 -0
  118. package/src/services/contentAggregator.js +0 -0
  119. package/src/services/contentLikes.js +0 -0
  120. package/src/services/contentProgress.js +6 -2
  121. package/src/services/dataContext.js +0 -0
  122. package/src/services/dateUtils.js +31 -42
  123. package/src/services/forum.js +0 -0
  124. package/src/services/gamification/awards.js +0 -0
  125. package/src/services/gamification/gamification.js +0 -0
  126. package/src/services/gamification/types.js +0 -0
  127. package/src/services/imageSRCBuilder.js +0 -0
  128. package/src/services/railcontent.js +1 -9
  129. package/src/services/recommendations.js +0 -0
  130. package/src/services/sanity.js +7 -1
  131. package/src/services/types.js +0 -0
  132. package/src/services/user/account.ts +0 -0
  133. package/src/services/user/chat.js +0 -0
  134. package/src/services/user/interests.js +0 -0
  135. package/src/services/user/management.js +0 -0
  136. package/src/services/user/notifications.js +0 -0
  137. package/src/services/user/permissions.js +0 -0
  138. package/src/services/user/profile.js +0 -0
  139. package/src/services/user/sessions.js +0 -0
  140. package/src/services/user/types.js +0 -0
  141. package/src/services/user/user-management-system.js +0 -0
  142. package/src/services/userActivity.js +75 -68
  143. package/test/HttpClient.test.js +0 -0
  144. package/test/content.test.js +0 -0
  145. package/test/contentLikes.test.js +0 -0
  146. package/test/contentProgress.test.js +0 -0
  147. package/test/dataContext.test.js +0 -0
  148. package/test/forum.test.js +0 -0
  149. package/test/imageSRCBuilder.test.js +0 -0
  150. package/test/imageSRCVerify.test.js +0 -0
  151. package/test/initializeTests.js +0 -0
  152. package/test/lib/lastUpdated.test.js +0 -0
  153. package/test/live/contentProgressLive.test.js +0 -0
  154. package/test/live/railcontentLive.test.js +0 -0
  155. package/test/localStorageMock.js +0 -0
  156. package/test/log.js +0 -0
  157. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  158. package/test/mockData/mockData_progress_content.json +0 -0
  159. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  160. package/test/mockData/mockData_user_practices.json +0 -0
  161. package/test/notifications.test.js +0 -0
  162. package/test/progressRows.test.js +0 -0
  163. package/test/sanityQueryService.test.js +0 -0
  164. package/test/streakMessage.test.js +0 -0
  165. package/test/user/permissions.test.js +0 -0
  166. package/test/userActivity.test.js +0 -0
  167. package/tools/generate-index.cjs +0 -0
package/.coderabbit.yaml CHANGED
File without changes
package/.editorconfig CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
package/.prettierignore CHANGED
File without changes
package/.prettierrc CHANGED
File without changes
package/.yarnrc.yml ADDED
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [2.27.3](https://github.com/railroadmedia/musora-content-services/compare/v2.27.0...v2.27.3) (2025-07-23)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **last-engaged:** add playlist last engaged endpoint ([#361](https://github.com/railroadmedia/musora-content-services/issues/361)) ([3396207](https://github.com/railroadmedia/musora-content-services/commit/33962077500e47ff9cba93fb23fd28b63eb4112a))
11
+ * MU2-710 - Update MCS to use new endpoint to get recent activities tabs with data ([5cfcc27](https://github.com/railroadmedia/musora-content-services/commit/5cfcc27745072907e745a1015350249f6dbccb85))
12
+ * Song Tutorials are showing up in Recent Songs as collections ([68d4559](https://github.com/railroadmedia/musora-content-services/commit/68d4559f8ee528441a8a4bff73796fbd48c8321b))
13
+ * T3PS-266 - Practice tracker meta ([fa3c962](https://github.com/railroadmedia/musora-content-services/commit/fa3c962580978ce6aef4fdf5ad8023852bf92a6d))
14
+ * T3PS-415: progress rows for courses/song tutorials/packs ([4ad26cc](https://github.com/railroadmedia/musora-content-services/commit/4ad26ccbfbf2eade11882ae246d102d72093c1c5))
15
+ * Timezone issue - Migrate native Date to Dayjs ([c37def1](https://github.com/railroadmedia/musora-content-services/commit/c37def12b471fe570e15c7be220ab8d52e1dad88))
16
+ * **Userpractice:** add category_id and instrument_id to userPractice ([2c92c6f](https://github.com/railroadmedia/musora-content-services/commit/2c92c6f6adcb7fac657c3b12e1c3f5e927cff214))
17
+
5
18
  ### [2.27.2](https://github.com/railroadmedia/musora-content-services/compare/v2.27.1...v2.27.2) (2025-07-21)
6
19
 
7
20
 
package/README.md CHANGED
File without changes
package/babel.config.cjs CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/docs/global.html CHANGED
File without changes
File without changes
package/docs/index.html CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/jest.config.js CHANGED
File without changes
package/jsdoc.json CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.27.2",
3
+ "version": "2.27.3",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -32,6 +32,7 @@
32
32
  "@babel/preset-env": "^7.25.3",
33
33
  "@sanity/client": "^5.4.2",
34
34
  "babel-jest": "^29.7.0",
35
+ "dayjs": "^1.11.13",
35
36
  "docdash": "^2.0.2",
36
37
  "groqd": "^0.15.12"
37
38
  }
@@ -249,6 +249,7 @@ const commonMetadata = {
249
249
  },
250
250
  'recent-activities': {
251
251
  name: 'Recent Activity',
252
+ onlyAvailableTabs: true,
252
253
  tabs: [
253
254
  Tabs.RecentAll,
254
255
  Tabs.RecentActivityLessons,
@@ -182,15 +182,16 @@ export const lessonTypesMapping = {
182
182
  export const getNextLessonLessonParentTypes = ['course', 'guided-course', 'pack', 'pack-bundle', 'song-tutorial'];
183
183
 
184
184
  export const progressTypesMapping = {
185
- 'lesson': [...singleLessonTypes,...practiceAlongsLessonTypes, ...liveArchivesLessonTypes, ...performancesLessonTypes, ...studentArchivesLessonTypes, ...documentariesLessonTypes, 'live'],
185
+ 'lesson': [...singleLessonTypes,...practiceAlongsLessonTypes, ...liveArchivesLessonTypes, ...performancesLessonTypes, ...studentArchivesLessonTypes, ...documentariesLessonTypes, 'live', 'pack-bundle-lesson', 'course-part'],
186
186
  'course': ['course'],
187
187
  'show': showsLessonTypes,
188
- 'song tutorial': tutorialsLessonTypes,
188
+ 'song tutorial': [...tutorialsLessonTypes, 'song-tutorial-children'],
189
189
  'songs': transcriptionsLessonTypes,
190
190
  'play-along': playAlongLessonTypes,
191
191
  'guided course': ['guided-course'],
192
192
  'pack': ['pack', 'semester-pack'],
193
- 'method': ['learning-path']
193
+ 'method': ['learning-path'],
194
+ 'jam track': ['jam-track'],
194
195
  };
195
196
 
196
197
  export const songs = {
@@ -207,9 +208,9 @@ export const filterTypes = {
207
208
 
208
209
  export const recentTypes = {
209
210
  lessons: [...individualLessonsTypes, 'course-part', 'pack-bundle-lesson', 'challenge-part', 'guided-course-part', 'quick-tips'],
210
- songs: [...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes],
211
+ songs: [...transcriptionsLessonTypes, ...playAlongLessonTypes, 'song-tutorial-children'],
211
212
  home: [...individualLessonsTypes, ...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes,
212
- 'guided-course', 'learning-path', 'live']
213
+ 'guided-course', 'learning-path', 'live', 'course', 'pack']
213
214
  }
214
215
 
215
216
  export let contentTypeConfig = {
File without changes
package/src/index.d.ts CHANGED
@@ -83,7 +83,8 @@ import {
83
83
  getTimeRemainingUntilLocal,
84
84
  getWeekNumber,
85
85
  isNextDay,
86
- isSameDate
86
+ isSameDate,
87
+ toDayjs
87
88
  } from './services/dateUtils.js';
88
89
 
89
90
  import {
@@ -291,6 +292,7 @@ import {
291
292
  createPracticeNotes,
292
293
  deletePracticeSession,
293
294
  deleteUserActivity,
295
+ fetchRecentActivitiesActiveTabs,
294
296
  findIncompleteLesson,
295
297
  getPracticeNotes,
296
298
  getPracticeSessions,
@@ -400,6 +402,7 @@ declare module 'musora-content-services' {
400
402
  fetchPlaylist,
401
403
  fetchPlaylistItems,
402
404
  fetchRecent,
405
+ fetchRecentActivitiesActiveTabs,
403
406
  fetchRecentUserActivities,
404
407
  fetchRelatedLessons,
405
408
  fetchRelatedRecommendedContent,
@@ -529,6 +532,7 @@ declare module 'musora-content-services' {
529
532
  setupAccount,
530
533
  startLiveEventPolling,
531
534
  status,
535
+ toDayjs,
532
536
  togglePlaylistPrivate,
533
537
  unEnrollUserInGuidedCourse,
534
538
  unPinGuidedCourse,
package/src/index.js CHANGED
@@ -83,7 +83,8 @@ import {
83
83
  getTimeRemainingUntilLocal,
84
84
  getWeekNumber,
85
85
  isNextDay,
86
- isSameDate
86
+ isSameDate,
87
+ toDayjs
87
88
  } from './services/dateUtils.js';
88
89
 
89
90
  import {
@@ -291,6 +292,7 @@ import {
291
292
  createPracticeNotes,
292
293
  deletePracticeSession,
293
294
  deleteUserActivity,
295
+ fetchRecentActivitiesActiveTabs,
294
296
  findIncompleteLesson,
295
297
  getPracticeNotes,
296
298
  getPracticeSessions,
@@ -399,6 +401,7 @@ export {
399
401
  fetchPlaylist,
400
402
  fetchPlaylistItems,
401
403
  fetchRecent,
404
+ fetchRecentActivitiesActiveTabs,
402
405
  fetchRecentUserActivities,
403
406
  fetchRelatedLessons,
404
407
  fetchRelatedRecommendedContent,
@@ -528,6 +531,7 @@ export {
528
531
  setupAccount,
529
532
  startLiveEventPolling,
530
533
  status,
534
+ toDayjs,
531
535
  togglePlaylistPrivate,
532
536
  unEnrollUserInGuidedCourse,
533
537
  unPinGuidedCourse,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -15,6 +15,7 @@ const DATA_KEY_STATUS = 's'
15
15
  const DATA_KEY_PROGRESS = 'p'
16
16
  const DATA_KEY_RESUME_TIME = 't'
17
17
  const DATA_KEY_LAST_UPDATED_TIME = 'u'
18
+ const DATA_KEY_BRAND = 'b'
18
19
 
19
20
  export let dataContext = new DataContext(ContentProgressVersionKey, fetchContentProgress)
20
21
 
@@ -191,7 +192,7 @@ export async function getAllStartedOrCompleted({ limit = null, onlyIds = true, b
191
192
  const isRecent = item[DATA_KEY_LAST_UPDATED_TIME] >= oneMonthAgoInSeconds
192
193
  const isCorrectBrand = !brand || !item.b || item.b === brand
193
194
  const isNotExcluded = !excludedSet.has(id)
194
- return isRelevantStatus && isRecent && isCorrectBrand && isNotExcluded
195
+ return isRelevantStatus && isCorrectBrand && isNotExcluded
195
196
  })
196
197
  .sort(([, a], [, b]) => {
197
198
  const v1 = a[DATA_KEY_LAST_UPDATED_TIME]
@@ -371,7 +372,7 @@ export async function recordWatchSession(
371
372
  //TODO: Good enough for Alpha, Refine in reliability improvements
372
373
  sessionData[sessionId] = sessionData[sessionId] || {}
373
374
  const secondsSinceLastUpdate = Math.ceil(secondsPlayed - (sessionData[sessionId][contentId] ?? 0))
374
- await recordUserPractice({ content_id: contentId, duration_seconds: secondsSinceLastUpdate, category_id: categoryId, instrument_id: instrumentId })
375
+ await recordUserPractice({ content_id: contentId, duration_seconds: secondsSinceLastUpdate, instrument_id: instrumentId })
375
376
  } catch (error) {
376
377
  console.error('Failed to record user practice:', error)
377
378
  }
@@ -438,8 +439,11 @@ function bubbleProgress(hierarchy, contentId, localContext) {
438
439
  return localContext.data[childId]?.[DATA_KEY_PROGRESS] ?? 0
439
440
  })
440
441
  let progress = Math.round(childProgress.reduce((a, b) => a + b, 0) / childProgress.length)
442
+ const brand =localContext.data[contentId]?.[DATA_KEY_BRAND] ?? null
441
443
  data[DATA_KEY_PROGRESS] = progress
442
444
  data[DATA_KEY_STATUS] = progress === 100 ? STATE_COMPLETED : STATE_STARTED
445
+ data[DATA_KEY_LAST_UPDATED_TIME] = Math.round(new Date().getTime() / 1000)
446
+ data[DATA_KEY_BRAND] = brand
443
447
  localContext.data[parentId] = data
444
448
  bubbleProgress(hierarchy, parentId, localContext)
445
449
  }
File without changes
@@ -1,58 +1,47 @@
1
1
  // dateUtils.js
2
+ import dayjs from "dayjs";
3
+ import utc from "dayjs/plugin/utc";
4
+ import timezone from "dayjs/plugin/timezone";
5
+ import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'
6
+ import isoWeek from 'dayjs/plugin/isoWeek';
7
+ import isBetween from 'dayjs/plugin/isBetween'
8
+ import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
2
9
 
3
- export function convertToTimeZone(date, timeZone) {
4
- const formatter = new Intl.DateTimeFormat('en-US', {
5
- timeZone,
6
- year: 'numeric',
7
- month: '2-digit',
8
- day: '2-digit',
9
- hour: '2-digit',
10
- minute: '2-digit',
11
- second: '2-digit',
12
- hour12: false,
13
- });
10
+ dayjs.extend(utc);
11
+ dayjs.extend(timezone);
12
+ dayjs.extend(isSameOrAfter)
13
+ dayjs.extend(isoWeek)
14
+ dayjs.extend(isBetween)
15
+ dayjs.extend(isSameOrBefore)
14
16
 
15
- const parts = formatter.formatToParts(date).reduce((acc, part) => {
16
- if (part.type !== 'literal') acc[part.type] = part.value;
17
- return acc;
18
- }, {});
17
+ export function toDayjs(date, timeZone = 'UTC') {
18
+ return dayjs.tz(date, timeZone).startOf('day')
19
+ }
19
20
 
20
- return new Date(`${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:${parts.second}`);
21
+ export function convertToTimeZone(date, timeZone) {
22
+ return dayjs(date).tz(timeZone).format('YYYY-MM-DD');
21
23
  }
22
- // Get start of the week (Monday)
23
- export function getMonday(date) {
24
- const d = new Date(date);
25
- const day = d.getDay();
26
- const diff = d.getDate() - day + (day === 0 ? -6 : 1);
27
- return new Date(d.setDate(diff));
24
+
25
+ export function getMonday(date, timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone) {
26
+ // Use isoWeekday(1) - Monday is 1
27
+ return toDayjs(date, timeZone).isoWeekday(1)
28
28
  }
29
29
 
30
- // Get the week number
31
- export function getWeekNumber(d) {
32
- let newDate = new Date(d.getTime());
33
- newDate.setUTCDate(newDate.getUTCDate() + 4 - (newDate.getUTCDay()||7));
34
- var yearStart = new Date(Date.UTC(newDate.getUTCFullYear(),0,1));
35
- var weekNo = Math.ceil(( ( (newDate - yearStart) / 86400000) + 1)/7);
36
- return weekNo;
30
+ // Get the ISO week number for a dayjs object
31
+ export function getWeekNumber(date) {
32
+ return dayjs(date).isoWeek()
37
33
  }
38
34
  //Check if two dates are the same
39
- export function isSameDate(date1, date2, method = '') {
40
- return date1.toISOString().split('T')[0] === date2.toISOString().split('T')[0];
35
+ export function isSameDate(date1, date2) {
36
+ return dayjs(date1).isSame(dayjs(date2), 'day')
41
37
  }
42
38
 
43
39
  // Check if two dates are consecutive days
44
- export function isNextDay(prev, current) {
45
- const prevDate = new Date(prev.getFullYear(), prev.getMonth(), prev.getDate());
46
- const nextDate = new Date(prevDate);
47
- nextDate.setDate(prevDate.getDate() + 1); // Add 1 day
48
-
49
- return (
50
- nextDate.getFullYear() === current.getFullYear() &&
51
- nextDate.getMonth() === current.getMonth() &&
52
- nextDate.getDate() === current.getDate()
53
- );
40
+ export function isNextDay(date1, date2) {
41
+ const d1 = dayjs(date1).startOf('day')
42
+ const d2 = dayjs(date2).startOf('day')
43
+ return d2.diff(d1, 'day') === 1
54
44
  }
55
-
56
45
  export function getTimeRemainingUntilLocal(targetUtcIsoString, {withTotalSeconds} = {}) {
57
46
  const targetUTC = new Date(targetUtcIsoString);
58
47
  if (isNaN(targetUTC.getTime())) {
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -791,17 +791,9 @@ export async function fetchUserPractices(currentVersion = 0, { userId } = {}) {
791
791
 
792
792
  const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
793
793
 
794
-
795
794
  const formattedPractices = userPractices.reduce((acc, practice) => {
796
795
  // Convert UTC date to user's local date (still a Date object)
797
- const utcDate = new Date(practice.day);
798
- const localDate = convertToTimeZone(utcDate, userTimeZone);
799
-
800
- const userTimeZoneDay =
801
- localDate.getFullYear() + '-' +
802
- String(localDate.getMonth() + 1).padStart(2, '0') + '-' +
803
- String(localDate.getDate()).padStart(2, '0');
804
-
796
+ const userTimeZoneDay = convertToTimeZone(practice.day, userTimeZone);
805
797
  if (!acc[userTimeZoneDay]) {
806
798
  acc[userTimeZoneDay] = [];
807
799
  }
File without changes