@open-mercato/core 0.6.6-develop.6094.1.28b081ea16 → 0.6.6-develop.6121.1.5797a901b3

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,48 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { Button } from "@open-mercato/ui/primitives/button";
4
+ import { Kbd } from "@open-mercato/ui/primitives/kbd";
5
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
6
+ const CALENDAR_SHORTCUTS = [
7
+ { key: "T", labelKey: "customers.calendar.shortcuts.today", fallback: "Today" },
8
+ { key: "D", labelKey: "customers.calendar.shortcuts.dayView", fallback: "Day view" },
9
+ { key: "W", labelKey: "customers.calendar.shortcuts.week", fallback: "Week" },
10
+ { key: "M", labelKey: "customers.calendar.shortcuts.month", fallback: "Month" },
11
+ { key: "A", labelKey: "customers.calendar.shortcuts.agenda", fallback: "Agenda" },
12
+ { key: "N", labelKey: "customers.calendar.shortcuts.newEvent", fallback: "New event" },
13
+ { key: "/", labelKey: "customers.calendar.shortcuts.search", fallback: "Search" },
14
+ { key: "?", labelKey: "customers.calendar.shortcuts.help", fallback: "Shortcuts" }
15
+ ];
16
+ function CalendarFooter({ timezoneLabel, onOpenShortcuts }) {
17
+ const t = useT();
18
+ return /* @__PURE__ */ jsxs("footer", { className: "flex flex-wrap items-center gap-x-4 gap-y-1.5 border-t bg-muted/40 px-4 py-2", children: [
19
+ CALENDAR_SHORTCUTS.map((shortcut) => {
20
+ const legend = /* @__PURE__ */ jsxs(Fragment, { children: [
21
+ /* @__PURE__ */ jsx(Kbd, { children: shortcut.key }),
22
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: t(shortcut.labelKey, shortcut.fallback) })
23
+ ] });
24
+ if (shortcut.key === "?" && onOpenShortcuts) {
25
+ return /* @__PURE__ */ jsx(
26
+ Button,
27
+ {
28
+ type: "button",
29
+ variant: "ghost",
30
+ size: "sm",
31
+ className: "h-auto gap-1.5 p-0 font-normal hover:bg-transparent",
32
+ "aria-label": t("customers.calendar.shortcuts.title", "Keyboard shortcuts"),
33
+ onClick: onOpenShortcuts,
34
+ children: legend
35
+ },
36
+ shortcut.key
37
+ );
38
+ }
39
+ return /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-1.5", children: legend }, shortcut.key);
40
+ }),
41
+ /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs text-muted-foreground", children: timezoneLabel })
42
+ ] });
43
+ }
44
+ export {
45
+ CALENDAR_SHORTCUTS,
46
+ CalendarFooter
47
+ };
48
+ //# sourceMappingURL=CalendarFooter.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/components/calendar/CalendarFooter.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Kbd } from '@open-mercato/ui/primitives/kbd'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { CalendarFooterProps } from './types'\n\nexport const CALENDAR_SHORTCUTS: ReadonlyArray<{\n key: string\n labelKey: string\n fallback: string\n}> = [\n { key: 'T', labelKey: 'customers.calendar.shortcuts.today', fallback: 'Today' },\n { key: 'D', labelKey: 'customers.calendar.shortcuts.dayView', fallback: 'Day view' },\n { key: 'W', labelKey: 'customers.calendar.shortcuts.week', fallback: 'Week' },\n { key: 'M', labelKey: 'customers.calendar.shortcuts.month', fallback: 'Month' },\n { key: 'A', labelKey: 'customers.calendar.shortcuts.agenda', fallback: 'Agenda' },\n { key: 'N', labelKey: 'customers.calendar.shortcuts.newEvent', fallback: 'New event' },\n { key: '/', labelKey: 'customers.calendar.shortcuts.search', fallback: 'Search' },\n { key: '?', labelKey: 'customers.calendar.shortcuts.help', fallback: 'Shortcuts' },\n]\n\nexport function CalendarFooter({ timezoneLabel, onOpenShortcuts }: CalendarFooterProps) {\n const t = useT()\n return (\n <footer className=\"flex flex-wrap items-center gap-x-4 gap-y-1.5 border-t bg-muted/40 px-4 py-2\">\n {CALENDAR_SHORTCUTS.map((shortcut) => {\n const legend = (\n <>\n <Kbd>{shortcut.key}</Kbd>\n <span className=\"text-xs text-muted-foreground\">\n {t(shortcut.labelKey, shortcut.fallback)}\n </span>\n </>\n )\n if (shortcut.key === '?' && onOpenShortcuts) {\n return (\n <Button\n key={shortcut.key}\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto gap-1.5 p-0 font-normal hover:bg-transparent\"\n aria-label={t('customers.calendar.shortcuts.title', 'Keyboard shortcuts')}\n onClick={onOpenShortcuts}\n >\n {legend}\n </Button>\n )\n }\n return (\n <span key={shortcut.key} className=\"inline-flex items-center gap-1.5\">\n {legend}\n </span>\n )\n })}\n <span className=\"ml-auto text-xs text-muted-foreground\">{timezoneLabel}</span>\n </footer>\n )\n}\n"],
5
+ "mappings": ";AA6BU,mBACE,KADF;AA1BV,SAAS,cAAc;AACvB,SAAS,WAAW;AACpB,SAAS,YAAY;AAGd,MAAM,qBAIR;AAAA,EACH,EAAE,KAAK,KAAK,UAAU,sCAAsC,UAAU,QAAQ;AAAA,EAC9E,EAAE,KAAK,KAAK,UAAU,wCAAwC,UAAU,WAAW;AAAA,EACnF,EAAE,KAAK,KAAK,UAAU,qCAAqC,UAAU,OAAO;AAAA,EAC5E,EAAE,KAAK,KAAK,UAAU,sCAAsC,UAAU,QAAQ;AAAA,EAC9E,EAAE,KAAK,KAAK,UAAU,uCAAuC,UAAU,SAAS;AAAA,EAChF,EAAE,KAAK,KAAK,UAAU,yCAAyC,UAAU,YAAY;AAAA,EACrF,EAAE,KAAK,KAAK,UAAU,uCAAuC,UAAU,SAAS;AAAA,EAChF,EAAE,KAAK,KAAK,UAAU,qCAAqC,UAAU,YAAY;AACnF;AAEO,SAAS,eAAe,EAAE,eAAe,gBAAgB,GAAwB;AACtF,QAAM,IAAI,KAAK;AACf,SACE,qBAAC,YAAO,WAAU,gFACf;AAAA,uBAAmB,IAAI,CAAC,aAAa;AACpC,YAAM,SACJ,iCACE;AAAA,4BAAC,OAAK,mBAAS,KAAI;AAAA,QACnB,oBAAC,UAAK,WAAU,iCACb,YAAE,SAAS,UAAU,SAAS,QAAQ,GACzC;AAAA,SACF;AAEF,UAAI,SAAS,QAAQ,OAAO,iBAAiB;AAC3C,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,cAAY,EAAE,sCAAsC,oBAAoB;AAAA,YACxE,SAAS;AAAA,YAER;AAAA;AAAA,UARI,SAAS;AAAA,QAShB;AAAA,MAEJ;AACA,aACE,oBAAC,UAAwB,WAAU,oCAChC,oBADQ,SAAS,GAEpB;AAAA,IAEJ,CAAC;AAAA,IACD,oBAAC,UAAK,WAAU,yCAAyC,yBAAc;AAAA,KACzE;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Plus } from "lucide-react";
5
+ import { Button } from "@open-mercato/ui/primitives/button";
6
+ import { useLocale, useT } from "@open-mercato/shared/lib/i18n/context";
7
+ function CalendarHeader({ view, anchor, onNewEvent }) {
8
+ const t = useT();
9
+ const locale = useLocale();
10
+ const title = React.useMemo(() => {
11
+ if (view === "agenda") return t("customers.calendar.header.titleAgenda", "Upcoming");
12
+ if (view === "month") {
13
+ return new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }).format(anchor);
14
+ }
15
+ return new Intl.DateTimeFormat(locale, { month: "short", day: "2-digit", year: "numeric" }).format(anchor);
16
+ }, [view, anchor, locale, t]);
17
+ return /* @__PURE__ */ jsxs("header", { className: "flex items-center gap-3 border-b py-4", children: [
18
+ /* @__PURE__ */ jsx("h1", { className: "min-w-0 truncate text-xl font-semibold text-foreground", children: title }),
19
+ onNewEvent ? /* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 items-center", children: /* @__PURE__ */ jsxs(
20
+ Button,
21
+ {
22
+ type: "button",
23
+ onClick: onNewEvent,
24
+ "aria-label": t("customers.calendar.actions.newEvent", "New event"),
25
+ children: [
26
+ /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" }),
27
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: t("customers.calendar.actions.newEvent", "New event") })
28
+ ]
29
+ }
30
+ ) }) : null
31
+ ] });
32
+ }
33
+ export {
34
+ CalendarHeader
35
+ };
36
+ //# sourceMappingURL=CalendarHeader.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/components/calendar/CalendarHeader.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Plus } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { CalendarHeaderProps } from './types'\n\nexport function CalendarHeader({ view, anchor, onNewEvent }: CalendarHeaderProps) {\n const t = useT()\n const locale = useLocale()\n\n const title = React.useMemo(() => {\n if (view === 'agenda') return t('customers.calendar.header.titleAgenda', 'Upcoming')\n if (view === 'month') {\n return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(anchor)\n }\n return new Intl.DateTimeFormat(locale, { month: 'short', day: '2-digit', year: 'numeric' }).format(anchor)\n }, [view, anchor, locale, t])\n\n return (\n <header className=\"flex items-center gap-3 border-b py-4\">\n <h1 className=\"min-w-0 truncate text-xl font-semibold text-foreground\">{title}</h1>\n {onNewEvent ? (\n <div className=\"ml-auto flex shrink-0 items-center\">\n <Button\n type=\"button\"\n onClick={onNewEvent}\n aria-label={t('customers.calendar.actions.newEvent', 'New event')}\n >\n <Plus aria-hidden=\"true\" />\n <span className=\"hidden sm:inline\">\n {t('customers.calendar.actions.newEvent', 'New event')}\n </span>\n </Button>\n </div>\n ) : null}\n </header>\n )\n}\n"],
5
+ "mappings": ";AAsBM,cAGI,YAHJ;AApBN,YAAY,WAAW;AACvB,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,SAAS,WAAW,YAAY;AAGzB,SAAS,eAAe,EAAE,MAAM,QAAQ,WAAW,GAAwB;AAChF,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AAEzB,QAAM,QAAQ,MAAM,QAAQ,MAAM;AAChC,QAAI,SAAS,SAAU,QAAO,EAAE,yCAAyC,UAAU;AACnF,QAAI,SAAS,SAAS;AACpB,aAAO,IAAI,KAAK,eAAe,QAAQ,EAAE,OAAO,QAAQ,MAAM,UAAU,CAAC,EAAE,OAAO,MAAM;AAAA,IAC1F;AACA,WAAO,IAAI,KAAK,eAAe,QAAQ,EAAE,OAAO,SAAS,KAAK,WAAW,MAAM,UAAU,CAAC,EAAE,OAAO,MAAM;AAAA,EAC3G,GAAG,CAAC,MAAM,QAAQ,QAAQ,CAAC,CAAC;AAE5B,SACE,qBAAC,YAAO,WAAU,yCAChB;AAAA,wBAAC,QAAG,WAAU,0DAA0D,iBAAM;AAAA,IAC7E,aACC,oBAAC,SAAI,WAAU,sCACb;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS;AAAA,QACT,cAAY,EAAE,uCAAuC,WAAW;AAAA,QAEhE;AAAA,8BAAC,QAAK,eAAY,QAAO;AAAA,UACzB,oBAAC,UAAK,WAAU,oBACb,YAAE,uCAAuC,WAAW,GACvD;AAAA;AAAA;AAAA,IACF,GACF,IACE;AAAA,KACN;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,516 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import dynamic from "next/dynamic";
5
+ import { addDays } from "date-fns/addDays";
6
+ import { isSameDay } from "date-fns/isSameDay";
7
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
8
+ import { apiCall, apiCallOrThrow, withScopedApiRequestHeaders } from "@open-mercato/ui/backend/utils/apiCall";
9
+ import { matchFeature } from "@open-mercato/shared/lib/auth/featureMatch";
10
+ import {
11
+ buildOptimisticLockHeader,
12
+ extractOptimisticLockConflict
13
+ } from "@open-mercato/ui/backend/utils/optimisticLock";
14
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
15
+ import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
16
+ import { ErrorMessage, LoadingMessage } from "@open-mercato/ui/backend/detail";
17
+ import { Button } from "@open-mercato/ui/primitives/button";
18
+ import { countByCategory } from "../../lib/calendar/categories.js";
19
+ import { findConflicts } from "../../lib/calendar/conflicts.js";
20
+ import { getVisibleRange } from "../../lib/calendar/range.js";
21
+ import { AgendaList } from "./AgendaList.js";
22
+ import { CalendarFooter } from "./CalendarFooter.js";
23
+ import { CalendarHeader } from "./CalendarHeader.js";
24
+ import { CalendarTabs } from "./CalendarTabs.js";
25
+ import { CalendarToolbar } from "./CalendarToolbar.js";
26
+ import { MonthGrid } from "./MonthGrid.js";
27
+ import { ShortcutsDialog } from "./ShortcutsDialog.js";
28
+ import { TimeGrid } from "./TimeGrid.js";
29
+ import { UpcomingCards } from "./UpcomingCards.js";
30
+ import { CalendarSettingsModal } from "./CalendarSettingsModal.js";
31
+ import { useCalendarPreferences } from "./useCalendarPreferences.js";
32
+ import { MAX_WINDOW_ITEMS, useCalendarItems } from "./useCalendarItems.js";
33
+ const CalendarEventEditor = dynamic(
34
+ () => import("./CalendarEventEditor.js").then((mod) => mod.CalendarEventEditor),
35
+ { ssr: false }
36
+ );
37
+ const SEARCH_DEBOUNCE_MS = 200;
38
+ const PHONE_BREAKPOINT_PX = 640;
39
+ const HIGHLIGHT_CLEAR_MS = 3e3;
40
+ const DEFAULT_AGENDA_HORIZON_DAYS = 7;
41
+ const UPCOMING_CARDS_COUNT = 4;
42
+ const EMPTY_FILTERS = { types: [], status: null, ownerUserId: null };
43
+ const MANAGE_FEATURE = "customers.interactions.manage";
44
+ function useCanManageInteractions() {
45
+ const [canManage, setCanManage] = React.useState(false);
46
+ React.useEffect(() => {
47
+ const controller = new AbortController();
48
+ let cancelled = false;
49
+ apiCall("/api/auth/feature-check", {
50
+ method: "POST",
51
+ headers: { "Content-Type": "application/json" },
52
+ signal: controller.signal,
53
+ body: JSON.stringify({ features: [MANAGE_FEATURE] })
54
+ }).then((call) => {
55
+ if (cancelled || !call.ok) return;
56
+ const granted = Array.isArray(call.result?.granted) ? call.result.granted.map((feature) => String(feature)) : [];
57
+ setCanManage(granted.some((grantedFeature) => matchFeature(MANAGE_FEATURE, grantedFeature)));
58
+ }).catch(() => {
59
+ if (!cancelled && !controller.signal.aborted) setCanManage(false);
60
+ });
61
+ return () => {
62
+ cancelled = true;
63
+ controller.abort();
64
+ };
65
+ }, []);
66
+ return canManage;
67
+ }
68
+ function buildTimezoneLabel() {
69
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
70
+ const offsetMinutes = -(/* @__PURE__ */ new Date()).getTimezoneOffset();
71
+ const sign = offsetMinutes >= 0 ? "+" : "-";
72
+ const absolute = Math.abs(offsetMinutes);
73
+ const hours = Math.floor(absolute / 60);
74
+ const minutes = absolute % 60;
75
+ const offset = minutes > 0 ? `${sign}${hours}:${String(minutes).padStart(2, "0")}` : `${sign}${hours}`;
76
+ return `${timeZone} (GMT${offset})`;
77
+ }
78
+ function resolveJoinUrl(location) {
79
+ const trimmed = location?.trim() ?? "";
80
+ if (!trimmed) return null;
81
+ if (/^https?:\/\//i.test(trimmed)) return trimmed;
82
+ if (/^www\./i.test(trimmed)) return `https://${trimmed}`;
83
+ return null;
84
+ }
85
+ function asEditableItem(item) {
86
+ return item.isRecurringOccurrence ? { ...item, id: item.raw.id } : item;
87
+ }
88
+ function CalendarScreen() {
89
+ const t = useT();
90
+ const [view, setView] = React.useState("week");
91
+ const [anchor, setAnchor] = React.useState(() => /* @__PURE__ */ new Date());
92
+ const [agendaHorizonDays, setAgendaHorizonDays] = React.useState(DEFAULT_AGENDA_HORIZON_DAYS);
93
+ const [preset, setPreset] = React.useState("thisWeek");
94
+ React.useEffect(() => {
95
+ if (window.innerWidth >= PHONE_BREAKPOINT_PX) return;
96
+ setView("day");
97
+ setPreset(null);
98
+ }, []);
99
+ const [tab, setTab] = React.useState("all");
100
+ const [searchText, setSearchText] = React.useState("");
101
+ const [debouncedSearch, setDebouncedSearch] = React.useState("");
102
+ const [filters, setFilters] = React.useState(EMPTY_FILTERS);
103
+ const [editor, setEditor] = React.useState({ open: false, mode: "create", item: null });
104
+ const [editorMounted, setEditorMounted] = React.useState(false);
105
+ const [createRange, setCreateRange] = React.useState(null);
106
+ const [shortcutsOpen, setShortcutsOpen] = React.useState(false);
107
+ const [settingsOpen, setSettingsOpen] = React.useState(false);
108
+ const [highlightItemId, setHighlightItemId] = React.useState(null);
109
+ const [hasLoadedOnce, setHasLoadedOnce] = React.useState(false);
110
+ const { preferences, setPreferences, hydrated: preferencesHydrated, userId: currentUserId } = useCalendarPreferences();
111
+ const range = React.useMemo(
112
+ () => getVisibleRange(view, anchor, agendaHorizonDays),
113
+ [view, anchor, agendaHorizonDays]
114
+ );
115
+ const { items, isLoading, error, truncated, typeLabels, typeColors, refetch } = useCalendarItems(range);
116
+ React.useEffect(() => {
117
+ if (!isLoading) setHasLoadedOnce(true);
118
+ }, [isLoading]);
119
+ React.useEffect(() => {
120
+ const timer = window.setTimeout(() => setDebouncedSearch(searchText), SEARCH_DEBOUNCE_MS);
121
+ return () => window.clearTimeout(timer);
122
+ }, [searchText]);
123
+ React.useEffect(() => {
124
+ if (!highlightItemId) return;
125
+ const timer = window.setTimeout(() => setHighlightItemId(null), HIGHLIGHT_CLEAR_MS);
126
+ return () => window.clearTimeout(timer);
127
+ }, [highlightItemId]);
128
+ const visibleItems = React.useMemo(
129
+ () => items.filter((item) => item.end > range.from && item.start < range.to),
130
+ [items, range]
131
+ );
132
+ const searchedItems = React.useMemo(() => {
133
+ const query = debouncedSearch.trim().toLowerCase();
134
+ if (!query) return visibleItems;
135
+ return visibleItems.filter((item) => {
136
+ if (item.title.toLowerCase().includes(query)) return true;
137
+ if (item.location && item.location.toLowerCase().includes(query)) return true;
138
+ const rawBody = item.raw.body;
139
+ if (typeof rawBody === "string" && rawBody.toLowerCase().includes(query)) return true;
140
+ return item.participants.some(
141
+ (participant) => (participant.name ?? "").toLowerCase().includes(query)
142
+ );
143
+ });
144
+ }, [visibleItems, debouncedSearch]);
145
+ const baseItems = React.useMemo(
146
+ () => searchedItems.filter((item) => {
147
+ if (filters.types.length > 0 && !filters.types.includes(item.interactionType)) return false;
148
+ if (filters.status && item.status !== filters.status) return false;
149
+ if (filters.ownerUserId && item.ownerUserId !== filters.ownerUserId) return false;
150
+ if (!preferences.showCrmActivities && item.category !== "meeting" && item.category !== "event") return false;
151
+ return true;
152
+ }),
153
+ [searchedItems, filters, preferences.showCrmActivities]
154
+ );
155
+ const tabCounts = React.useMemo(() => countByCategory(baseItems), [baseItems]);
156
+ const viewItems = React.useMemo(() => {
157
+ if (tab === "meetings") return baseItems.filter((item) => item.category === "meeting");
158
+ if (tab === "events") return baseItems.filter((item) => item.category === "event");
159
+ return baseItems;
160
+ }, [baseItems, tab]);
161
+ const conflictMap = React.useMemo(
162
+ () => findConflicts(baseItems, { scope: preferences.conflictScope, currentUserId }),
163
+ [baseItems, preferences.conflictScope, currentUserId]
164
+ );
165
+ const conflictIds = React.useMemo(() => new Set(conflictMap.keys()), [conflictMap]);
166
+ const upcomingCards = React.useMemo(() => {
167
+ const now = /* @__PURE__ */ new Date();
168
+ const nowMs = now.getTime();
169
+ return baseItems.filter((item) => item.start.getTime() >= nowMs).sort((first, second) => first.start.getTime() - second.start.getTime()).slice(0, UPCOMING_CARDS_COUNT).map((item) => {
170
+ const conflictCount = preferences.conflictWarnings ? conflictMap.get(item.id)?.length ?? 0 : 0;
171
+ const kind = item.status === "canceled" ? "cancelled" : conflictCount > 0 ? "conflicted" : isSameDay(item.start, now) ? "today" : "future";
172
+ return { item, kind, conflictCount };
173
+ });
174
+ }, [baseItems, conflictMap, preferences.conflictWarnings]);
175
+ const typeOptions = React.useMemo(() => {
176
+ const values = new Set(Object.keys(typeLabels));
177
+ for (const item of items) values.add(item.interactionType);
178
+ return [...values].sort().map((value) => ({ value, label: typeLabels[value] ?? value }));
179
+ }, [items, typeLabels]);
180
+ const ownerOptions = React.useMemo(() => {
181
+ const participantNames = /* @__PURE__ */ new Map();
182
+ for (const item of items) {
183
+ for (const participant of item.participants) {
184
+ if (participant.name && !participantNames.has(participant.userId)) {
185
+ participantNames.set(participant.userId, participant.name);
186
+ }
187
+ }
188
+ }
189
+ const owners = /* @__PURE__ */ new Map();
190
+ for (const item of items) {
191
+ if (!item.ownerUserId || owners.has(item.ownerUserId)) continue;
192
+ owners.set(item.ownerUserId, participantNames.get(item.ownerUserId) ?? item.ownerUserId);
193
+ }
194
+ return [...owners.entries()].map(([value, label]) => ({ value, label })).sort((first, second) => first.label.localeCompare(second.label));
195
+ }, [items]);
196
+ const timezoneLabel = React.useMemo(() => buildTimezoneLabel(), []);
197
+ const canManage = useCanManageInteractions();
198
+ const openCreateEditor = React.useCallback(() => {
199
+ if (!canManage) return;
200
+ setCreateRange(null);
201
+ setEditorMounted(true);
202
+ setEditor({ open: true, mode: "create", item: null });
203
+ }, [canManage]);
204
+ const openEditEditor = React.useCallback(
205
+ (item) => {
206
+ if (!canManage) return;
207
+ setCreateRange(null);
208
+ setEditorMounted(true);
209
+ setEditor({ open: true, mode: "edit", item: asEditableItem(item) });
210
+ },
211
+ [canManage]
212
+ );
213
+ const handleCreateRange = React.useCallback(
214
+ (start, end) => {
215
+ if (!canManage) return;
216
+ setCreateRange({ start, end });
217
+ setEditorMounted(true);
218
+ setEditor({ open: true, mode: "create", item: null });
219
+ },
220
+ [canManage]
221
+ );
222
+ const seedActivityTypes = React.useMemo(() => {
223
+ const seen = /* @__PURE__ */ new Set();
224
+ const labels = [];
225
+ for (const value of Object.keys(typeLabels)) {
226
+ const label = typeLabels[value] ?? value;
227
+ if (seen.has(label)) continue;
228
+ seen.add(label);
229
+ labels.push(label);
230
+ }
231
+ return labels;
232
+ }, [typeLabels]);
233
+ const handleToday = React.useCallback(() => {
234
+ setAnchor(/* @__PURE__ */ new Date());
235
+ setPreset(null);
236
+ }, []);
237
+ const handlePresetChange = React.useCallback((next) => {
238
+ setPreset(next);
239
+ setAnchor(/* @__PURE__ */ new Date());
240
+ if (next === "thisWeek") {
241
+ setView("week");
242
+ } else if (next === "thisMonth") {
243
+ setView("month");
244
+ } else {
245
+ setView("agenda");
246
+ setAgendaHorizonDays(next === "next30" ? 30 : DEFAULT_AGENDA_HORIZON_DAYS);
247
+ }
248
+ }, []);
249
+ const handleAnchorChange = React.useCallback((date) => {
250
+ setAnchor(date);
251
+ setPreset(null);
252
+ }, []);
253
+ const handleViewChange = React.useCallback((next) => {
254
+ setView(next);
255
+ setPreset(null);
256
+ }, []);
257
+ const handleTimeGridNavigate = React.useCallback((deltaDays) => {
258
+ setAnchor((current) => addDays(current, deltaDays));
259
+ setPreset(null);
260
+ }, []);
261
+ const handleDayOpen = React.useCallback((date) => {
262
+ setView("day");
263
+ setAnchor(date);
264
+ setPreset(null);
265
+ }, []);
266
+ const handleSeeConflict = React.useCallback((item) => {
267
+ setView("week");
268
+ setAnchor(item.start);
269
+ setPreset(null);
270
+ setHighlightItemId(item.id);
271
+ }, []);
272
+ const handleJoin = React.useCallback((item) => {
273
+ const url = resolveJoinUrl(item.location);
274
+ if (url) window.open(url, "_blank", "noopener");
275
+ }, []);
276
+ const { runMutation, retryLastMutation } = useGuardedMutation({
277
+ contextId: "customers-calendar-cancel",
278
+ blockedMessage: t("ui.forms.flash.saveBlocked", "Save blocked by validation")
279
+ });
280
+ const handleCancelItem = React.useCallback(
281
+ async (item) => {
282
+ const interactionId = item.raw.id;
283
+ try {
284
+ await runMutation({
285
+ operation: () => withScopedApiRequestHeaders(
286
+ buildOptimisticLockHeader(item.updatedAt),
287
+ () => apiCallOrThrow("/api/customers/interactions", {
288
+ method: "PUT",
289
+ headers: { "content-type": "application/json" },
290
+ body: JSON.stringify({ id: interactionId, status: "canceled" })
291
+ })
292
+ ),
293
+ mutationPayload: {
294
+ operation: "cancelCalendarEvent",
295
+ interactionId,
296
+ interactionType: item.interactionType
297
+ },
298
+ context: {
299
+ formId: "customers-calendar-cancel",
300
+ resourceKind: "customers.interaction",
301
+ resourceId: interactionId,
302
+ retryLastMutation
303
+ }
304
+ });
305
+ flash(t("customers.calendar.cards.cancelSuccess", "Event cancelled"), "success");
306
+ refetch();
307
+ } catch (err) {
308
+ if (extractOptimisticLockConflict(err)) return;
309
+ flash(t("customers.calendar.cards.cancelError", "Failed to cancel event"), "error");
310
+ }
311
+ },
312
+ [refetch, retryLastMutation, runMutation, t]
313
+ );
314
+ const focusSearch = React.useCallback(() => {
315
+ const node = document.querySelector("[data-calendar-search]");
316
+ if (node instanceof HTMLInputElement) node.focus();
317
+ else if (node instanceof HTMLElement) node.querySelector("input")?.focus();
318
+ }, []);
319
+ const editorOpen = editor.open;
320
+ React.useEffect(() => {
321
+ const handleKeyDown = (event) => {
322
+ if (event.defaultPrevented) return;
323
+ if (event.metaKey || event.ctrlKey || event.altKey) return;
324
+ const target = event.target;
325
+ if (target instanceof HTMLElement) {
326
+ const tag = target.tagName;
327
+ if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || target.isContentEditable) return;
328
+ }
329
+ if (editorOpen) return;
330
+ switch (event.key) {
331
+ case "t":
332
+ case "T":
333
+ event.preventDefault();
334
+ setAnchor(/* @__PURE__ */ new Date());
335
+ setPreset(null);
336
+ break;
337
+ case "d":
338
+ case "D":
339
+ event.preventDefault();
340
+ setView("day");
341
+ setPreset(null);
342
+ break;
343
+ case "w":
344
+ case "W":
345
+ event.preventDefault();
346
+ setView("week");
347
+ setPreset(null);
348
+ break;
349
+ case "m":
350
+ case "M":
351
+ event.preventDefault();
352
+ setView("month");
353
+ setPreset(null);
354
+ break;
355
+ case "a":
356
+ case "A":
357
+ event.preventDefault();
358
+ setView("agenda");
359
+ setPreset(null);
360
+ break;
361
+ case "n":
362
+ case "N":
363
+ event.preventDefault();
364
+ openCreateEditor();
365
+ break;
366
+ case "/":
367
+ event.preventDefault();
368
+ focusSearch();
369
+ break;
370
+ case "?":
371
+ event.preventDefault();
372
+ setShortcutsOpen((open) => !open);
373
+ break;
374
+ case "Escape":
375
+ setHighlightItemId(null);
376
+ break;
377
+ default:
378
+ break;
379
+ }
380
+ };
381
+ window.addEventListener("keydown", handleKeyDown);
382
+ return () => window.removeEventListener("keydown", handleKeyDown);
383
+ }, [editorOpen, focusSearch, openCreateEditor]);
384
+ const showInitialLoading = isLoading && !hasLoadedOnce || !preferencesHydrated;
385
+ let viewArea;
386
+ if (error) {
387
+ viewArea = /* @__PURE__ */ jsx(
388
+ ErrorMessage,
389
+ {
390
+ label: t("customers.calendar.errors.loadFailed", "Failed to load calendar events."),
391
+ action: /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: refetch, children: t("customers.calendar.errors.retry", "Retry") })
392
+ }
393
+ );
394
+ } else if (showInitialLoading) {
395
+ viewArea = /* @__PURE__ */ jsx(LoadingMessage, { label: t("customers.calendar.loading", "Loading calendar\u2026") });
396
+ } else if (view === "month") {
397
+ viewArea = /* @__PURE__ */ jsx(MonthGrid, { anchor, items: viewItems, onItemClick: openEditEditor, onDayOpen: handleDayOpen });
398
+ } else if (view === "agenda") {
399
+ viewArea = /* @__PURE__ */ jsx(
400
+ AgendaList,
401
+ {
402
+ anchor,
403
+ horizonDays: agendaHorizonDays,
404
+ items: viewItems,
405
+ typeLabels,
406
+ onItemClick: openEditEditor
407
+ }
408
+ );
409
+ } else {
410
+ viewArea = /* @__PURE__ */ jsx(
411
+ TimeGrid,
412
+ {
413
+ days: view === "day" ? 1 : 7,
414
+ anchor,
415
+ items: viewItems,
416
+ conflictIds,
417
+ showWeekends: preferences.showWeekends,
418
+ showConflicts: preferences.conflictWarnings,
419
+ aiSummaries: preferences.aiSummaries,
420
+ highlightItemId,
421
+ onItemClick: openEditEditor,
422
+ onJoin: handleJoin,
423
+ onNavigate: handleTimeGridNavigate,
424
+ onCreate: canManage ? openCreateEditor : void 0,
425
+ onCreateRange: canManage ? handleCreateRange : void 0
426
+ }
427
+ );
428
+ }
429
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-4", children: [
430
+ /* @__PURE__ */ jsx(CalendarHeader, { view, anchor, onNewEvent: canManage ? openCreateEditor : void 0 }),
431
+ /* @__PURE__ */ jsx(
432
+ CalendarToolbar,
433
+ {
434
+ view,
435
+ anchor,
436
+ range,
437
+ preset,
438
+ search: searchText,
439
+ filters,
440
+ typeOptions,
441
+ ownerOptions,
442
+ onToday: handleToday,
443
+ onPresetChange: handlePresetChange,
444
+ onAnchorChange: handleAnchorChange,
445
+ onSearchChange: setSearchText,
446
+ onFiltersChange: setFilters,
447
+ onOpenSettings: () => setSettingsOpen(true)
448
+ }
449
+ ),
450
+ /* @__PURE__ */ jsx(
451
+ UpcomingCards,
452
+ {
453
+ cards: upcomingCards,
454
+ canManage,
455
+ onJoin: handleJoin,
456
+ onSeeConflict: handleSeeConflict,
457
+ onOpen: openEditEditor,
458
+ onEdit: openEditEditor,
459
+ onCancel: handleCancelItem
460
+ }
461
+ ),
462
+ /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-3", children: [
463
+ /* @__PURE__ */ jsx(
464
+ CalendarTabs,
465
+ {
466
+ tab,
467
+ counts: tabCounts,
468
+ view,
469
+ onTabChange: setTab,
470
+ onViewChange: handleViewChange
471
+ }
472
+ ),
473
+ truncated ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", role: "status", children: t("customers.calendar.notice.truncated", "Showing first {count} items for this range.", {
474
+ count: MAX_WINDOW_ITEMS
475
+ }) }) : null,
476
+ /* @__PURE__ */ jsx("div", { className: "flex min-h-[560px] flex-1 flex-col [&>*]:flex-1", children: viewArea })
477
+ ] }),
478
+ /* @__PURE__ */ jsx("div", { className: "hidden md:block", children: /* @__PURE__ */ jsx(CalendarFooter, { timezoneLabel, onOpenShortcuts: () => setShortcutsOpen(true) }) }),
479
+ /* @__PURE__ */ jsx(ShortcutsDialog, { open: shortcutsOpen, onOpenChange: setShortcutsOpen }),
480
+ /* @__PURE__ */ jsx(
481
+ CalendarSettingsModal,
482
+ {
483
+ open: settingsOpen,
484
+ preferences,
485
+ seedActivityTypes,
486
+ onOpenChange: setSettingsOpen,
487
+ onSave: (next) => {
488
+ setPreferences(next);
489
+ flash(t("customers.calendar.settings.saved", "Calendar settings saved"), "success");
490
+ }
491
+ }
492
+ ),
493
+ editorMounted ? /* @__PURE__ */ jsx(
494
+ CalendarEventEditor,
495
+ {
496
+ open: editor.open,
497
+ mode: editor.mode,
498
+ item: editor.item,
499
+ defaultDate: anchor,
500
+ defaultRange: createRange,
501
+ typeLabels,
502
+ typeColors,
503
+ surfacedTypes: preferences.activityTypes,
504
+ eventCategories: preferences.eventCategories,
505
+ conflictScope: preferences.conflictScope,
506
+ currentUserId,
507
+ onOpenChange: (open) => setEditor((current) => ({ ...current, open })),
508
+ onSaved: refetch
509
+ }
510
+ ) : null
511
+ ] });
512
+ }
513
+ export {
514
+ CalendarScreen
515
+ };
516
+ //# sourceMappingURL=CalendarScreen.js.map