@open-mercato/core 0.6.6-develop.6094.1.28b081ea16 → 0.6.6-develop.6126.1.0b9392fdae

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 (317) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/catalog_product/index.js +52 -0
  3. package/dist/generated/entities/catalog_product/index.js.map +2 -2
  4. package/dist/generated/entities/catalog_product_variant/index.js +4 -0
  5. package/dist/generated/entities/catalog_product_variant/index.js.map +2 -2
  6. package/dist/generated/entity-fields-registry.js +28 -0
  7. package/dist/generated/entity-fields-registry.js.map +2 -2
  8. package/dist/modules/catalog/api/products/route.js +103 -33
  9. package/dist/modules/catalog/api/products/route.js.map +2 -2
  10. package/dist/modules/catalog/api/variants/route.js +4 -0
  11. package/dist/modules/catalog/api/variants/route.js.map +2 -2
  12. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +46 -2
  13. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  14. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +4 -0
  15. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  16. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js +2 -0
  17. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js.map +2 -2
  18. package/dist/modules/catalog/backend/catalog/products/create/page.js +42 -2
  19. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  20. package/dist/modules/catalog/commands/products.js +251 -14
  21. package/dist/modules/catalog/commands/products.js.map +2 -2
  22. package/dist/modules/catalog/commands/variants.js +72 -1
  23. package/dist/modules/catalog/commands/variants.js.map +2 -2
  24. package/dist/modules/catalog/components/products/ProductComplianceSection.js +500 -0
  25. package/dist/modules/catalog/components/products/ProductComplianceSection.js.map +7 -0
  26. package/dist/modules/catalog/components/products/VariantBuilder.js +39 -1
  27. package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
  28. package/dist/modules/catalog/components/products/productForm.js +164 -2
  29. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  30. package/dist/modules/catalog/components/products/variantForm.js +2 -0
  31. package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
  32. package/dist/modules/catalog/data/entities.js +93 -0
  33. package/dist/modules/catalog/data/entities.js.map +2 -2
  34. package/dist/modules/catalog/data/types.js +28 -0
  35. package/dist/modules/catalog/data/types.js.map +2 -2
  36. package/dist/modules/catalog/data/validators.js +100 -5
  37. package/dist/modules/catalog/data/validators.js.map +2 -2
  38. package/dist/modules/catalog/lib/gtin.js +61 -0
  39. package/dist/modules/catalog/lib/gtin.js.map +7 -0
  40. package/dist/modules/catalog/migrations/Migration20260611090000.js +17 -0
  41. package/dist/modules/catalog/migrations/Migration20260611090000.js.map +7 -0
  42. package/dist/modules/catalog/translations.js +1 -1
  43. package/dist/modules/catalog/translations.js.map +2 -2
  44. package/dist/modules/configs/api/cache/route.js +60 -10
  45. package/dist/modules/configs/api/cache/route.js.map +3 -3
  46. package/dist/modules/configs/components/CachePanel.js +52 -29
  47. package/dist/modules/configs/components/CachePanel.js.map +2 -2
  48. package/dist/modules/currencies/api/currencies/options/route.js +18 -4
  49. package/dist/modules/currencies/api/currencies/options/route.js.map +2 -2
  50. package/dist/modules/currencies/services/rateFetchingService.js +35 -18
  51. package/dist/modules/currencies/services/rateFetchingService.js.map +2 -2
  52. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +16 -16
  53. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  54. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +1 -1
  55. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  56. package/dist/modules/customers/backend/calendar/page.js +10 -0
  57. package/dist/modules/customers/backend/calendar/page.js.map +7 -0
  58. package/dist/modules/customers/backend/calendar/page.meta.js +25 -0
  59. package/dist/modules/customers/backend/calendar/page.meta.js.map +7 -0
  60. package/dist/modules/customers/cli.js +1 -0
  61. package/dist/modules/customers/cli.js.map +2 -2
  62. package/dist/modules/customers/components/calendar/AgendaList.js +182 -0
  63. package/dist/modules/customers/components/calendar/AgendaList.js.map +7 -0
  64. package/dist/modules/customers/components/calendar/CalendarEventEditor.js +331 -0
  65. package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +7 -0
  66. package/dist/modules/customers/components/calendar/CalendarFooter.js +48 -0
  67. package/dist/modules/customers/components/calendar/CalendarFooter.js.map +7 -0
  68. package/dist/modules/customers/components/calendar/CalendarHeader.js +36 -0
  69. package/dist/modules/customers/components/calendar/CalendarHeader.js.map +7 -0
  70. package/dist/modules/customers/components/calendar/CalendarScreen.js +516 -0
  71. package/dist/modules/customers/components/calendar/CalendarScreen.js.map +7 -0
  72. package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +163 -0
  73. package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +7 -0
  74. package/dist/modules/customers/components/calendar/CalendarTabs.js +60 -0
  75. package/dist/modules/customers/components/calendar/CalendarTabs.js.map +7 -0
  76. package/dist/modules/customers/components/calendar/CalendarToolbar.js +262 -0
  77. package/dist/modules/customers/components/calendar/CalendarToolbar.js.map +7 -0
  78. package/dist/modules/customers/components/calendar/EventBlock.js +149 -0
  79. package/dist/modules/customers/components/calendar/EventBlock.js.map +7 -0
  80. package/dist/modules/customers/components/calendar/EventPeekPopover.js +72 -0
  81. package/dist/modules/customers/components/calendar/EventPeekPopover.js.map +7 -0
  82. package/dist/modules/customers/components/calendar/MonthGrid.js +214 -0
  83. package/dist/modules/customers/components/calendar/MonthGrid.js.map +7 -0
  84. package/dist/modules/customers/components/calendar/ShortcutsDialog.js +44 -0
  85. package/dist/modules/customers/components/calendar/ShortcutsDialog.js.map +7 -0
  86. package/dist/modules/customers/components/calendar/TimeGrid.js +410 -0
  87. package/dist/modules/customers/components/calendar/TimeGrid.js.map +7 -0
  88. package/dist/modules/customers/components/calendar/UpcomingCards.js +175 -0
  89. package/dist/modules/customers/components/calendar/UpcomingCards.js.map +7 -0
  90. package/dist/modules/customers/components/calendar/editor/CategoryField.js +75 -0
  91. package/dist/modules/customers/components/calendar/editor/CategoryField.js.map +7 -0
  92. package/dist/modules/customers/components/calendar/editor/LocationField.js +30 -0
  93. package/dist/modules/customers/components/calendar/editor/LocationField.js.map +7 -0
  94. package/dist/modules/customers/components/calendar/editor/PeopleField.js +135 -0
  95. package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +7 -0
  96. package/dist/modules/customers/components/calendar/editor/RelatedToField.js +218 -0
  97. package/dist/modules/customers/components/calendar/editor/RelatedToField.js.map +7 -0
  98. package/dist/modules/customers/components/calendar/editor/RepeatField.js +119 -0
  99. package/dist/modules/customers/components/calendar/editor/RepeatField.js.map +7 -0
  100. package/dist/modules/customers/components/calendar/editor/ScheduleSection.js +83 -0
  101. package/dist/modules/customers/components/calendar/editor/ScheduleSection.js.map +7 -0
  102. package/dist/modules/customers/components/calendar/editor/SegmentGroup.js +44 -0
  103. package/dist/modules/customers/components/calendar/editor/SegmentGroup.js.map +7 -0
  104. package/dist/modules/customers/components/calendar/editor/hooks.js +132 -0
  105. package/dist/modules/customers/components/calendar/editor/hooks.js.map +7 -0
  106. package/dist/modules/customers/components/calendar/editor/inputs.js +160 -0
  107. package/dist/modules/customers/components/calendar/editor/inputs.js.map +7 -0
  108. package/dist/modules/customers/components/calendar/editor/lookups.js +107 -0
  109. package/dist/modules/customers/components/calendar/editor/lookups.js.map +7 -0
  110. package/dist/modules/customers/components/calendar/types.js +30 -0
  111. package/dist/modules/customers/components/calendar/types.js.map +7 -0
  112. package/dist/modules/customers/components/calendar/useCalendarItems.js +131 -0
  113. package/dist/modules/customers/components/calendar/useCalendarItems.js.map +7 -0
  114. package/dist/modules/customers/components/calendar/useCalendarPreferences.js +41 -0
  115. package/dist/modules/customers/components/calendar/useCalendarPreferences.js.map +7 -0
  116. package/dist/modules/customers/lib/calendar/categories.js +28 -0
  117. package/dist/modules/customers/lib/calendar/categories.js.map +7 -0
  118. package/dist/modules/customers/lib/calendar/conflicts.js +72 -0
  119. package/dist/modules/customers/lib/calendar/conflicts.js.map +7 -0
  120. package/dist/modules/customers/lib/calendar/editorPayload.js +271 -0
  121. package/dist/modules/customers/lib/calendar/editorPayload.js.map +7 -0
  122. package/dist/modules/customers/lib/calendar/grid.js +48 -0
  123. package/dist/modules/customers/lib/calendar/grid.js.map +7 -0
  124. package/dist/modules/customers/lib/calendar/layout.js +39 -0
  125. package/dist/modules/customers/lib/calendar/layout.js.map +7 -0
  126. package/dist/modules/customers/lib/calendar/mapItem.js +79 -0
  127. package/dist/modules/customers/lib/calendar/mapItem.js.map +7 -0
  128. package/dist/modules/customers/lib/calendar/preferences.js +71 -0
  129. package/dist/modules/customers/lib/calendar/preferences.js.map +7 -0
  130. package/dist/modules/customers/lib/calendar/range.js +46 -0
  131. package/dist/modules/customers/lib/calendar/range.js.map +7 -0
  132. package/dist/modules/customers/lib/calendar/recurrence.js +113 -0
  133. package/dist/modules/customers/lib/calendar/recurrence.js.map +7 -0
  134. package/dist/modules/dashboards/services/widgetDataService.js +5 -5
  135. package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
  136. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +61 -1
  137. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  138. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +33 -1
  139. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
  140. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +61 -1
  141. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  142. package/dist/modules/dictionaries/api/route.js +33 -1
  143. package/dist/modules/dictionaries/api/route.js.map +2 -2
  144. package/dist/modules/feature_toggles/lib/queries.js +36 -52
  145. package/dist/modules/feature_toggles/lib/queries.js.map +2 -2
  146. package/dist/modules/perspectives/api/[tableId]/[perspectiveId]/route.js +32 -1
  147. package/dist/modules/perspectives/api/[tableId]/[perspectiveId]/route.js.map +2 -2
  148. package/dist/modules/perspectives/api/[tableId]/roles/[roleId]/route.js +32 -1
  149. package/dist/modules/perspectives/api/[tableId]/roles/[roleId]/route.js.map +2 -2
  150. package/dist/modules/perspectives/api/[tableId]/route.js +73 -2
  151. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  152. package/dist/modules/perspectives/services/perspectiveService.js +5 -3
  153. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  154. package/dist/modules/planner/api/access.js +9 -0
  155. package/dist/modules/planner/api/access.js.map +2 -2
  156. package/dist/modules/planner/api/availability-date-specific.js +22 -1
  157. package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
  158. package/dist/modules/planner/api/availability-weekly.js +22 -1
  159. package/dist/modules/planner/api/availability-weekly.js.map +2 -2
  160. package/dist/modules/resources/api/resources/tags/assign/route.js +39 -0
  161. package/dist/modules/resources/api/resources/tags/assign/route.js.map +2 -2
  162. package/dist/modules/resources/api/resources/tags/unassign/route.js +39 -0
  163. package/dist/modules/resources/api/resources/tags/unassign/route.js.map +2 -2
  164. package/dist/modules/sales/api/settings/document-numbers/route.js +33 -1
  165. package/dist/modules/sales/api/settings/document-numbers/route.js.map +2 -2
  166. package/dist/modules/sales/api/settings/order-editing/route.js +35 -3
  167. package/dist/modules/sales/api/settings/order-editing/route.js.map +2 -2
  168. package/dist/modules/staff/api/leave-requests/accept/route.js +41 -0
  169. package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
  170. package/dist/modules/staff/api/leave-requests/reject/route.js +41 -0
  171. package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
  172. package/dist/modules/staff/api/team-members/self/route.js +40 -0
  173. package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
  174. package/dist/modules/staff/api/team-members/tags/assign/route.js +41 -0
  175. package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
  176. package/dist/modules/staff/api/team-members/tags/unassign/route.js +41 -0
  177. package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
  178. package/dist/modules/translations/api/[entityType]/[entityId]/route.js +61 -1
  179. package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
  180. package/dist/modules/translations/api/context.js +7 -0
  181. package/dist/modules/translations/api/context.js.map +2 -2
  182. package/dist/modules/translations/api/put/locales.js +33 -1
  183. package/dist/modules/translations/api/put/locales.js.map +2 -2
  184. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +6 -7
  185. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  186. package/dist/modules/workflows/backend/instances/[id]/page.js.map +1 -1
  187. package/dist/modules/workflows/components/EdgeEditDialog.js.map +1 -1
  188. package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js.map +1 -1
  189. package/dist/modules/workflows/components/NodeEditDialog.js.map +1 -1
  190. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +1 -1
  191. package/dist/modules/workflows/components/WorkflowGraph.js.map +1 -1
  192. package/dist/modules/workflows/components/WorkflowGraphImpl.js +17 -9
  193. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
  194. package/dist/modules/workflows/components/mobile/MobileVisualEditor.js.map +1 -1
  195. package/dist/modules/workflows/frontend/checkout-demo/deriveCurrentStep.js +8 -0
  196. package/dist/modules/workflows/frontend/checkout-demo/deriveCurrentStep.js.map +7 -0
  197. package/dist/modules/workflows/frontend/checkout-demo/page.js +2 -20
  198. package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
  199. package/dist/modules/workflows/lib/graph-utils.js +8 -0
  200. package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
  201. package/generated/entities/catalog_product/index.ts +26 -0
  202. package/generated/entities/catalog_product_variant/index.ts +2 -0
  203. package/generated/entity-fields-registry.ts +28 -0
  204. package/package.json +7 -7
  205. package/src/modules/catalog/api/products/route.ts +123 -39
  206. package/src/modules/catalog/api/variants/route.ts +4 -0
  207. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +43 -0
  208. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +14 -0
  209. package/src/modules/catalog/backend/catalog/products/[productId]/variants/create/page.tsx +2 -0
  210. package/src/modules/catalog/backend/catalog/products/create/page.tsx +41 -0
  211. package/src/modules/catalog/commands/products.ts +307 -2
  212. package/src/modules/catalog/commands/variants.ts +90 -1
  213. package/src/modules/catalog/components/products/ProductComplianceSection.tsx +497 -0
  214. package/src/modules/catalog/components/products/VariantBuilder.tsx +43 -0
  215. package/src/modules/catalog/components/products/productForm.ts +262 -0
  216. package/src/modules/catalog/components/products/variantForm.ts +4 -0
  217. package/src/modules/catalog/data/entities.ts +97 -0
  218. package/src/modules/catalog/data/types.ts +36 -0
  219. package/src/modules/catalog/data/validators.ts +159 -3
  220. package/src/modules/catalog/i18n/de.json +64 -0
  221. package/src/modules/catalog/i18n/en.json +64 -0
  222. package/src/modules/catalog/i18n/es.json +64 -0
  223. package/src/modules/catalog/i18n/pl.json +64 -0
  224. package/src/modules/catalog/lib/gtin.ts +66 -0
  225. package/src/modules/catalog/migrations/.snapshot-open-mercato.json +457 -0
  226. package/src/modules/catalog/migrations/Migration20260611090000.ts +17 -0
  227. package/src/modules/catalog/translations.ts +1 -1
  228. package/src/modules/configs/api/cache/route.ts +72 -10
  229. package/src/modules/configs/components/CachePanel.tsx +59 -29
  230. package/src/modules/currencies/api/currencies/options/route.ts +22 -4
  231. package/src/modules/currencies/services/rateFetchingService.ts +63 -26
  232. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +18 -18
  233. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +1 -1
  234. package/src/modules/customer_accounts/i18n/de.json +1 -1
  235. package/src/modules/customer_accounts/i18n/en.json +1 -1
  236. package/src/modules/customer_accounts/i18n/es.json +1 -1
  237. package/src/modules/customer_accounts/i18n/pl.json +1 -1
  238. package/src/modules/customers/backend/calendar/page.meta.ts +23 -0
  239. package/src/modules/customers/backend/calendar/page.tsx +12 -0
  240. package/src/modules/customers/cli.ts +1 -0
  241. package/src/modules/customers/components/calendar/AgendaList.tsx +219 -0
  242. package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +386 -0
  243. package/src/modules/customers/components/calendar/CalendarFooter.tsx +61 -0
  244. package/src/modules/customers/components/calendar/CalendarHeader.tsx +40 -0
  245. package/src/modules/customers/components/calendar/CalendarScreen.tsx +590 -0
  246. package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +207 -0
  247. package/src/modules/customers/components/calendar/CalendarTabs.tsx +63 -0
  248. package/src/modules/customers/components/calendar/CalendarToolbar.tsx +295 -0
  249. package/src/modules/customers/components/calendar/EventBlock.tsx +205 -0
  250. package/src/modules/customers/components/calendar/EventPeekPopover.tsx +100 -0
  251. package/src/modules/customers/components/calendar/MonthGrid.tsx +236 -0
  252. package/src/modules/customers/components/calendar/ShortcutsDialog.tsx +57 -0
  253. package/src/modules/customers/components/calendar/TimeGrid.tsx +510 -0
  254. package/src/modules/customers/components/calendar/UpcomingCards.tsx +220 -0
  255. package/src/modules/customers/components/calendar/editor/CategoryField.tsx +79 -0
  256. package/src/modules/customers/components/calendar/editor/LocationField.tsx +37 -0
  257. package/src/modules/customers/components/calendar/editor/PeopleField.tsx +148 -0
  258. package/src/modules/customers/components/calendar/editor/RelatedToField.tsx +242 -0
  259. package/src/modules/customers/components/calendar/editor/RepeatField.tsx +132 -0
  260. package/src/modules/customers/components/calendar/editor/ScheduleSection.tsx +110 -0
  261. package/src/modules/customers/components/calendar/editor/SegmentGroup.tsx +50 -0
  262. package/src/modules/customers/components/calendar/editor/hooks.ts +162 -0
  263. package/src/modules/customers/components/calendar/editor/inputs.tsx +158 -0
  264. package/src/modules/customers/components/calendar/editor/lookups.ts +160 -0
  265. package/src/modules/customers/components/calendar/types.ts +163 -0
  266. package/src/modules/customers/components/calendar/useCalendarItems.ts +162 -0
  267. package/src/modules/customers/components/calendar/useCalendarPreferences.ts +52 -0
  268. package/src/modules/customers/i18n/de.json +195 -0
  269. package/src/modules/customers/i18n/en.json +195 -0
  270. package/src/modules/customers/i18n/es.json +195 -0
  271. package/src/modules/customers/i18n/pl.json +195 -0
  272. package/src/modules/customers/lib/calendar/categories.ts +26 -0
  273. package/src/modules/customers/lib/calendar/conflicts.ts +117 -0
  274. package/src/modules/customers/lib/calendar/editorPayload.ts +388 -0
  275. package/src/modules/customers/lib/calendar/grid.ts +50 -0
  276. package/src/modules/customers/lib/calendar/layout.ts +47 -0
  277. package/src/modules/customers/lib/calendar/mapItem.ts +94 -0
  278. package/src/modules/customers/lib/calendar/preferences.ts +95 -0
  279. package/src/modules/customers/lib/calendar/range.ts +45 -0
  280. package/src/modules/customers/lib/calendar/recurrence.ts +137 -0
  281. package/src/modules/dashboards/services/widgetDataService.ts +8 -6
  282. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +61 -1
  283. package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +33 -1
  284. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +65 -1
  285. package/src/modules/dictionaries/api/route.ts +36 -1
  286. package/src/modules/feature_toggles/lib/queries.ts +41 -60
  287. package/src/modules/perspectives/api/[tableId]/[perspectiveId]/route.ts +34 -1
  288. package/src/modules/perspectives/api/[tableId]/roles/[roleId]/route.ts +34 -1
  289. package/src/modules/perspectives/api/[tableId]/route.ts +107 -32
  290. package/src/modules/perspectives/services/perspectiveService.ts +9 -5
  291. package/src/modules/planner/api/access.ts +9 -0
  292. package/src/modules/planner/api/availability-date-specific.ts +22 -1
  293. package/src/modules/planner/api/availability-weekly.ts +22 -1
  294. package/src/modules/resources/api/resources/tags/assign/route.ts +42 -0
  295. package/src/modules/resources/api/resources/tags/unassign/route.ts +42 -0
  296. package/src/modules/sales/api/settings/document-numbers/route.ts +35 -1
  297. package/src/modules/sales/api/settings/order-editing/route.ts +37 -3
  298. package/src/modules/staff/api/leave-requests/accept/route.ts +45 -0
  299. package/src/modules/staff/api/leave-requests/reject/route.ts +45 -0
  300. package/src/modules/staff/api/team-members/self/route.ts +43 -0
  301. package/src/modules/staff/api/team-members/tags/assign/route.ts +45 -0
  302. package/src/modules/staff/api/team-members/tags/unassign/route.ts +45 -0
  303. package/src/modules/translations/api/[entityType]/[entityId]/route.ts +65 -1
  304. package/src/modules/translations/api/context.ts +7 -0
  305. package/src/modules/translations/api/put/locales.ts +35 -1
  306. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +11 -9
  307. package/src/modules/workflows/backend/instances/[id]/page.tsx +1 -1
  308. package/src/modules/workflows/components/EdgeEditDialog.tsx +1 -1
  309. package/src/modules/workflows/components/EdgeEditDialogCrudForm.tsx +1 -1
  310. package/src/modules/workflows/components/NodeEditDialog.tsx +1 -1
  311. package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +1 -1
  312. package/src/modules/workflows/components/WorkflowGraph.tsx +2 -2
  313. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +27 -13
  314. package/src/modules/workflows/components/mobile/MobileVisualEditor.tsx +3 -3
  315. package/src/modules/workflows/frontend/checkout-demo/deriveCurrentStep.ts +12 -0
  316. package/src/modules/workflows/frontend/checkout-demo/page.tsx +3 -23
  317. package/src/modules/workflows/lib/graph-utils.ts +21 -1
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/lib/calendar/editorPayload.ts"],
4
+ "sourcesContent": ["import type { CalendarItem } from '../../components/calendar/types'\nimport { parseRecurrenceRule } from './recurrence'\n\nexport type EditorKind = 'meeting' | 'call' | 'email' | 'note' | 'event' | 'task'\n\nexport const EDITOR_KINDS: EditorKind[] = ['meeting', 'call', 'email', 'note', 'event', 'task']\n\nexport type EditorDateLabel = 'starts' | 'when' | 'sent' | 'logged' | 'due'\n\nexport type EditorPeopleMode = 'attendees' | 'participants' | 'to' | 'assignee'\n\nexport type EditorKindConfig = {\n dateLabel: EditorDateLabel\n hasEnd: boolean\n hasAllDay: boolean\n hasRepeat: boolean\n location: 'location' | 'phoneLink' | null\n people: EditorPeopleMode | null\n hasPriority: boolean\n}\n\nexport const KIND_CONFIG: Record<EditorKind, EditorKindConfig> = {\n meeting: { dateLabel: 'starts', hasEnd: true, hasAllDay: true, hasRepeat: true, location: 'location', people: 'attendees', hasPriority: false },\n call: { dateLabel: 'when', hasEnd: false, hasAllDay: true, hasRepeat: true, location: 'phoneLink', people: 'participants', hasPriority: false },\n email: { dateLabel: 'sent', hasEnd: false, hasAllDay: true, hasRepeat: true, location: null, people: 'to', hasPriority: false },\n note: { dateLabel: 'logged', hasEnd: false, hasAllDay: false, hasRepeat: false, location: null, people: null, hasPriority: false },\n event: { dateLabel: 'starts', hasEnd: true, hasAllDay: true, hasRepeat: true, location: 'location', people: 'attendees', hasPriority: false },\n task: { dateLabel: 'due', hasEnd: false, hasAllDay: true, hasRepeat: true, location: null, people: 'assignee', hasPriority: true },\n}\n\nconst KIND_BY_INTERACTION_TYPE: Record<string, EditorKind> = {\n meeting: 'meeting',\n call: 'call',\n 'video-call': 'call',\n email: 'email',\n note: 'note',\n event: 'event',\n webinar: 'event',\n task: 'task',\n todo: 'task',\n deadline: 'task',\n}\n\nexport function editorKindOfInteractionType(interactionType: string): EditorKind {\n return KIND_BY_INTERACTION_TYPE[interactionType] ?? 'meeting'\n}\n\nexport type EditorCategoryOption = { value: string; label: string }\n\n/**\n * Builds the editor's Category quick-pick options from the tenant dictionary and\n * the user's calendar preferences:\n * - `surfacedTypes` (settings \"Activity Types\") filters which dictionary types are\n * offered \u2014 a non-empty list keeps only matching labels; empty means \"show all\".\n * - `eventCategories` (settings \"Event Categories\") add custom quick-pick labels.\n * Dictionary entries keep their canonical key as the value (so category\u2192tab/tint\n * mapping is preserved); custom labels use the label as the value.\n */\nexport function buildEditorCategoryOptions(params: {\n typeLabels: Record<string, string>\n surfacedTypes: string[]\n eventCategories: string[]\n selectedValue: string\n selectedFallbackLabel: string\n}): EditorCategoryOption[] {\n const { typeLabels, surfacedTypes, eventCategories, selectedValue, selectedFallbackLabel } = params\n const dictionaryOptions: EditorCategoryOption[] = Object.entries(typeLabels).map(([value, label]) => ({ value, label }))\n const surfacedSet = new Set(surfacedTypes)\n const filtered =\n surfacedTypes.length > 0\n ? dictionaryOptions.filter((option) => surfacedSet.has(option.label))\n : dictionaryOptions\n const options = [...filtered]\n const knownLabels = new Set(options.map((option) => option.label))\n const knownValues = new Set(options.map((option) => option.value))\n const customLabels: string[] = []\n for (const label of [...eventCategories, ...surfacedTypes]) {\n const trimmed = label.trim()\n if (!trimmed || knownLabels.has(trimmed) || customLabels.includes(trimmed)) continue\n customLabels.push(trimmed)\n }\n for (const label of customLabels) {\n options.push({ value: label, label })\n knownValues.add(label)\n }\n if (!knownValues.has(selectedValue)) {\n options.unshift({ value: selectedValue, label: typeLabels[selectedValue] ?? selectedFallbackLabel })\n }\n return options\n}\n\nexport type EditorRepeatFreq = 'none' | 'daily' | 'weekly'\n\nexport type EditorRepeatEndType = 'never' | 'date' | 'count'\n\nexport type EditorPriority = 'low' | 'medium' | 'high'\n\nexport const PRIORITY_NUMBER: Record<EditorPriority, number> = { low: 10, medium: 50, high: 90 }\n\nexport function priorityFromNumber(value: number | null | undefined): EditorPriority {\n if (typeof value !== 'number' || Number.isNaN(value)) return 'medium'\n if (value <= 33) return 'low'\n if (value <= 66) return 'medium'\n return 'high'\n}\n\nexport type EditorRelatedTo = {\n id: string\n kind: 'person' | 'company' | 'unknown'\n label: string\n}\n\nexport type EditorParticipant = {\n userId: string\n name: string\n email?: string\n isCustomer: boolean\n}\n\nexport type EditorFormState = {\n kind: EditorKind\n title: string\n relatedTo: EditorRelatedTo | null\n dealId: string | null\n dealLabel: string | null\n allDay: boolean\n date: string\n startTime: string\n endDate: string\n endTime: string\n repeatFreq: EditorRepeatFreq\n repeatDays: boolean[]\n repeatEndType: EditorRepeatEndType\n repeatCount: number\n repeatUntilDate: string\n category: string | null\n location: string\n participants: EditorParticipant[]\n assigneeUserId: string | null\n assigneeName: string | null\n priority: EditorPriority\n description: string\n status: 'planned' | 'done' | 'canceled'\n}\n\nconst MO_FIRST_DAY_TOKENS = ['MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU'] as const\n\nfunction padDatePart(value: number): string {\n return String(value).padStart(2, '0')\n}\n\nexport function formatLocalDateInput(date: Date): string {\n return `${date.getFullYear()}-${padDatePart(date.getMonth() + 1)}-${padDatePart(date.getDate())}`\n}\n\nexport function formatLocalTimeInput(date: Date): string {\n return `${padDatePart(date.getHours())}:${padDatePart(date.getMinutes())}`\n}\n\nfunction moFirstIndexOfDate(date: Date): number {\n return (date.getDay() + 6) % 7\n}\n\nexport function defaultRepeatDaysForDateInput(dateInput: string): boolean[] {\n const parsed = new Date(`${dateInput}T00:00:00`)\n return defaultRepeatDays(Number.isNaN(parsed.getTime()) ? new Date() : parsed)\n}\n\nfunction defaultRepeatDays(start: Date): boolean[] {\n const days = [false, false, false, false, false, false, false]\n days[moFirstIndexOfDate(start)] = true\n return days\n}\n\n/**\n * Resolves the `ownerUserId` an interaction will actually be SAVED with, so the\n * editor's conflict probe keys on the same owner the grid sees after save (see\n * buildInteractionPayload + the create/update command):\n * - Task (people === 'assignee'): owner = the assignee.\n * - Other kinds: the payload omits owner, so edit preserves the existing owner\n * and create is ownerless (null) \u2014 conflicts then come from participants only.\n */\nexport function resolveSavedOwnerUserId(\n config: EditorKindConfig,\n form: EditorFormState,\n isEdit: boolean,\n existingOwnerUserId: string | null,\n): string | null {\n if (config.people === 'assignee') return form.assigneeUserId ?? null\n return isEdit ? existingOwnerUserId : null\n}\n\nexport function createDefaultFormState(\n defaultDate?: Date | null,\n now: Date = new Date(),\n range?: { start: Date; end: Date } | null,\n): EditorFormState {\n let base: Date\n let end: Date\n if (range) {\n base = new Date(range.start)\n end = new Date(range.end)\n } else {\n base = defaultDate ? new Date(defaultDate) : new Date(now)\n base.setHours(now.getHours(), 0, 0, 0)\n base.setHours(base.getHours() + 1)\n end = new Date(base.getTime() + 90 * 60_000)\n }\n return {\n kind: 'meeting',\n title: '',\n relatedTo: null,\n dealId: null,\n dealLabel: null,\n allDay: false,\n date: formatLocalDateInput(base),\n startTime: formatLocalTimeInput(base),\n endDate: formatLocalDateInput(end),\n endTime: formatLocalTimeInput(end),\n repeatFreq: 'none',\n repeatDays: defaultRepeatDays(base),\n repeatEndType: 'never',\n repeatCount: 8,\n repeatUntilDate: '',\n category: null,\n location: '',\n participants: [],\n assigneeUserId: null,\n assigneeName: null,\n priority: 'medium',\n description: '',\n status: 'planned',\n }\n}\n\nexport function buildRecurrenceRule(state: EditorFormState): string | null {\n if (state.repeatFreq === 'none') return null\n let rule: string\n if (state.repeatFreq === 'daily') {\n rule = 'FREQ=DAILY'\n } else {\n const selected = MO_FIRST_DAY_TOKENS.filter((_, index) => state.repeatDays[index])\n const tokens = selected.length > 0\n ? selected\n : [MO_FIRST_DAY_TOKENS[moFirstIndexOfDate(new Date(`${state.date}T00:00:00`))]]\n rule = `FREQ=WEEKLY;BYDAY=${tokens.join(',')}`\n }\n if (state.repeatEndType === 'count') rule += `;COUNT=${state.repeatCount}`\n if (state.repeatEndType === 'date' && state.repeatUntilDate) {\n rule += `;UNTIL=${state.repeatUntilDate.replace(/-/g, '')}T235959Z`\n }\n return rule\n}\n\nexport function computeDurationMinutes(state: EditorFormState): number | null {\n const start = new Date(`${state.date}T${state.startTime}:00`)\n const end = new Date(`${state.endDate}T${state.endTime}:00`)\n if (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) return null\n const minutes = Math.round((end.getTime() - start.getTime()) / 60_000)\n return minutes > 0 ? minutes : null\n}\n\nexport type BuildPayloadOptions = { mode: 'create' | 'edit'; id?: string }\n\nexport function buildInteractionPayload(state: EditorFormState, options: BuildPayloadOptions): Record<string, unknown> {\n const config = KIND_CONFIG[state.kind]\n const time = state.allDay && config.hasAllDay ? '00:00' : state.startTime\n const scheduledAt = new Date(`${state.date}T${time}:00`).toISOString()\n const recurrenceRule = config.hasRepeat ? buildRecurrenceRule(state) : null\n const payload: Record<string, unknown> = {\n ...(options.mode === 'edit' && options.id ? { id: options.id } : {}),\n entityId: state.relatedTo?.id ?? null,\n dealId: state.dealId ?? null,\n interactionType: state.category ?? state.kind,\n title: state.title.trim(),\n body: state.description.trim() || null,\n status: options.mode === 'create' ? 'planned' : state.status,\n date: state.date,\n time,\n scheduledAt,\n durationMinutes: config.hasEnd && !(state.allDay && config.hasAllDay) ? computeDurationMinutes(state) : null,\n allDay: config.hasAllDay ? state.allDay : null,\n location: config.location ? state.location.trim() || null : null,\n recurrenceRule,\n recurrenceEnd:\n recurrenceRule && state.repeatEndType === 'date' && state.repeatUntilDate\n ? new Date(state.repeatUntilDate).toISOString()\n : null,\n participants:\n config.people && config.people !== 'assignee' && state.participants.length > 0\n ? state.participants.map((participant) => ({\n userId: participant.userId,\n name: participant.name,\n email: participant.email,\n status: participant.isCustomer ? 'customer' : 'pending',\n }))\n : null,\n }\n if (config.people === 'assignee') payload.ownerUserId = state.assigneeUserId ?? null\n if (config.hasPriority) payload.priority = PRIORITY_NUMBER[state.priority]\n return payload\n}\n\nfunction readUnknownString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\nfunction readUnknownNumber(value: unknown): number | null {\n return typeof value === 'number' && Number.isFinite(value) ? value : null\n}\n\ntype ParsedRepeat = Pick<EditorFormState, 'repeatFreq' | 'repeatDays' | 'repeatEndType' | 'repeatCount' | 'repeatUntilDate'>\n\nfunction parseRepeatFromRule(rawRule: unknown, start: Date): ParsedRepeat {\n const fallback: ParsedRepeat = {\n repeatFreq: 'none',\n repeatDays: defaultRepeatDays(start),\n repeatEndType: 'never',\n repeatCount: 8,\n repeatUntilDate: '',\n }\n const ruleText = readUnknownString(rawRule)\n if (!ruleText) return fallback\n const parsed = parseRecurrenceRule(ruleText)\n if (!parsed) return fallback\n const repeatDays = defaultRepeatDays(start)\n if (parsed.byDay) {\n repeatDays.fill(false)\n for (const jsWeekday of parsed.byDay) repeatDays[(jsWeekday + 6) % 7] = true\n }\n let repeatEndType: EditorRepeatEndType = 'never'\n let repeatCount = 8\n let repeatUntilDate = ''\n if (parsed.count !== null) {\n repeatEndType = 'count'\n repeatCount = parsed.count\n } else if (parsed.until) {\n repeatEndType = 'date'\n repeatUntilDate = `${parsed.until.getUTCFullYear()}-${padDatePart(parsed.until.getUTCMonth() + 1)}-${padDatePart(parsed.until.getUTCDate())}`\n }\n return {\n repeatFreq: parsed.freq === 'DAILY' ? 'daily' : 'weekly',\n repeatDays,\n repeatEndType,\n repeatCount,\n repeatUntilDate,\n }\n}\n\nfunction parseParticipants(item: CalendarItem): EditorParticipant[] {\n const rawParticipants = Array.isArray(item.raw.participants) ? item.raw.participants : []\n const statusByUserId = new Map<string, string | null>()\n for (const raw of rawParticipants) {\n statusByUserId.set(raw.userId, readUnknownString((raw as Record<string, unknown>).status))\n }\n return item.participants.map((participant) => ({\n userId: participant.userId,\n name: participant.name ?? participant.email ?? participant.userId,\n email: participant.email,\n isCustomer: statusByUserId.get(participant.userId) === 'customer',\n }))\n}\n\nexport function parseItemToFormState(item: CalendarItem): EditorFormState {\n const kind = editorKindOfInteractionType(item.interactionType)\n const raw = item.raw as Record<string, unknown>\n return {\n kind,\n title: item.title,\n relatedTo: item.entityId ? { id: item.entityId, kind: 'unknown', label: '' } : null,\n dealId: item.dealId,\n dealLabel: null,\n allDay: item.allDay,\n date: formatLocalDateInput(item.start),\n startTime: formatLocalTimeInput(item.start),\n endDate: formatLocalDateInput(item.end),\n endTime: formatLocalTimeInput(item.end),\n ...parseRepeatFromRule(item.raw.recurrenceRule, item.start),\n category: item.interactionType,\n location: item.location ?? '',\n participants: parseParticipants(item),\n assigneeUserId: item.ownerUserId,\n assigneeName: null,\n priority: priorityFromNumber(readUnknownNumber(raw.priority)),\n description: readUnknownString(raw.body) ?? '',\n status: item.status,\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,48 @@
1
+ const DRAG_SNAP_MINUTES = 15;
2
+ const MIN_DRAG_DURATION_MINUTES = 30;
3
+ const MINUTES_PER_DAY = 24 * 60;
4
+ function isWeekendDay(date) {
5
+ const weekday = date.getDay();
6
+ return weekday === 0 || weekday === 6;
7
+ }
8
+ function applyWeekendVisibility(days, showWeekends) {
9
+ if (showWeekends) return days;
10
+ const workingDays = days.filter((day) => !isWeekendDay(day));
11
+ return workingDays.length > 0 ? workingDays : days;
12
+ }
13
+ function clampMinutes(value) {
14
+ if (value < 0) return 0;
15
+ if (value > MINUTES_PER_DAY) return MINUTES_PER_DAY;
16
+ return value;
17
+ }
18
+ function offsetYToMinutes(offsetY, hourHeightPx, snapMinutes = DRAG_SNAP_MINUTES) {
19
+ if (hourHeightPx <= 0) return 0;
20
+ const rawMinutes = offsetY / hourHeightPx * 60;
21
+ const snapped = Math.round(rawMinutes / snapMinutes) * snapMinutes;
22
+ return clampMinutes(snapped);
23
+ }
24
+ function buildDragRange(dayStart, startMinutes, endMinutes) {
25
+ let lower = clampMinutes(Math.min(startMinutes, endMinutes));
26
+ let upper = clampMinutes(Math.max(startMinutes, endMinutes));
27
+ if (upper - lower < MIN_DRAG_DURATION_MINUTES) upper = lower + MIN_DRAG_DURATION_MINUTES;
28
+ if (upper > MINUTES_PER_DAY) {
29
+ upper = MINUTES_PER_DAY;
30
+ lower = Math.max(0, upper - MIN_DRAG_DURATION_MINUTES);
31
+ }
32
+ const start = new Date(dayStart);
33
+ start.setHours(0, 0, 0, 0);
34
+ start.setMinutes(lower);
35
+ const end = new Date(dayStart);
36
+ end.setHours(0, 0, 0, 0);
37
+ end.setMinutes(upper);
38
+ return { start, end };
39
+ }
40
+ export {
41
+ DRAG_SNAP_MINUTES,
42
+ MIN_DRAG_DURATION_MINUTES,
43
+ applyWeekendVisibility,
44
+ buildDragRange,
45
+ isWeekendDay,
46
+ offsetYToMinutes
47
+ };
48
+ //# sourceMappingURL=grid.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/lib/calendar/grid.ts"],
4
+ "sourcesContent": ["export const DRAG_SNAP_MINUTES = 15\nexport const MIN_DRAG_DURATION_MINUTES = 30\nconst MINUTES_PER_DAY = 24 * 60\n\nexport function isWeekendDay(date: Date): boolean {\n const weekday = date.getDay()\n return weekday === 0 || weekday === 6\n}\n\nexport function applyWeekendVisibility(days: Date[], showWeekends: boolean): Date[] {\n if (showWeekends) return days\n const workingDays = days.filter((day) => !isWeekendDay(day))\n return workingDays.length > 0 ? workingDays : days\n}\n\nfunction clampMinutes(value: number): number {\n if (value < 0) return 0\n if (value > MINUTES_PER_DAY) return MINUTES_PER_DAY\n return value\n}\n\nexport function offsetYToMinutes(\n offsetY: number,\n hourHeightPx: number,\n snapMinutes: number = DRAG_SNAP_MINUTES,\n): number {\n if (hourHeightPx <= 0) return 0\n const rawMinutes = (offsetY / hourHeightPx) * 60\n const snapped = Math.round(rawMinutes / snapMinutes) * snapMinutes\n return clampMinutes(snapped)\n}\n\nexport type DragRange = { start: Date; end: Date }\n\nexport function buildDragRange(dayStart: Date, startMinutes: number, endMinutes: number): DragRange {\n let lower = clampMinutes(Math.min(startMinutes, endMinutes))\n let upper = clampMinutes(Math.max(startMinutes, endMinutes))\n if (upper - lower < MIN_DRAG_DURATION_MINUTES) upper = lower + MIN_DRAG_DURATION_MINUTES\n if (upper > MINUTES_PER_DAY) {\n upper = MINUTES_PER_DAY\n lower = Math.max(0, upper - MIN_DRAG_DURATION_MINUTES)\n }\n const start = new Date(dayStart)\n start.setHours(0, 0, 0, 0)\n start.setMinutes(lower)\n const end = new Date(dayStart)\n end.setHours(0, 0, 0, 0)\n end.setMinutes(upper)\n return { start, end }\n}\n"],
5
+ "mappings": "AAAO,MAAM,oBAAoB;AAC1B,MAAM,4BAA4B;AACzC,MAAM,kBAAkB,KAAK;AAEtB,SAAS,aAAa,MAAqB;AAChD,QAAM,UAAU,KAAK,OAAO;AAC5B,SAAO,YAAY,KAAK,YAAY;AACtC;AAEO,SAAS,uBAAuB,MAAc,cAA+B;AAClF,MAAI,aAAc,QAAO;AACzB,QAAM,cAAc,KAAK,OAAO,CAAC,QAAQ,CAAC,aAAa,GAAG,CAAC;AAC3D,SAAO,YAAY,SAAS,IAAI,cAAc;AAChD;AAEA,SAAS,aAAa,OAAuB;AAC3C,MAAI,QAAQ,EAAG,QAAO;AACtB,MAAI,QAAQ,gBAAiB,QAAO;AACpC,SAAO;AACT;AAEO,SAAS,iBACd,SACA,cACA,cAAsB,mBACd;AACR,MAAI,gBAAgB,EAAG,QAAO;AAC9B,QAAM,aAAc,UAAU,eAAgB;AAC9C,QAAM,UAAU,KAAK,MAAM,aAAa,WAAW,IAAI;AACvD,SAAO,aAAa,OAAO;AAC7B;AAIO,SAAS,eAAe,UAAgB,cAAsB,YAA+B;AAClG,MAAI,QAAQ,aAAa,KAAK,IAAI,cAAc,UAAU,CAAC;AAC3D,MAAI,QAAQ,aAAa,KAAK,IAAI,cAAc,UAAU,CAAC;AAC3D,MAAI,QAAQ,QAAQ,0BAA2B,SAAQ,QAAQ;AAC/D,MAAI,QAAQ,iBAAiB;AAC3B,YAAQ;AACR,YAAQ,KAAK,IAAI,GAAG,QAAQ,yBAAyB;AAAA,EACvD;AACA,QAAM,QAAQ,IAAI,KAAK,QAAQ;AAC/B,QAAM,SAAS,GAAG,GAAG,GAAG,CAAC;AACzB,QAAM,WAAW,KAAK;AACtB,QAAM,MAAM,IAAI,KAAK,QAAQ;AAC7B,MAAI,SAAS,GAAG,GAAG,GAAG,CAAC;AACvB,MAAI,WAAW,KAAK;AACpB,SAAO,EAAE,OAAO,IAAI;AACtB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,39 @@
1
+ function packOverlaps(dayItems) {
2
+ const sorted = [...dayItems].sort((first, second) => {
3
+ const startDelta = first.start.getTime() - second.start.getTime();
4
+ if (startDelta !== 0) return startDelta;
5
+ return second.end.getTime() - first.end.getTime();
6
+ });
7
+ const result = [];
8
+ let cluster = [];
9
+ let columnEnds = [];
10
+ let clusterEnd = Number.NEGATIVE_INFINITY;
11
+ const flushCluster = () => {
12
+ const columns = columnEnds.length;
13
+ for (const entry of cluster) {
14
+ result.push({ item: entry.item, column: entry.column, columns });
15
+ }
16
+ cluster = [];
17
+ columnEnds = [];
18
+ clusterEnd = Number.NEGATIVE_INFINITY;
19
+ };
20
+ for (const item of sorted) {
21
+ const startTime = item.start.getTime();
22
+ if (cluster.length > 0 && startTime >= clusterEnd) flushCluster();
23
+ let column = columnEnds.findIndex((columnEnd) => columnEnd <= startTime);
24
+ if (column === -1) {
25
+ column = columnEnds.length;
26
+ columnEnds.push(item.end.getTime());
27
+ } else {
28
+ columnEnds[column] = item.end.getTime();
29
+ }
30
+ cluster.push({ item, column });
31
+ clusterEnd = Math.max(clusterEnd, item.end.getTime());
32
+ }
33
+ flushCluster();
34
+ return result;
35
+ }
36
+ export {
37
+ packOverlaps
38
+ };
39
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/lib/calendar/layout.ts"],
4
+ "sourcesContent": ["import type { CalendarItem } from '../../components/calendar/types'\n\nexport type PackedCalendarItem = {\n item: CalendarItem\n column: number\n columns: number\n}\n\nexport function packOverlaps(dayItems: CalendarItem[]): PackedCalendarItem[] {\n const sorted = [...dayItems].sort((first, second) => {\n const startDelta = first.start.getTime() - second.start.getTime()\n if (startDelta !== 0) return startDelta\n return second.end.getTime() - first.end.getTime()\n })\n\n const result: PackedCalendarItem[] = []\n let cluster: Array<{ item: CalendarItem; column: number }> = []\n let columnEnds: number[] = []\n let clusterEnd = Number.NEGATIVE_INFINITY\n\n const flushCluster = () => {\n const columns = columnEnds.length\n for (const entry of cluster) {\n result.push({ item: entry.item, column: entry.column, columns })\n }\n cluster = []\n columnEnds = []\n clusterEnd = Number.NEGATIVE_INFINITY\n }\n\n for (const item of sorted) {\n const startTime = item.start.getTime()\n if (cluster.length > 0 && startTime >= clusterEnd) flushCluster()\n let column = columnEnds.findIndex((columnEnd) => columnEnd <= startTime)\n if (column === -1) {\n column = columnEnds.length\n columnEnds.push(item.end.getTime())\n } else {\n columnEnds[column] = item.end.getTime()\n }\n cluster.push({ item, column })\n clusterEnd = Math.max(clusterEnd, item.end.getTime())\n }\n flushCluster()\n\n return result\n}\n"],
5
+ "mappings": "AAQO,SAAS,aAAa,UAAgD;AAC3E,QAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,OAAO,WAAW;AACnD,UAAM,aAAa,MAAM,MAAM,QAAQ,IAAI,OAAO,MAAM,QAAQ;AAChE,QAAI,eAAe,EAAG,QAAO;AAC7B,WAAO,OAAO,IAAI,QAAQ,IAAI,MAAM,IAAI,QAAQ;AAAA,EAClD,CAAC;AAED,QAAM,SAA+B,CAAC;AACtC,MAAI,UAAyD,CAAC;AAC9D,MAAI,aAAuB,CAAC;AAC5B,MAAI,aAAa,OAAO;AAExB,QAAM,eAAe,MAAM;AACzB,UAAM,UAAU,WAAW;AAC3B,eAAW,SAAS,SAAS;AAC3B,aAAO,KAAK,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,QAAQ,QAAQ,CAAC;AAAA,IACjE;AACA,cAAU,CAAC;AACX,iBAAa,CAAC;AACd,iBAAa,OAAO;AAAA,EACtB;AAEA,aAAW,QAAQ,QAAQ;AACzB,UAAM,YAAY,KAAK,MAAM,QAAQ;AACrC,QAAI,QAAQ,SAAS,KAAK,aAAa,WAAY,cAAa;AAChE,QAAI,SAAS,WAAW,UAAU,CAAC,cAAc,aAAa,SAAS;AACvE,QAAI,WAAW,IAAI;AACjB,eAAS,WAAW;AACpB,iBAAW,KAAK,KAAK,IAAI,QAAQ,CAAC;AAAA,IACpC,OAAO;AACL,iBAAW,MAAM,IAAI,KAAK,IAAI,QAAQ;AAAA,IACxC;AACA,YAAQ,KAAK,EAAE,MAAM,OAAO,CAAC;AAC7B,iBAAa,KAAK,IAAI,YAAY,KAAK,IAAI,QAAQ,CAAC;AAAA,EACtD;AACA,eAAa;AAEb,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,79 @@
1
+ import { addMinutes } from "date-fns/addMinutes";
2
+ import { endOfDay } from "date-fns/endOfDay";
3
+ import { startOfDay } from "date-fns/startOfDay";
4
+ import { categoryOf } from "./categories.js";
5
+ const DEFAULT_DURATION_MINUTES = 30;
6
+ function narrowStatus(status) {
7
+ if (status === "done") return "done";
8
+ if (status === "canceled") return "canceled";
9
+ return "planned";
10
+ }
11
+ function detectPlatform(location) {
12
+ if (!location) return null;
13
+ const normalized = location.toLowerCase();
14
+ if (normalized.includes("zoom.us") || normalized.includes("zoom")) return "zoom";
15
+ if (normalized.includes("meet.google") || normalized.includes("on meet")) return "meet";
16
+ if (normalized.includes("slack")) return "slack";
17
+ if (normalized.includes("teams")) return "teams";
18
+ return null;
19
+ }
20
+ function detectLocationKind(location, platform) {
21
+ if (!location) return null;
22
+ const normalized = location.trim().toLowerCase();
23
+ if (normalized.startsWith("http") || normalized.startsWith("www")) return "url";
24
+ if (platform) return "platform";
25
+ return "venue";
26
+ }
27
+ function mapParticipants(payload) {
28
+ const participants = payload.participants;
29
+ if (!Array.isArray(participants)) return [];
30
+ const seen = /* @__PURE__ */ new Set();
31
+ const mapped = [];
32
+ for (const participant of participants) {
33
+ if (seen.has(participant.userId)) continue;
34
+ seen.add(participant.userId);
35
+ const entry = { userId: participant.userId };
36
+ if (typeof participant.name === "string") entry.name = participant.name;
37
+ if (typeof participant.email === "string") entry.email = participant.email;
38
+ mapped.push(entry);
39
+ }
40
+ return mapped;
41
+ }
42
+ function mapInteractionToCalendarItem(payload, typeColorByType) {
43
+ const effectiveStartRaw = payload.occurredAt ?? payload.scheduledAt ?? null;
44
+ if (!effectiveStartRaw) return null;
45
+ const parsedStart = new Date(effectiveStartRaw);
46
+ if (Number.isNaN(parsedStart.getTime())) return null;
47
+ const allDay = payload.allDay === true;
48
+ const durationMinutes = payload.durationMinutes ?? DEFAULT_DURATION_MINUTES;
49
+ const start = allDay ? startOfDay(parsedStart) : parsedStart;
50
+ const end = allDay ? endOfDay(parsedStart) : addMinutes(parsedStart, durationMinutes);
51
+ const location = payload.location ?? null;
52
+ const platform = detectPlatform(location);
53
+ return {
54
+ id: payload.id,
55
+ title: payload.title ?? "",
56
+ interactionType: payload.interactionType,
57
+ category: categoryOf(payload.interactionType),
58
+ status: narrowStatus(payload.status),
59
+ start,
60
+ end,
61
+ allDay,
62
+ location,
63
+ platform,
64
+ locationKind: detectLocationKind(location, platform),
65
+ participants: mapParticipants(payload),
66
+ ownerUserId: payload.ownerUserId ?? null,
67
+ entityId: payload.entityId ?? null,
68
+ dealId: payload.dealId ?? null,
69
+ color: payload.appearanceColor ?? typeColorByType[payload.interactionType] ?? null,
70
+ isRecurringOccurrence: false,
71
+ updatedAt: payload.updatedAt ?? null,
72
+ raw: payload
73
+ };
74
+ }
75
+ export {
76
+ detectPlatform,
77
+ mapInteractionToCalendarItem
78
+ };
79
+ //# sourceMappingURL=mapItem.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/lib/calendar/mapItem.ts"],
4
+ "sourcesContent": ["import { addMinutes } from 'date-fns/addMinutes'\nimport { endOfDay } from 'date-fns/endOfDay'\nimport { startOfDay } from 'date-fns/startOfDay'\nimport type {\n CalendarInteractionPayload,\n CalendarItem,\n CalendarItemStatus,\n CalendarLocationKind,\n CalendarParticipant,\n CalendarPlatform,\n} from '../../components/calendar/types'\nimport { categoryOf } from './categories'\n\nconst DEFAULT_DURATION_MINUTES = 30\n\nfunction narrowStatus(status: string): CalendarItemStatus {\n if (status === 'done') return 'done'\n if (status === 'canceled') return 'canceled'\n return 'planned'\n}\n\nexport function detectPlatform(location: string | null): CalendarPlatform | null {\n if (!location) return null\n const normalized = location.toLowerCase()\n if (normalized.includes('zoom.us') || normalized.includes('zoom')) return 'zoom'\n if (normalized.includes('meet.google') || normalized.includes('on meet')) return 'meet'\n if (normalized.includes('slack')) return 'slack'\n if (normalized.includes('teams')) return 'teams'\n return null\n}\n\nfunction detectLocationKind(location: string | null, platform: CalendarPlatform | null): CalendarLocationKind | null {\n if (!location) return null\n const normalized = location.trim().toLowerCase()\n if (normalized.startsWith('http') || normalized.startsWith('www')) return 'url'\n if (platform) return 'platform'\n return 'venue'\n}\n\nfunction mapParticipants(payload: CalendarInteractionPayload): CalendarParticipant[] {\n const participants = payload.participants\n if (!Array.isArray(participants)) return []\n const seen = new Set<string>()\n const mapped: CalendarParticipant[] = []\n for (const participant of participants) {\n if (seen.has(participant.userId)) continue\n seen.add(participant.userId)\n const entry: CalendarParticipant = { userId: participant.userId }\n if (typeof participant.name === 'string') entry.name = participant.name\n if (typeof participant.email === 'string') entry.email = participant.email\n mapped.push(entry)\n }\n return mapped\n}\n\nexport function mapInteractionToCalendarItem(\n payload: CalendarInteractionPayload,\n typeColorByType: Record<string, string | null>,\n): CalendarItem | null {\n const effectiveStartRaw = payload.occurredAt ?? payload.scheduledAt ?? null\n if (!effectiveStartRaw) return null\n const parsedStart = new Date(effectiveStartRaw)\n if (Number.isNaN(parsedStart.getTime())) return null\n\n const allDay = payload.allDay === true\n const durationMinutes = payload.durationMinutes ?? DEFAULT_DURATION_MINUTES\n const start = allDay ? startOfDay(parsedStart) : parsedStart\n const end = allDay ? endOfDay(parsedStart) : addMinutes(parsedStart, durationMinutes)\n\n const location = payload.location ?? null\n const platform = detectPlatform(location)\n\n return {\n id: payload.id,\n title: payload.title ?? '',\n interactionType: payload.interactionType,\n category: categoryOf(payload.interactionType),\n status: narrowStatus(payload.status),\n start,\n end,\n allDay,\n location,\n platform,\n locationKind: detectLocationKind(location, platform),\n participants: mapParticipants(payload),\n ownerUserId: payload.ownerUserId ?? null,\n entityId: payload.entityId ?? null,\n dealId: payload.dealId ?? null,\n color: payload.appearanceColor ?? typeColorByType[payload.interactionType] ?? null,\n isRecurringOccurrence: false,\n updatedAt: payload.updatedAt ?? null,\n raw: payload,\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAS3B,SAAS,kBAAkB;AAE3B,MAAM,2BAA2B;AAEjC,SAAS,aAAa,QAAoC;AACxD,MAAI,WAAW,OAAQ,QAAO;AAC9B,MAAI,WAAW,WAAY,QAAO;AAClC,SAAO;AACT;AAEO,SAAS,eAAe,UAAkD;AAC/E,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,aAAa,SAAS,YAAY;AACxC,MAAI,WAAW,SAAS,SAAS,KAAK,WAAW,SAAS,MAAM,EAAG,QAAO;AAC1E,MAAI,WAAW,SAAS,aAAa,KAAK,WAAW,SAAS,SAAS,EAAG,QAAO;AACjF,MAAI,WAAW,SAAS,OAAO,EAAG,QAAO;AACzC,MAAI,WAAW,SAAS,OAAO,EAAG,QAAO;AACzC,SAAO;AACT;AAEA,SAAS,mBAAmB,UAAyB,UAAgE;AACnH,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,aAAa,SAAS,KAAK,EAAE,YAAY;AAC/C,MAAI,WAAW,WAAW,MAAM,KAAK,WAAW,WAAW,KAAK,EAAG,QAAO;AAC1E,MAAI,SAAU,QAAO;AACrB,SAAO;AACT;AAEA,SAAS,gBAAgB,SAA4D;AACnF,QAAM,eAAe,QAAQ;AAC7B,MAAI,CAAC,MAAM,QAAQ,YAAY,EAAG,QAAO,CAAC;AAC1C,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAgC,CAAC;AACvC,aAAW,eAAe,cAAc;AACtC,QAAI,KAAK,IAAI,YAAY,MAAM,EAAG;AAClC,SAAK,IAAI,YAAY,MAAM;AAC3B,UAAM,QAA6B,EAAE,QAAQ,YAAY,OAAO;AAChE,QAAI,OAAO,YAAY,SAAS,SAAU,OAAM,OAAO,YAAY;AACnE,QAAI,OAAO,YAAY,UAAU,SAAU,OAAM,QAAQ,YAAY;AACrE,WAAO,KAAK,KAAK;AAAA,EACnB;AACA,SAAO;AACT;AAEO,SAAS,6BACd,SACA,iBACqB;AACrB,QAAM,oBAAoB,QAAQ,cAAc,QAAQ,eAAe;AACvE,MAAI,CAAC,kBAAmB,QAAO;AAC/B,QAAM,cAAc,IAAI,KAAK,iBAAiB;AAC9C,MAAI,OAAO,MAAM,YAAY,QAAQ,CAAC,EAAG,QAAO;AAEhD,QAAM,SAAS,QAAQ,WAAW;AAClC,QAAM,kBAAkB,QAAQ,mBAAmB;AACnD,QAAM,QAAQ,SAAS,WAAW,WAAW,IAAI;AACjD,QAAM,MAAM,SAAS,SAAS,WAAW,IAAI,WAAW,aAAa,eAAe;AAEpF,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,WAAW,eAAe,QAAQ;AAExC,SAAO;AAAA,IACL,IAAI,QAAQ;AAAA,IACZ,OAAO,QAAQ,SAAS;AAAA,IACxB,iBAAiB,QAAQ;AAAA,IACzB,UAAU,WAAW,QAAQ,eAAe;AAAA,IAC5C,QAAQ,aAAa,QAAQ,MAAM;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,mBAAmB,UAAU,QAAQ;AAAA,IACnD,cAAc,gBAAgB,OAAO;AAAA,IACrC,aAAa,QAAQ,eAAe;AAAA,IACpC,UAAU,QAAQ,YAAY;AAAA,IAC9B,QAAQ,QAAQ,UAAU;AAAA,IAC1B,OAAO,QAAQ,mBAAmB,gBAAgB,QAAQ,eAAe,KAAK;AAAA,IAC9E,uBAAuB;AAAA,IACvB,WAAW,QAAQ,aAAa;AAAA,IAChC,KAAK;AAAA,EACP;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,71 @@
1
+ const CONFLICT_SCOPES = ["mine", "all"];
2
+ const MAX_EVENT_CATEGORIES = 8;
3
+ const MAX_ACTIVITY_TYPES = 6;
4
+ const DEFAULT_CALENDAR_PREFERENCES = {
5
+ showWeekends: false,
6
+ conflictWarnings: true,
7
+ conflictScope: "mine",
8
+ showCrmActivities: true,
9
+ aiSummaries: true,
10
+ eventCategories: [],
11
+ activityTypes: []
12
+ };
13
+ const CALENDAR_PREFERENCES_STORAGE_PREFIX = "om.customers.calendar.preferences.v1";
14
+ function calendarPreferencesStorageKey(scopeKey) {
15
+ return `${CALENDAR_PREFERENCES_STORAGE_PREFIX}:${scopeKey}`;
16
+ }
17
+ function normalizeCalendarTagList(value, max) {
18
+ if (!Array.isArray(value)) return [];
19
+ const seen = /* @__PURE__ */ new Set();
20
+ const result = [];
21
+ for (const entry of value) {
22
+ if (typeof entry !== "string") continue;
23
+ const trimmed = entry.trim();
24
+ if (!trimmed || seen.has(trimmed)) continue;
25
+ seen.add(trimmed);
26
+ result.push(trimmed);
27
+ if (result.length >= max) break;
28
+ }
29
+ return result;
30
+ }
31
+ function readConflictScope(value, fallback) {
32
+ return value === "mine" || value === "all" ? value : fallback;
33
+ }
34
+ function mergeCalendarPreferences(stored) {
35
+ if (!stored || typeof stored !== "object") return { ...DEFAULT_CALENDAR_PREFERENCES };
36
+ const record = stored;
37
+ const readBoolean = (key, fallback) => typeof record[key] === "boolean" ? record[key] : fallback;
38
+ return {
39
+ showWeekends: readBoolean("showWeekends", DEFAULT_CALENDAR_PREFERENCES.showWeekends),
40
+ conflictWarnings: readBoolean("conflictWarnings", DEFAULT_CALENDAR_PREFERENCES.conflictWarnings),
41
+ conflictScope: readConflictScope(record.conflictScope, DEFAULT_CALENDAR_PREFERENCES.conflictScope),
42
+ showCrmActivities: readBoolean("showCrmActivities", DEFAULT_CALENDAR_PREFERENCES.showCrmActivities),
43
+ aiSummaries: readBoolean("aiSummaries", DEFAULT_CALENDAR_PREFERENCES.aiSummaries),
44
+ eventCategories: normalizeCalendarTagList(record.eventCategories, MAX_EVENT_CATEGORIES),
45
+ activityTypes: normalizeCalendarTagList(record.activityTypes, MAX_ACTIVITY_TYPES)
46
+ };
47
+ }
48
+ function parseStoredCalendarPreferences(raw) {
49
+ if (!raw) return { ...DEFAULT_CALENDAR_PREFERENCES };
50
+ try {
51
+ return mergeCalendarPreferences(JSON.parse(raw));
52
+ } catch {
53
+ return { ...DEFAULT_CALENDAR_PREFERENCES };
54
+ }
55
+ }
56
+ function calendarPreferencesEqual(first, second) {
57
+ return first.showWeekends === second.showWeekends && first.conflictWarnings === second.conflictWarnings && first.conflictScope === second.conflictScope && first.showCrmActivities === second.showCrmActivities && first.aiSummaries === second.aiSummaries && first.eventCategories.length === second.eventCategories.length && first.eventCategories.every((value, index) => value === second.eventCategories[index]) && first.activityTypes.length === second.activityTypes.length && first.activityTypes.every((value, index) => value === second.activityTypes[index]);
58
+ }
59
+ export {
60
+ CALENDAR_PREFERENCES_STORAGE_PREFIX,
61
+ CONFLICT_SCOPES,
62
+ DEFAULT_CALENDAR_PREFERENCES,
63
+ MAX_ACTIVITY_TYPES,
64
+ MAX_EVENT_CATEGORIES,
65
+ calendarPreferencesEqual,
66
+ calendarPreferencesStorageKey,
67
+ mergeCalendarPreferences,
68
+ normalizeCalendarTagList,
69
+ parseStoredCalendarPreferences
70
+ };
71
+ //# sourceMappingURL=preferences.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/lib/calendar/preferences.ts"],
4
+ "sourcesContent": ["// Whose overlaps the calendar flags as conflicts:\n// - 'mine': only when the current user is an actor (owner/participant) in BOTH\n// overlapping events \u2014 i.e. the current user is personally double-booked.\n// - 'all': any two visible org events that share an actor, even when the current\n// user is in neither (team-wide scheduling awareness).\nexport type ConflictScope = 'mine' | 'all'\n\nexport const CONFLICT_SCOPES: ConflictScope[] = ['mine', 'all']\n\nexport type CalendarPreferences = {\n showWeekends: boolean\n conflictWarnings: boolean\n conflictScope: ConflictScope\n showCrmActivities: boolean\n aiSummaries: boolean\n eventCategories: string[]\n activityTypes: string[]\n}\n\nexport const MAX_EVENT_CATEGORIES = 8\nexport const MAX_ACTIVITY_TYPES = 6\n\nexport const DEFAULT_CALENDAR_PREFERENCES: CalendarPreferences = {\n showWeekends: false,\n conflictWarnings: true,\n conflictScope: 'mine',\n showCrmActivities: true,\n aiSummaries: true,\n eventCategories: [],\n activityTypes: [],\n}\n\nexport const CALENDAR_PREFERENCES_STORAGE_PREFIX = 'om.customers.calendar.preferences.v1'\n\nexport function calendarPreferencesStorageKey(scopeKey: string): string {\n return `${CALENDAR_PREFERENCES_STORAGE_PREFIX}:${scopeKey}`\n}\n\nexport function normalizeCalendarTagList(value: unknown, max: number): string[] {\n if (!Array.isArray(value)) return []\n const seen = new Set<string>()\n const result: string[] = []\n for (const entry of value) {\n if (typeof entry !== 'string') continue\n const trimmed = entry.trim()\n if (!trimmed || seen.has(trimmed)) continue\n seen.add(trimmed)\n result.push(trimmed)\n if (result.length >= max) break\n }\n return result\n}\n\nfunction readConflictScope(value: unknown, fallback: ConflictScope): ConflictScope {\n return value === 'mine' || value === 'all' ? value : fallback\n}\n\nexport function mergeCalendarPreferences(stored: unknown): CalendarPreferences {\n if (!stored || typeof stored !== 'object') return { ...DEFAULT_CALENDAR_PREFERENCES }\n const record = stored as Record<string, unknown>\n const readBoolean = (key: keyof CalendarPreferences, fallback: boolean): boolean =>\n typeof record[key] === 'boolean' ? (record[key] as boolean) : fallback\n return {\n showWeekends: readBoolean('showWeekends', DEFAULT_CALENDAR_PREFERENCES.showWeekends),\n conflictWarnings: readBoolean('conflictWarnings', DEFAULT_CALENDAR_PREFERENCES.conflictWarnings),\n conflictScope: readConflictScope(record.conflictScope, DEFAULT_CALENDAR_PREFERENCES.conflictScope),\n showCrmActivities: readBoolean('showCrmActivities', DEFAULT_CALENDAR_PREFERENCES.showCrmActivities),\n aiSummaries: readBoolean('aiSummaries', DEFAULT_CALENDAR_PREFERENCES.aiSummaries),\n eventCategories: normalizeCalendarTagList(record.eventCategories, MAX_EVENT_CATEGORIES),\n activityTypes: normalizeCalendarTagList(record.activityTypes, MAX_ACTIVITY_TYPES),\n }\n}\n\nexport function parseStoredCalendarPreferences(raw: string | null): CalendarPreferences {\n if (!raw) return { ...DEFAULT_CALENDAR_PREFERENCES }\n try {\n return mergeCalendarPreferences(JSON.parse(raw))\n } catch {\n return { ...DEFAULT_CALENDAR_PREFERENCES }\n }\n}\n\nexport function calendarPreferencesEqual(first: CalendarPreferences, second: CalendarPreferences): boolean {\n return (\n first.showWeekends === second.showWeekends &&\n first.conflictWarnings === second.conflictWarnings &&\n first.conflictScope === second.conflictScope &&\n first.showCrmActivities === second.showCrmActivities &&\n first.aiSummaries === second.aiSummaries &&\n first.eventCategories.length === second.eventCategories.length &&\n first.eventCategories.every((value, index) => value === second.eventCategories[index]) &&\n first.activityTypes.length === second.activityTypes.length &&\n first.activityTypes.every((value, index) => value === second.activityTypes[index])\n )\n}\n"],
5
+ "mappings": "AAOO,MAAM,kBAAmC,CAAC,QAAQ,KAAK;AAYvD,MAAM,uBAAuB;AAC7B,MAAM,qBAAqB;AAE3B,MAAM,+BAAoD;AAAA,EAC/D,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,iBAAiB,CAAC;AAAA,EAClB,eAAe,CAAC;AAClB;AAEO,MAAM,sCAAsC;AAE5C,SAAS,8BAA8B,UAA0B;AACtE,SAAO,GAAG,mCAAmC,IAAI,QAAQ;AAC3D;AAEO,SAAS,yBAAyB,OAAgB,KAAuB;AAC9E,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAmB,CAAC;AAC1B,aAAW,SAAS,OAAO;AACzB,QAAI,OAAO,UAAU,SAAU;AAC/B,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,WAAW,KAAK,IAAI,OAAO,EAAG;AACnC,SAAK,IAAI,OAAO;AAChB,WAAO,KAAK,OAAO;AACnB,QAAI,OAAO,UAAU,IAAK;AAAA,EAC5B;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,OAAgB,UAAwC;AACjF,SAAO,UAAU,UAAU,UAAU,QAAQ,QAAQ;AACvD;AAEO,SAAS,yBAAyB,QAAsC;AAC7E,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO,EAAE,GAAG,6BAA6B;AACpF,QAAM,SAAS;AACf,QAAM,cAAc,CAAC,KAAgC,aACnD,OAAO,OAAO,GAAG,MAAM,YAAa,OAAO,GAAG,IAAgB;AAChE,SAAO;AAAA,IACL,cAAc,YAAY,gBAAgB,6BAA6B,YAAY;AAAA,IACnF,kBAAkB,YAAY,oBAAoB,6BAA6B,gBAAgB;AAAA,IAC/F,eAAe,kBAAkB,OAAO,eAAe,6BAA6B,aAAa;AAAA,IACjG,mBAAmB,YAAY,qBAAqB,6BAA6B,iBAAiB;AAAA,IAClG,aAAa,YAAY,eAAe,6BAA6B,WAAW;AAAA,IAChF,iBAAiB,yBAAyB,OAAO,iBAAiB,oBAAoB;AAAA,IACtF,eAAe,yBAAyB,OAAO,eAAe,kBAAkB;AAAA,EAClF;AACF;AAEO,SAAS,+BAA+B,KAAyC;AACtF,MAAI,CAAC,IAAK,QAAO,EAAE,GAAG,6BAA6B;AACnD,MAAI;AACF,WAAO,yBAAyB,KAAK,MAAM,GAAG,CAAC;AAAA,EACjD,QAAQ;AACN,WAAO,EAAE,GAAG,6BAA6B;AAAA,EAC3C;AACF;AAEO,SAAS,yBAAyB,OAA4B,QAAsC;AACzG,SACE,MAAM,iBAAiB,OAAO,gBAC9B,MAAM,qBAAqB,OAAO,oBAClC,MAAM,kBAAkB,OAAO,iBAC/B,MAAM,sBAAsB,OAAO,qBACnC,MAAM,gBAAgB,OAAO,eAC7B,MAAM,gBAAgB,WAAW,OAAO,gBAAgB,UACxD,MAAM,gBAAgB,MAAM,CAAC,OAAO,UAAU,UAAU,OAAO,gBAAgB,KAAK,CAAC,KACrF,MAAM,cAAc,WAAW,OAAO,cAAc,UACpD,MAAM,cAAc,MAAM,CAAC,OAAO,UAAU,UAAU,OAAO,cAAc,KAAK,CAAC;AAErF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,46 @@
1
+ import { addDays } from "date-fns/addDays";
2
+ import { addMonths } from "date-fns/addMonths";
3
+ import { addWeeks } from "date-fns/addWeeks";
4
+ import { endOfDay } from "date-fns/endOfDay";
5
+ import { endOfMonth } from "date-fns/endOfMonth";
6
+ import { endOfWeek } from "date-fns/endOfWeek";
7
+ import { startOfDay } from "date-fns/startOfDay";
8
+ import { startOfMonth } from "date-fns/startOfMonth";
9
+ import { startOfWeek } from "date-fns/startOfWeek";
10
+ const MONDAY_WEEK = { weekStartsOn: 1 };
11
+ function getVisibleRange(view, anchor, agendaHorizonDays) {
12
+ switch (view) {
13
+ case "day":
14
+ return { from: startOfDay(anchor), to: endOfDay(anchor) };
15
+ case "week":
16
+ return { from: startOfWeek(anchor, MONDAY_WEEK), to: endOfWeek(anchor, MONDAY_WEEK) };
17
+ case "month":
18
+ return {
19
+ from: startOfWeek(startOfMonth(anchor), MONDAY_WEEK),
20
+ to: endOfWeek(endOfMonth(anchor), MONDAY_WEEK)
21
+ };
22
+ case "agenda":
23
+ return { from: startOfDay(anchor), to: endOfDay(addDays(anchor, agendaHorizonDays)) };
24
+ }
25
+ }
26
+ function getFetchWindow(range) {
27
+ return { from: addDays(range.from, -1), to: range.to };
28
+ }
29
+ function shiftAnchor(view, anchor, direction) {
30
+ switch (view) {
31
+ case "day":
32
+ return addDays(anchor, direction);
33
+ case "week":
34
+ return addWeeks(anchor, direction);
35
+ case "month":
36
+ return addMonths(anchor, direction);
37
+ case "agenda":
38
+ return addDays(anchor, direction * 7);
39
+ }
40
+ }
41
+ export {
42
+ getFetchWindow,
43
+ getVisibleRange,
44
+ shiftAnchor
45
+ };
46
+ //# sourceMappingURL=range.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/lib/calendar/range.ts"],
4
+ "sourcesContent": ["import { addDays } from 'date-fns/addDays'\nimport { addMonths } from 'date-fns/addMonths'\nimport { addWeeks } from 'date-fns/addWeeks'\nimport { endOfDay } from 'date-fns/endOfDay'\nimport { endOfMonth } from 'date-fns/endOfMonth'\nimport { endOfWeek } from 'date-fns/endOfWeek'\nimport { startOfDay } from 'date-fns/startOfDay'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfWeek } from 'date-fns/startOfWeek'\nimport type { CalendarRange, CalendarView } from '../../components/calendar/types'\n\nconst MONDAY_WEEK = { weekStartsOn: 1 as const }\n\nexport function getVisibleRange(view: CalendarView, anchor: Date, agendaHorizonDays: number): CalendarRange {\n switch (view) {\n case 'day':\n return { from: startOfDay(anchor), to: endOfDay(anchor) }\n case 'week':\n return { from: startOfWeek(anchor, MONDAY_WEEK), to: endOfWeek(anchor, MONDAY_WEEK) }\n case 'month':\n return {\n from: startOfWeek(startOfMonth(anchor), MONDAY_WEEK),\n to: endOfWeek(endOfMonth(anchor), MONDAY_WEEK),\n }\n case 'agenda':\n return { from: startOfDay(anchor), to: endOfDay(addDays(anchor, agendaHorizonDays)) }\n }\n}\n\nexport function getFetchWindow(range: CalendarRange): CalendarRange {\n return { from: addDays(range.from, -1), to: range.to }\n}\n\nexport function shiftAnchor(view: CalendarView, anchor: Date, direction: 1 | -1): Date {\n switch (view) {\n case 'day':\n return addDays(anchor, direction)\n case 'week':\n return addWeeks(anchor, direction)\n case 'month':\n return addMonths(anchor, direction)\n case 'agenda':\n return addDays(anchor, direction * 7)\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAG5B,MAAM,cAAc,EAAE,cAAc,EAAW;AAExC,SAAS,gBAAgB,MAAoB,QAAc,mBAA0C;AAC1G,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,EAAE,MAAM,WAAW,MAAM,GAAG,IAAI,SAAS,MAAM,EAAE;AAAA,IAC1D,KAAK;AACH,aAAO,EAAE,MAAM,YAAY,QAAQ,WAAW,GAAG,IAAI,UAAU,QAAQ,WAAW,EAAE;AAAA,IACtF,KAAK;AACH,aAAO;AAAA,QACL,MAAM,YAAY,aAAa,MAAM,GAAG,WAAW;AAAA,QACnD,IAAI,UAAU,WAAW,MAAM,GAAG,WAAW;AAAA,MAC/C;AAAA,IACF,KAAK;AACH,aAAO,EAAE,MAAM,WAAW,MAAM,GAAG,IAAI,SAAS,QAAQ,QAAQ,iBAAiB,CAAC,EAAE;AAAA,EACxF;AACF;AAEO,SAAS,eAAe,OAAqC;AAClE,SAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,EAAE,GAAG,IAAI,MAAM,GAAG;AACvD;AAEO,SAAS,YAAY,MAAoB,QAAc,WAAyB;AACrF,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,QAAQ,QAAQ,SAAS;AAAA,IAClC,KAAK;AACH,aAAO,SAAS,QAAQ,SAAS;AAAA,IACnC,KAAK;AACH,aAAO,UAAU,QAAQ,SAAS;AAAA,IACpC,KAAK;AACH,aAAO,QAAQ,QAAQ,YAAY,CAAC;AAAA,EACxC;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,113 @@
1
+ import { addDays } from "date-fns/addDays";
2
+ const MAX_OCCURRENCES_PER_WINDOW = 100;
3
+ const WEEKDAY_TOKENS = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
4
+ const UNTIL_PATTERN = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z$/;
5
+ function parseUntil(value) {
6
+ const match = UNTIL_PATTERN.exec(value);
7
+ if (!match) return null;
8
+ const [, year, month, day, hours, minutes, seconds] = match;
9
+ const parsed = new Date(
10
+ Date.UTC(Number(year), Number(month) - 1, Number(day), Number(hours), Number(minutes), Number(seconds))
11
+ );
12
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
13
+ }
14
+ function parseRecurrenceRule(rule) {
15
+ const parts = rule.split(";").map((part) => part.trim()).filter((part) => part.length > 0);
16
+ if (parts.length === 0) return null;
17
+ let freq = null;
18
+ let byDay = null;
19
+ let count = null;
20
+ let until = null;
21
+ for (const part of parts) {
22
+ const separatorIndex = part.indexOf("=");
23
+ if (separatorIndex <= 0) return null;
24
+ const key = part.slice(0, separatorIndex).toUpperCase();
25
+ const value = part.slice(separatorIndex + 1);
26
+ if (key === "FREQ") {
27
+ if (value !== "DAILY" && value !== "WEEKLY") return null;
28
+ freq = value;
29
+ } else if (key === "BYDAY") {
30
+ const tokens = value.split(",").map((token) => token.trim().toUpperCase()).filter((token) => token.length > 0);
31
+ if (tokens.length === 0) return null;
32
+ const weekdays = [];
33
+ for (const token of tokens) {
34
+ const weekday = WEEKDAY_TOKENS.indexOf(token);
35
+ if (weekday === -1) return null;
36
+ weekdays.push(weekday);
37
+ }
38
+ byDay = weekdays;
39
+ } else if (key === "COUNT") {
40
+ const parsedCount = Number(value);
41
+ if (!Number.isInteger(parsedCount) || parsedCount < 1) return null;
42
+ count = parsedCount;
43
+ } else if (key === "UNTIL") {
44
+ const parsedUntil = parseUntil(value);
45
+ if (!parsedUntil) return null;
46
+ until = parsedUntil;
47
+ } else {
48
+ return null;
49
+ }
50
+ }
51
+ if (!freq) return null;
52
+ return { freq, byDay, count, until };
53
+ }
54
+ function parseRecurrenceEndTime(rawRecurrenceEnd) {
55
+ if (typeof rawRecurrenceEnd !== "string" || rawRecurrenceEnd.length === 0) return null;
56
+ const parsed = new Date(rawRecurrenceEnd);
57
+ if (Number.isNaN(parsed.getTime())) return null;
58
+ const endOfDayLocal = new Date(
59
+ parsed.getUTCFullYear(),
60
+ parsed.getUTCMonth(),
61
+ parsed.getUTCDate(),
62
+ 23,
63
+ 59,
64
+ 59,
65
+ 999
66
+ );
67
+ return endOfDayLocal.getTime();
68
+ }
69
+ function occursOn(date, rule, seriesStartWeekday) {
70
+ if (rule.freq === "DAILY") return true;
71
+ const allowedWeekdays = rule.byDay ?? [seriesStartWeekday];
72
+ return allowedWeekdays.includes(date.getDay());
73
+ }
74
+ function expandOccurrences(item, range) {
75
+ const rawRule = item.raw.recurrenceRule;
76
+ if (typeof rawRule !== "string" || rawRule.trim().length === 0) return [item];
77
+ const rule = parseRecurrenceRule(rawRule);
78
+ if (!rule) return [item];
79
+ const durationMs = item.end.getTime() - item.start.getTime();
80
+ const recurrenceEndTime = parseRecurrenceEndTime(item.raw.recurrenceEnd);
81
+ const untilTime = rule.until ? rule.until.getTime() : null;
82
+ const seriesStartWeekday = item.start.getDay();
83
+ const occurrences = [];
84
+ let occurrenceIndex = 0;
85
+ let cursor = new Date(item.start);
86
+ while (cursor.getTime() <= range.to.getTime()) {
87
+ if (untilTime !== null && cursor.getTime() > untilTime) break;
88
+ if (recurrenceEndTime !== null && cursor.getTime() > recurrenceEndTime) break;
89
+ if (occursOn(cursor, rule, seriesStartWeekday)) {
90
+ if (rule.count !== null && occurrenceIndex >= rule.count) break;
91
+ const occurrenceStart = new Date(cursor);
92
+ const occurrenceEnd = new Date(occurrenceStart.getTime() + durationMs);
93
+ if (occurrenceStart.getTime() <= range.to.getTime() && occurrenceEnd.getTime() > range.from.getTime()) {
94
+ occurrences.push({
95
+ ...item,
96
+ id: `${item.id}:${occurrenceIndex}`,
97
+ start: occurrenceStart,
98
+ end: occurrenceEnd,
99
+ isRecurringOccurrence: true
100
+ });
101
+ if (occurrences.length >= MAX_OCCURRENCES_PER_WINDOW) break;
102
+ }
103
+ occurrenceIndex += 1;
104
+ }
105
+ cursor = addDays(cursor, 1);
106
+ }
107
+ return occurrences;
108
+ }
109
+ export {
110
+ expandOccurrences,
111
+ parseRecurrenceRule
112
+ };
113
+ //# sourceMappingURL=recurrence.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/lib/calendar/recurrence.ts"],
4
+ "sourcesContent": ["import { addDays } from 'date-fns/addDays'\nimport type { CalendarItem, CalendarRange } from '../../components/calendar/types'\n\nconst MAX_OCCURRENCES_PER_WINDOW = 100\n\nconst WEEKDAY_TOKENS = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'] as const\n\nconst UNTIL_PATTERN = /^(\\d{4})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})(\\d{2})Z$/\n\nexport type ParsedRecurrenceRule = {\n freq: 'DAILY' | 'WEEKLY'\n byDay: number[] | null\n count: number | null\n until: Date | null\n}\n\nfunction parseUntil(value: string): Date | null {\n const match = UNTIL_PATTERN.exec(value)\n if (!match) return null\n const [, year, month, day, hours, minutes, seconds] = match\n const parsed = new Date(\n Date.UTC(Number(year), Number(month) - 1, Number(day), Number(hours), Number(minutes), Number(seconds)),\n )\n return Number.isNaN(parsed.getTime()) ? null : parsed\n}\n\nexport function parseRecurrenceRule(rule: string): ParsedRecurrenceRule | null {\n const parts = rule\n .split(';')\n .map((part) => part.trim())\n .filter((part) => part.length > 0)\n if (parts.length === 0) return null\n\n let freq: ParsedRecurrenceRule['freq'] | null = null\n let byDay: number[] | null = null\n let count: number | null = null\n let until: Date | null = null\n\n for (const part of parts) {\n const separatorIndex = part.indexOf('=')\n if (separatorIndex <= 0) return null\n const key = part.slice(0, separatorIndex).toUpperCase()\n const value = part.slice(separatorIndex + 1)\n if (key === 'FREQ') {\n if (value !== 'DAILY' && value !== 'WEEKLY') return null\n freq = value\n } else if (key === 'BYDAY') {\n const tokens = value\n .split(',')\n .map((token) => token.trim().toUpperCase())\n .filter((token) => token.length > 0)\n if (tokens.length === 0) return null\n const weekdays: number[] = []\n for (const token of tokens) {\n const weekday = WEEKDAY_TOKENS.indexOf(token as (typeof WEEKDAY_TOKENS)[number])\n if (weekday === -1) return null\n weekdays.push(weekday)\n }\n byDay = weekdays\n } else if (key === 'COUNT') {\n const parsedCount = Number(value)\n if (!Number.isInteger(parsedCount) || parsedCount < 1) return null\n count = parsedCount\n } else if (key === 'UNTIL') {\n const parsedUntil = parseUntil(value)\n if (!parsedUntil) return null\n until = parsedUntil\n } else {\n return null\n }\n }\n\n if (!freq) return null\n return { freq, byDay, count, until }\n}\n\nfunction parseRecurrenceEndTime(rawRecurrenceEnd: string | null | undefined): number | null {\n if (typeof rawRecurrenceEnd !== 'string' || rawRecurrenceEnd.length === 0) return null\n const parsed = new Date(rawRecurrenceEnd)\n if (Number.isNaN(parsed.getTime())) return null\n const endOfDayLocal = new Date(\n parsed.getUTCFullYear(),\n parsed.getUTCMonth(),\n parsed.getUTCDate(),\n 23,\n 59,\n 59,\n 999,\n )\n return endOfDayLocal.getTime()\n}\n\nfunction occursOn(date: Date, rule: ParsedRecurrenceRule, seriesStartWeekday: number): boolean {\n if (rule.freq === 'DAILY') return true\n const allowedWeekdays = rule.byDay ?? [seriesStartWeekday]\n return allowedWeekdays.includes(date.getDay())\n}\n\nexport function expandOccurrences(item: CalendarItem, range: CalendarRange): CalendarItem[] {\n const rawRule = item.raw.recurrenceRule\n if (typeof rawRule !== 'string' || rawRule.trim().length === 0) return [item]\n const rule = parseRecurrenceRule(rawRule)\n if (!rule) return [item]\n\n const durationMs = item.end.getTime() - item.start.getTime()\n const recurrenceEndTime = parseRecurrenceEndTime(item.raw.recurrenceEnd)\n const untilTime = rule.until ? rule.until.getTime() : null\n const seriesStartWeekday = item.start.getDay()\n\n const occurrences: CalendarItem[] = []\n let occurrenceIndex = 0\n let cursor = new Date(item.start)\n\n while (cursor.getTime() <= range.to.getTime()) {\n if (untilTime !== null && cursor.getTime() > untilTime) break\n if (recurrenceEndTime !== null && cursor.getTime() > recurrenceEndTime) break\n if (occursOn(cursor, rule, seriesStartWeekday)) {\n if (rule.count !== null && occurrenceIndex >= rule.count) break\n const occurrenceStart = new Date(cursor)\n const occurrenceEnd = new Date(occurrenceStart.getTime() + durationMs)\n if (occurrenceStart.getTime() <= range.to.getTime() && occurrenceEnd.getTime() > range.from.getTime()) {\n occurrences.push({\n ...item,\n id: `${item.id}:${occurrenceIndex}`,\n start: occurrenceStart,\n end: occurrenceEnd,\n isRecurringOccurrence: true,\n })\n if (occurrences.length >= MAX_OCCURRENCES_PER_WINDOW) break\n }\n occurrenceIndex += 1\n }\n cursor = addDays(cursor, 1)\n }\n\n return occurrences\n}\n"],
5
+ "mappings": "AAAA,SAAS,eAAe;AAGxB,MAAM,6BAA6B;AAEnC,MAAM,iBAAiB,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAEhE,MAAM,gBAAgB;AAStB,SAAS,WAAW,OAA4B;AAC9C,QAAM,QAAQ,cAAc,KAAK,KAAK;AACtC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,CAAC,EAAE,MAAM,OAAO,KAAK,OAAO,SAAS,OAAO,IAAI;AACtD,QAAM,SAAS,IAAI;AAAA,IACjB,KAAK,IAAI,OAAO,IAAI,GAAG,OAAO,KAAK,IAAI,GAAG,OAAO,GAAG,GAAG,OAAO,KAAK,GAAG,OAAO,OAAO,GAAG,OAAO,OAAO,CAAC;AAAA,EACxG;AACA,SAAO,OAAO,MAAM,OAAO,QAAQ,CAAC,IAAI,OAAO;AACjD;AAEO,SAAS,oBAAoB,MAA2C;AAC7E,QAAM,QAAQ,KACX,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACnC,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,MAAI,OAA4C;AAChD,MAAI,QAAyB;AAC7B,MAAI,QAAuB;AAC3B,MAAI,QAAqB;AAEzB,aAAW,QAAQ,OAAO;AACxB,UAAM,iBAAiB,KAAK,QAAQ,GAAG;AACvC,QAAI,kBAAkB,EAAG,QAAO;AAChC,UAAM,MAAM,KAAK,MAAM,GAAG,cAAc,EAAE,YAAY;AACtD,UAAM,QAAQ,KAAK,MAAM,iBAAiB,CAAC;AAC3C,QAAI,QAAQ,QAAQ;AAClB,UAAI,UAAU,WAAW,UAAU,SAAU,QAAO;AACpD,aAAO;AAAA,IACT,WAAW,QAAQ,SAAS;AAC1B,YAAM,SAAS,MACZ,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,EAAE,YAAY,CAAC,EACzC,OAAO,CAAC,UAAU,MAAM,SAAS,CAAC;AACrC,UAAI,OAAO,WAAW,EAAG,QAAO;AAChC,YAAM,WAAqB,CAAC;AAC5B,iBAAW,SAAS,QAAQ;AAC1B,cAAM,UAAU,eAAe,QAAQ,KAAwC;AAC/E,YAAI,YAAY,GAAI,QAAO;AAC3B,iBAAS,KAAK,OAAO;AAAA,MACvB;AACA,cAAQ;AAAA,IACV,WAAW,QAAQ,SAAS;AAC1B,YAAM,cAAc,OAAO,KAAK;AAChC,UAAI,CAAC,OAAO,UAAU,WAAW,KAAK,cAAc,EAAG,QAAO;AAC9D,cAAQ;AAAA,IACV,WAAW,QAAQ,SAAS;AAC1B,YAAM,cAAc,WAAW,KAAK;AACpC,UAAI,CAAC,YAAa,QAAO;AACzB,cAAQ;AAAA,IACV,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,EAAE,MAAM,OAAO,OAAO,MAAM;AACrC;AAEA,SAAS,uBAAuB,kBAA4D;AAC1F,MAAI,OAAO,qBAAqB,YAAY,iBAAiB,WAAW,EAAG,QAAO;AAClF,QAAM,SAAS,IAAI,KAAK,gBAAgB;AACxC,MAAI,OAAO,MAAM,OAAO,QAAQ,CAAC,EAAG,QAAO;AAC3C,QAAM,gBAAgB,IAAI;AAAA,IACxB,OAAO,eAAe;AAAA,IACtB,OAAO,YAAY;AAAA,IACnB,OAAO,WAAW;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,cAAc,QAAQ;AAC/B;AAEA,SAAS,SAAS,MAAY,MAA4B,oBAAqC;AAC7F,MAAI,KAAK,SAAS,QAAS,QAAO;AAClC,QAAM,kBAAkB,KAAK,SAAS,CAAC,kBAAkB;AACzD,SAAO,gBAAgB,SAAS,KAAK,OAAO,CAAC;AAC/C;AAEO,SAAS,kBAAkB,MAAoB,OAAsC;AAC1F,QAAM,UAAU,KAAK,IAAI;AACzB,MAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,EAAE,WAAW,EAAG,QAAO,CAAC,IAAI;AAC5E,QAAM,OAAO,oBAAoB,OAAO;AACxC,MAAI,CAAC,KAAM,QAAO,CAAC,IAAI;AAEvB,QAAM,aAAa,KAAK,IAAI,QAAQ,IAAI,KAAK,MAAM,QAAQ;AAC3D,QAAM,oBAAoB,uBAAuB,KAAK,IAAI,aAAa;AACvE,QAAM,YAAY,KAAK,QAAQ,KAAK,MAAM,QAAQ,IAAI;AACtD,QAAM,qBAAqB,KAAK,MAAM,OAAO;AAE7C,QAAM,cAA8B,CAAC;AACrC,MAAI,kBAAkB;AACtB,MAAI,SAAS,IAAI,KAAK,KAAK,KAAK;AAEhC,SAAO,OAAO,QAAQ,KAAK,MAAM,GAAG,QAAQ,GAAG;AAC7C,QAAI,cAAc,QAAQ,OAAO,QAAQ,IAAI,UAAW;AACxD,QAAI,sBAAsB,QAAQ,OAAO,QAAQ,IAAI,kBAAmB;AACxE,QAAI,SAAS,QAAQ,MAAM,kBAAkB,GAAG;AAC9C,UAAI,KAAK,UAAU,QAAQ,mBAAmB,KAAK,MAAO;AAC1D,YAAM,kBAAkB,IAAI,KAAK,MAAM;AACvC,YAAM,gBAAgB,IAAI,KAAK,gBAAgB,QAAQ,IAAI,UAAU;AACrE,UAAI,gBAAgB,QAAQ,KAAK,MAAM,GAAG,QAAQ,KAAK,cAAc,QAAQ,IAAI,MAAM,KAAK,QAAQ,GAAG;AACrG,oBAAY,KAAK;AAAA,UACf,GAAG;AAAA,UACH,IAAI,GAAG,KAAK,EAAE,IAAI,eAAe;AAAA,UACjC,OAAO;AAAA,UACP,KAAK;AAAA,UACL,uBAAuB;AAAA,QACzB,CAAC;AACD,YAAI,YAAY,UAAU,2BAA4B;AAAA,MACxD;AACA,yBAAmB;AAAA,IACrB;AACA,aAAS,QAAQ,QAAQ,CAAC;AAAA,EAC5B;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -64,11 +64,11 @@ class WidgetDataService {
64
64
  comparisonRange = getPreviousPeriod(dateRangeResolved, request.dateRange.preset);
65
65
  }
66
66
  }
67
- const mainResult = await this.executeQuery(request, dateRangeResolved);
68
- let comparisonResult;
69
- if (comparisonRange && request.dateRange) {
70
- comparisonResult = await this.executeQuery(request, comparisonRange);
71
- }
67
+ const shouldFetchComparison = Boolean(comparisonRange && request.dateRange);
68
+ const [mainResult, comparisonResult] = await Promise.all([
69
+ this.executeQuery(request, dateRangeResolved),
70
+ shouldFetchComparison && comparisonRange ? this.executeQuery(request, comparisonRange) : Promise.resolve(void 0)
71
+ ]);
72
72
  const response = {
73
73
  value: mainResult.value,
74
74
  data: mainResult.data,