@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,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/components/calendar/CalendarToolbar.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { format } from 'date-fns/format'\nimport { CalendarRange, ListFilter, Settings } from 'lucide-react'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Calendar } from '@open-mercato/ui/primitives/calendar'\nimport { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Kbd } from '@open-mercato/ui/primitives/kbd'\nimport { Popover, PopoverContent, PopoverTrigger } from '@open-mercato/ui/primitives/popover'\nimport { SearchInput } from '@open-mercato/ui/primitives/search-input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type {\n CalendarFiltersValue,\n CalendarRangePreset,\n CalendarToolbarProps,\n} from './types'\n\nconst RANGE_PRESETS: CalendarRangePreset[] = ['thisWeek', 'next7', 'thisMonth', 'next30']\n\nconst STATUS_OPTIONS = ['planned', 'done', 'canceled'] as const\n\nconst ALL_OPTION = 'all'\n\nconst EMPTY_FILTERS: CalendarFiltersValue = { types: [], status: null, ownerUserId: null }\n\nfunction formatRangeLabel(from: Date, to: Date): string {\n return `${format(from, 'MMM dd')} \u2013 ${format(to, 'MMM dd, yyyy')}`\n}\n\nexport function CalendarToolbar(props: CalendarToolbarProps) {\n const {\n anchor,\n range,\n preset,\n search,\n filters,\n typeOptions,\n ownerOptions,\n onToday,\n onPresetChange,\n onAnchorChange,\n onSearchChange,\n onFiltersChange,\n onOpenSettings,\n } = props\n const t = useT()\n const [rangeOpen, setRangeOpen] = React.useState(false)\n const [filtersOpen, setFiltersOpen] = React.useState(false)\n const [pendingFilters, setPendingFilters] = React.useState<CalendarFiltersValue>(filters)\n\n const presetLabels: Record<CalendarRangePreset, string> = {\n thisWeek: t('customers.calendar.toolbar.presets.thisWeek', 'This week'),\n next7: t('customers.calendar.toolbar.presets.next7', 'Next 7 days'),\n thisMonth: t('customers.calendar.toolbar.presets.thisMonth', 'This month'),\n next30: t('customers.calendar.toolbar.presets.next30', 'Next 30 days'),\n }\n\n const activeFilterCount =\n filters.types.length + (filters.status ? 1 : 0) + (filters.ownerUserId ? 1 : 0)\n\n const handleFiltersOpenChange = (open: boolean) => {\n if (open) setPendingFilters(filters)\n setFiltersOpen(open)\n }\n\n const applyFilters = () => {\n onFiltersChange(pendingFilters)\n setFiltersOpen(false)\n }\n\n const clearFilters = () => {\n setPendingFilters(EMPTY_FILTERS)\n onFiltersChange(EMPTY_FILTERS)\n setFiltersOpen(false)\n }\n\n const togglePendingType = (value: string, checked: boolean) => {\n setPendingFilters((current) => ({\n ...current,\n types: checked\n ? [...current.types, value]\n : current.types.filter((entry) => entry !== value),\n }))\n }\n\n return (\n <div className=\"flex flex-wrap items-center gap-2 sm:gap-3\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-2 sm:gap-3\">\n <Button type=\"button\" variant=\"outline\" onClick={onToday}>\n {t('customers.calendar.toolbar.today', 'Today')}\n </Button>\n <div className=\"flex min-w-0 items-center\">\n <Select\n value={preset ?? ''}\n onValueChange={(value) => onPresetChange(value as CalendarRangePreset)}\n >\n <SelectTrigger\n className=\"hidden w-auto min-w-32 rounded-r-none sm:flex\"\n aria-label={t('customers.calendar.toolbar.presetLabel', 'Date range preset')}\n >\n <SelectValue\n placeholder={t('customers.calendar.toolbar.presetPlaceholder', 'Custom range')}\n />\n </SelectTrigger>\n <SelectContent>\n {RANGE_PRESETS.map((value) => (\n <SelectItem key={value} value={value}>\n {presetLabels[value]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Popover open={rangeOpen} onOpenChange={setRangeOpen}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"min-w-0 text-muted-foreground sm:-ml-px sm:rounded-l-none\"\n >\n <CalendarRange aria-hidden=\"true\" />\n <span className=\"truncate\">{formatRangeLabel(range.from, range.to)}</span>\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-auto min-w-0 p-2\">\n <Calendar\n mode=\"single\"\n selected={anchor}\n defaultMonth={anchor}\n onSelect={(date) => {\n if (!date) return\n onAnchorChange(date)\n setRangeOpen(false)\n }}\n />\n </PopoverContent>\n </Popover>\n </div>\n </div>\n <div className=\"flex w-full min-w-0 items-center gap-2 sm:ml-auto sm:w-auto sm:flex-none sm:gap-3\">\n <div className=\"relative min-w-0 flex-1 sm:w-72 sm:flex-none\">\n <SearchInput\n value={search}\n onChange={onSearchChange}\n placeholder={t('customers.calendar.toolbar.searchPlaceholder', 'Search\u2026')}\n aria-label={t('customers.calendar.toolbar.searchPlaceholder', 'Search\u2026')}\n data-calendar-search=\"\"\n />\n {search.length === 0 ? (\n <Kbd className=\"pointer-events-none absolute right-2 top-1/2 hidden -translate-y-1/2 sm:inline-flex\">/</Kbd>\n ) : null}\n </div>\n <Popover open={filtersOpen} onOpenChange={handleFiltersOpenChange}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n aria-label={t('customers.calendar.toolbar.filters.label', 'Filter')}\n >\n <ListFilter aria-hidden=\"true\" />\n <span className=\"hidden sm:inline\">\n {t('customers.calendar.toolbar.filters.label', 'Filter')}\n </span>\n {activeFilterCount > 0 ? (\n <Badge variant=\"secondary\" size=\"sm\">\n {activeFilterCount}\n </Badge>\n ) : null}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n className=\"w-72 p-3\"\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n applyFilters()\n }\n }}\n >\n <div className=\"flex flex-col gap-4\">\n {typeOptions.length > 0 ? (\n <fieldset className=\"flex flex-col gap-2\">\n <legend className=\"pb-1 text-overline font-semibold uppercase tracking-widest text-muted-foreground\">\n {t('customers.calendar.toolbar.filters.types', 'Type')}\n </legend>\n {typeOptions.map((option) => (\n <CheckboxField\n key={option.value}\n label={option.label}\n size=\"sm\"\n checked={pendingFilters.types.includes(option.value)}\n onCheckedChange={(checked) =>\n togglePendingType(option.value, checked === true)\n }\n />\n ))}\n </fieldset>\n ) : null}\n <div className=\"flex flex-col gap-1.5\">\n <span className=\"text-overline font-semibold uppercase tracking-widest text-muted-foreground\">\n {t('customers.calendar.toolbar.filters.status', 'Status')}\n </span>\n <Select\n value={pendingFilters.status ?? ALL_OPTION}\n onValueChange={(value) =>\n setPendingFilters((current) => ({\n ...current,\n status: value === ALL_OPTION ? null : value,\n }))\n }\n >\n <SelectTrigger\n size=\"sm\"\n aria-label={t('customers.calendar.toolbar.filters.status', 'Status')}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL_OPTION}>\n {t('customers.calendar.toolbar.filters.allStatuses', 'All statuses')}\n </SelectItem>\n {STATUS_OPTIONS.map((status) => (\n <SelectItem key={status} value={status}>\n {t(`customers.calendar.toolbar.filters.statuses.${status}`, status)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {ownerOptions.length > 0 ? (\n <div className=\"flex flex-col gap-1.5\">\n <span className=\"text-overline font-semibold uppercase tracking-widest text-muted-foreground\">\n {t('customers.calendar.toolbar.filters.owner', 'Owner')}\n </span>\n <Select\n value={pendingFilters.ownerUserId ?? ALL_OPTION}\n onValueChange={(value) =>\n setPendingFilters((current) => ({\n ...current,\n ownerUserId: value === ALL_OPTION ? null : value,\n }))\n }\n >\n <SelectTrigger\n size=\"sm\"\n aria-label={t('customers.calendar.toolbar.filters.owner', 'Owner')}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL_OPTION}>\n {t('customers.calendar.toolbar.filters.allOwners', 'All owners')}\n </SelectItem>\n {ownerOptions.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : null}\n <div className=\"flex items-center justify-end gap-2 border-t pt-3\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={clearFilters}>\n {t('customers.calendar.toolbar.filters.clear', 'Clear')}\n </Button>\n <Button type=\"button\" size=\"sm\" onClick={applyFilters}>\n {t('customers.calendar.toolbar.filters.apply', 'Apply')}\n </Button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n <IconButton\n type=\"button\"\n variant=\"outline\"\n aria-label={t('customers.calendar.toolbar.settings', 'Calendar settings')}\n onClick={onOpenSettings}\n >\n <Settings aria-hidden />\n </IconButton>\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,149 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Globe, MapPin } from "lucide-react";
5
+ import { cn } from "@open-mercato/shared/lib/utils";
6
+ import { useLocale, useT } from "@open-mercato/shared/lib/i18n/context";
7
+ import { Avatar, AvatarStack } from "@open-mercato/ui/primitives/avatar";
8
+ import { Button } from "@open-mercato/ui/primitives/button";
9
+ const SHOW_TIME_MIN_HEIGHT_PX = 44;
10
+ const SHOW_META_MIN_HEIGHT_PX = 96;
11
+ const WRAP_TITLE_MIN_HEIGHT_PX = 128;
12
+ const MAX_VISIBLE_AVATARS = 3;
13
+ const PLATFORM_LABELS = {
14
+ zoom: { key: "customers.calendar.platform.zoom", fallback: "Zoom" },
15
+ meet: { key: "customers.calendar.platform.meet", fallback: "Meet" },
16
+ slack: { key: "customers.calendar.platform.slack", fallback: "Slack" },
17
+ teams: { key: "customers.calendar.platform.teams", fallback: "Teams" }
18
+ };
19
+ function softTintStyle(color) {
20
+ if (/^#[0-9a-fA-F]{6}$/.test(color)) return { backgroundColor: `${color}1A` };
21
+ return { backgroundColor: `color-mix(in srgb, ${color} 10%, transparent)` };
22
+ }
23
+ function resolveEventTone(item, nowMs) {
24
+ if (item.status === "canceled") {
25
+ return {
26
+ surfaceClassName: "bg-muted/60",
27
+ titleClassName: "text-muted-foreground line-through",
28
+ subClassName: "text-muted-foreground/70"
29
+ };
30
+ }
31
+ if (item.status === "done" || item.end.getTime() < nowMs) {
32
+ return {
33
+ surfaceClassName: "bg-muted",
34
+ titleClassName: "text-muted-foreground",
35
+ subClassName: "text-muted-foreground"
36
+ };
37
+ }
38
+ if (item.color) {
39
+ return {
40
+ surfaceClassName: "",
41
+ titleClassName: "text-foreground",
42
+ subClassName: "text-muted-foreground",
43
+ style: softTintStyle(item.color)
44
+ };
45
+ }
46
+ return {
47
+ surfaceClassName: "bg-muted/60",
48
+ titleClassName: "text-foreground",
49
+ subClassName: "text-muted-foreground"
50
+ };
51
+ }
52
+ function formatTimeRange(locale, start, end) {
53
+ const formatter = new Intl.DateTimeFormat(locale, { hour: "numeric", minute: "2-digit" });
54
+ try {
55
+ return formatter.formatRange(start, end);
56
+ } catch {
57
+ return `${formatter.format(start)} - ${formatter.format(end)}`;
58
+ }
59
+ }
60
+ function participantLabel(participant) {
61
+ return participant.name ?? participant.email ?? "?";
62
+ }
63
+ function LocationMeta({ item, subClassName, accentColor }) {
64
+ const t = useT();
65
+ if (!item.location || !item.locationKind) return null;
66
+ const iconStyle = accentColor ? { color: accentColor } : void 0;
67
+ if (item.locationKind === "platform" && item.platform) {
68
+ const platform = PLATFORM_LABELS[item.platform];
69
+ return /* @__PURE__ */ jsx("span", { className: cn("truncate text-xs", subClassName), children: t("customers.calendar.grid.onPlatform", "on {platform}", { platform: t(platform.key, platform.fallback) }) });
70
+ }
71
+ if (item.locationKind === "url") {
72
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
73
+ /* @__PURE__ */ jsx(Globe, { className: cn("size-4 shrink-0", !accentColor && subClassName), style: iconStyle, "aria-hidden": true }),
74
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-foreground", children: item.location })
75
+ ] });
76
+ }
77
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
78
+ /* @__PURE__ */ jsx(MapPin, { className: cn("size-4 shrink-0", !accentColor && subClassName), style: iconStyle, "aria-hidden": true }),
79
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-foreground", children: t("customers.calendar.grid.venue", "Venue: {name}", { name: item.location }) })
80
+ ] });
81
+ }
82
+ const EventBlock = React.forwardRef(function EventBlock2({
83
+ item,
84
+ top,
85
+ height,
86
+ insetInlineStart,
87
+ width,
88
+ conflicted,
89
+ highlighted,
90
+ selected,
91
+ nowMs,
92
+ className,
93
+ ...buttonProps
94
+ }, ref) {
95
+ const t = useT();
96
+ const locale = useLocale();
97
+ const tone = resolveEventTone(item, nowMs);
98
+ const title = item.title || t("customers.calendar.grid.untitled", "Untitled");
99
+ const timeRange = formatTimeRange(locale, item.start, item.end);
100
+ const showTime = height >= SHOW_TIME_MIN_HEIGHT_PX;
101
+ const wrapTitle = height >= WRAP_TITLE_MIN_HEIGHT_PX;
102
+ const hasMetaContent = item.participants.length > 0 || item.location !== null && item.locationKind !== null;
103
+ const showMeta = height >= SHOW_META_MIN_HEIGHT_PX && hasMetaContent;
104
+ const visibleParticipants = item.participants.slice(0, MAX_VISIBLE_AVATARS);
105
+ const overflowCount = item.participants.length - visibleParticipants.length;
106
+ return /* @__PURE__ */ jsxs(
107
+ Button,
108
+ {
109
+ ref,
110
+ type: "button",
111
+ variant: "ghost",
112
+ "aria-label": `${title}, ${timeRange}`,
113
+ className: cn(
114
+ "pointer-events-auto absolute h-auto flex-col items-start justify-start gap-1 whitespace-normal overflow-hidden rounded-md px-1.5 text-start outline-none hover:bg-muted/70 sm:px-3",
115
+ height >= SHOW_TIME_MIN_HEIGHT_PX ? "py-1 sm:py-2" : "py-0.5 sm:py-1",
116
+ tone.surfaceClassName,
117
+ conflicted && "ring-1 ring-status-warning-icon",
118
+ selected && "shadow-md ring-2 ring-foreground",
119
+ highlighted && "motion-safe:animate-pulse",
120
+ conflicted || highlighted || selected ? "z-30" : "z-10",
121
+ "focus-visible:z-30 focus-visible:ring-2 focus-visible:ring-ring",
122
+ className
123
+ ),
124
+ style: { top, height, insetInlineStart, width, ...tone.style },
125
+ ...buttonProps,
126
+ children: [
127
+ /* @__PURE__ */ jsx("span", { className: cn("w-full text-xs font-medium leading-4", wrapTitle ? "line-clamp-2" : "truncate", tone.titleClassName), children: title }),
128
+ showTime ? /* @__PURE__ */ jsx("span", { className: cn("w-full truncate text-overline uppercase tracking-wide", tone.subClassName), children: timeRange }) : null,
129
+ showMeta ? /* @__PURE__ */ jsxs("span", { className: "mt-auto flex w-full min-w-0 items-center gap-1.5", children: [
130
+ visibleParticipants.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
131
+ /* @__PURE__ */ jsx(AvatarStack, { size: "xs", max: MAX_VISIBLE_AVATARS, className: "shrink-0 gap-px [&>*:not(:first-child)]:-ml-1", children: visibleParticipants.map((participant) => /* @__PURE__ */ jsx(Avatar, { size: "xs", label: participantLabel(participant) }, participant.userId)) }),
132
+ overflowCount > 0 ? /* @__PURE__ */ jsxs("span", { className: cn("shrink-0 text-xs", tone.subClassName), children: [
133
+ "+",
134
+ overflowCount
135
+ ] }) : null
136
+ ] }) : null,
137
+ /* @__PURE__ */ jsx("span", { className: "ms-auto flex min-w-0 items-center gap-1.5", children: /* @__PURE__ */ jsx(LocationMeta, { item, subClassName: tone.subClassName, accentColor: item.color }) })
138
+ ] }) : null
139
+ ]
140
+ }
141
+ );
142
+ });
143
+ EventBlock.displayName = "EventBlock";
144
+ export {
145
+ EventBlock,
146
+ formatTimeRange,
147
+ resolveEventTone
148
+ };
149
+ //# sourceMappingURL=EventBlock.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/components/calendar/EventBlock.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Globe, MapPin } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Avatar, AvatarStack } from '@open-mercato/ui/primitives/avatar'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport type { CalendarItem, CalendarPlatform } from './types'\n\nconst SHOW_TIME_MIN_HEIGHT_PX = 44\nconst SHOW_META_MIN_HEIGHT_PX = 96\nconst WRAP_TITLE_MIN_HEIGHT_PX = 128\nconst MAX_VISIBLE_AVATARS = 3\n\nconst PLATFORM_LABELS: Record<CalendarPlatform, { key: string; fallback: string }> = {\n zoom: { key: 'customers.calendar.platform.zoom', fallback: 'Zoom' },\n meet: { key: 'customers.calendar.platform.meet', fallback: 'Meet' },\n slack: { key: 'customers.calendar.platform.slack', fallback: 'Slack' },\n teams: { key: 'customers.calendar.platform.teams', fallback: 'Teams' },\n}\n\nexport type EventTone = {\n surfaceClassName: string\n titleClassName: string\n subClassName: string\n style?: React.CSSProperties\n}\n\nfunction softTintStyle(color: string): React.CSSProperties {\n if (/^#[0-9a-fA-F]{6}$/.test(color)) return { backgroundColor: `${color}1A` }\n return { backgroundColor: `color-mix(in srgb, ${color} 10%, transparent)` }\n}\n\nexport function resolveEventTone(item: CalendarItem, nowMs: number): EventTone {\n if (item.status === 'canceled') {\n return {\n surfaceClassName: 'bg-muted/60',\n titleClassName: 'text-muted-foreground line-through',\n subClassName: 'text-muted-foreground/70',\n }\n }\n if (item.status === 'done' || item.end.getTime() < nowMs) {\n return {\n surfaceClassName: 'bg-muted',\n titleClassName: 'text-muted-foreground',\n subClassName: 'text-muted-foreground',\n }\n }\n if (item.color) {\n return {\n surfaceClassName: '',\n titleClassName: 'text-foreground',\n subClassName: 'text-muted-foreground',\n style: softTintStyle(item.color),\n }\n }\n return {\n surfaceClassName: 'bg-muted/60',\n titleClassName: 'text-foreground',\n subClassName: 'text-muted-foreground',\n }\n}\n\nexport function formatTimeRange(locale: string, start: Date, end: Date): string {\n const formatter = new Intl.DateTimeFormat(locale, { hour: 'numeric', minute: '2-digit' })\n try {\n return formatter.formatRange(start, end)\n } catch {\n return `${formatter.format(start)} - ${formatter.format(end)}`\n }\n}\n\nfunction participantLabel(participant: CalendarItem['participants'][number]): string {\n return participant.name ?? participant.email ?? '?'\n}\n\ntype LocationMetaProps = {\n item: CalendarItem\n subClassName: string\n accentColor: string | null\n}\n\nfunction LocationMeta({ item, subClassName, accentColor }: LocationMetaProps) {\n const t = useT()\n if (!item.location || !item.locationKind) return null\n const iconStyle = accentColor ? { color: accentColor } : undefined\n if (item.locationKind === 'platform' && item.platform) {\n const platform = PLATFORM_LABELS[item.platform]\n return (\n <span className={cn('truncate text-xs', subClassName)}>\n {t('customers.calendar.grid.onPlatform', 'on {platform}', { platform: t(platform.key, platform.fallback) })}\n </span>\n )\n }\n if (item.locationKind === 'url') {\n return (\n <>\n <Globe className={cn('size-4 shrink-0', !accentColor && subClassName)} style={iconStyle} aria-hidden />\n <span className=\"truncate text-xs text-foreground\">{item.location}</span>\n </>\n )\n }\n return (\n <>\n <MapPin className={cn('size-4 shrink-0', !accentColor && subClassName)} style={iconStyle} aria-hidden />\n <span className=\"truncate text-xs text-foreground\">\n {t('customers.calendar.grid.venue', 'Venue: {name}', { name: item.location })}\n </span>\n </>\n )\n}\n\nexport type EventBlockProps = {\n item: CalendarItem\n top: number\n height: number\n insetInlineStart: string\n width: string\n conflicted: boolean\n highlighted: boolean\n selected?: boolean\n nowMs: number\n} & Omit<React.ComponentProps<typeof Button>, 'style' | 'children'>\n\nexport const EventBlock = React.forwardRef<HTMLButtonElement, EventBlockProps>(function EventBlock(\n {\n item,\n top,\n height,\n insetInlineStart,\n width,\n conflicted,\n highlighted,\n selected,\n nowMs,\n className,\n ...buttonProps\n },\n ref,\n) {\n const t = useT()\n const locale = useLocale()\n const tone = resolveEventTone(item, nowMs)\n const title = item.title || t('customers.calendar.grid.untitled', 'Untitled')\n const timeRange = formatTimeRange(locale, item.start, item.end)\n const showTime = height >= SHOW_TIME_MIN_HEIGHT_PX\n const wrapTitle = height >= WRAP_TITLE_MIN_HEIGHT_PX\n const hasMetaContent = item.participants.length > 0 || (item.location !== null && item.locationKind !== null)\n const showMeta = height >= SHOW_META_MIN_HEIGHT_PX && hasMetaContent\n const visibleParticipants = item.participants.slice(0, MAX_VISIBLE_AVATARS)\n const overflowCount = item.participants.length - visibleParticipants.length\n\n return (\n <Button\n ref={ref}\n type=\"button\"\n variant=\"ghost\"\n aria-label={`${title}, ${timeRange}`}\n className={cn(\n 'pointer-events-auto absolute h-auto flex-col items-start justify-start gap-1 whitespace-normal overflow-hidden rounded-md px-1.5 text-start outline-none hover:bg-muted/70 sm:px-3',\n height >= SHOW_TIME_MIN_HEIGHT_PX ? 'py-1 sm:py-2' : 'py-0.5 sm:py-1',\n tone.surfaceClassName,\n conflicted && 'ring-1 ring-status-warning-icon',\n selected && 'shadow-md ring-2 ring-foreground',\n highlighted && 'motion-safe:animate-pulse',\n conflicted || highlighted || selected ? 'z-30' : 'z-10',\n 'focus-visible:z-30 focus-visible:ring-2 focus-visible:ring-ring',\n className,\n )}\n style={{ top, height, insetInlineStart, width, ...tone.style }}\n {...buttonProps}\n >\n <span className={cn('w-full text-xs font-medium leading-4', wrapTitle ? 'line-clamp-2' : 'truncate', tone.titleClassName)}>\n {title}\n </span>\n {showTime ? (\n <span className={cn('w-full truncate text-overline uppercase tracking-wide', tone.subClassName)}>\n {timeRange}\n </span>\n ) : null}\n {showMeta ? (\n <span className=\"mt-auto flex w-full min-w-0 items-center gap-1.5\">\n {visibleParticipants.length > 0 ? (\n <>\n <AvatarStack size=\"xs\" max={MAX_VISIBLE_AVATARS} className=\"shrink-0 gap-px [&>*:not(:first-child)]:-ml-1\">\n {visibleParticipants.map((participant) => (\n <Avatar key={participant.userId} size=\"xs\" label={participantLabel(participant)} />\n ))}\n </AvatarStack>\n {overflowCount > 0 ? (\n <span className={cn('shrink-0 text-xs', tone.subClassName)}>+{overflowCount}</span>\n ) : null}\n </>\n ) : null}\n <span className=\"ms-auto flex min-w-0 items-center gap-1.5\">\n <LocationMeta item={item} subClassName={tone.subClassName} accentColor={item.color} />\n </span>\n </span>\n ) : null}\n </Button>\n )\n})\n\nEventBlock.displayName = 'EventBlock'\n"],
5
+ "mappings": "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",
6
+ "names": ["EventBlock"]
7
+ }
@@ -0,0 +1,72 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Sparkles } from "lucide-react";
5
+ import { useLocale, useT } from "@open-mercato/shared/lib/i18n/context";
6
+ import { Button } from "@open-mercato/ui/primitives/button";
7
+ import { Popover, PopoverContent, PopoverTrigger } from "@open-mercato/ui/primitives/popover";
8
+ import { formatTimeRange } from "./EventBlock.js";
9
+ const PLATFORM_FULL_LABELS = {
10
+ zoom: { key: "customers.calendar.platformFull.zoom", fallback: "Zoom" },
11
+ meet: { key: "customers.calendar.platformFull.meet", fallback: "Google Meet" },
12
+ slack: { key: "customers.calendar.platformFull.slack", fallback: "Slack" },
13
+ teams: { key: "customers.calendar.platformFull.teams", fallback: "Microsoft Teams" }
14
+ };
15
+ function EventPeekPopover({
16
+ item,
17
+ open,
18
+ joinUrl,
19
+ aiSummaries,
20
+ onOpenChange,
21
+ onJoin,
22
+ onEdit,
23
+ children
24
+ }) {
25
+ const t = useT();
26
+ const locale = useLocale();
27
+ const title = item.title || t("customers.calendar.grid.untitled", "Untitled");
28
+ const dateLabel = React.useMemo(
29
+ () => new Intl.DateTimeFormat(locale, { weekday: "short", month: "short", day: "numeric" }).format(item.start),
30
+ [locale, item.start]
31
+ );
32
+ const timeRange = item.allDay ? t("customers.calendar.grid.allDay", "All day") : formatTimeRange(locale, item.start, item.end);
33
+ const attendeeCount = item.participants.length;
34
+ const attendeesLabel = attendeeCount === 1 ? t("customers.calendar.peek.attendee", "1 attendee") : t("customers.calendar.peek.attendees", "{count} attendees", { count: attendeeCount });
35
+ const platformLabel = item.locationKind === "platform" && item.platform ? t(PLATFORM_FULL_LABELS[item.platform].key, PLATFORM_FULL_LABELS[item.platform].fallback) : null;
36
+ const metaParts = [platformLabel, attendeeCount > 0 ? attendeesLabel : null].filter(
37
+ (part) => Boolean(part)
38
+ );
39
+ const showSummary = aiSummaries && metaParts.length > 0;
40
+ const showJoin = aiSummaries && Boolean(joinUrl);
41
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange, children: [
42
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children }),
43
+ /* @__PURE__ */ jsx(PopoverContent, { align: "start", side: "right", sideOffset: 8, className: "w-56 p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
44
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold leading-5 text-foreground", children: title }),
45
+ /* @__PURE__ */ jsx("p", { className: "text-xs leading-4 text-muted-foreground", children: `${dateLabel} \xB7 ${timeRange}` }),
46
+ showSummary ? /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1 text-xs leading-4 text-muted-foreground", children: [
47
+ /* @__PURE__ */ jsx(Sparkles, { "aria-hidden": true, className: "size-3.5 shrink-0" }),
48
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: metaParts.join(" \xB7 ") })
49
+ ] }) : null,
50
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-1", children: [
51
+ showJoin ? /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => onJoin(item), children: t("customers.calendar.peek.join", "Join") }) : null,
52
+ /* @__PURE__ */ jsx(
53
+ Button,
54
+ {
55
+ type: "button",
56
+ size: "sm",
57
+ variant: "secondary",
58
+ onClick: () => {
59
+ onOpenChange(false);
60
+ onEdit(item);
61
+ },
62
+ children: t("customers.calendar.peek.edit", "Edit")
63
+ }
64
+ )
65
+ ] })
66
+ ] }) })
67
+ ] });
68
+ }
69
+ export {
70
+ EventPeekPopover
71
+ };
72
+ //# sourceMappingURL=EventPeekPopover.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/components/calendar/EventPeekPopover.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Sparkles } from 'lucide-react'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Popover, PopoverContent, PopoverTrigger } from '@open-mercato/ui/primitives/popover'\nimport { formatTimeRange } from './EventBlock'\nimport type { CalendarItem, CalendarPlatform } from './types'\n\nconst PLATFORM_FULL_LABELS: Record<CalendarPlatform, { key: string; fallback: string }> = {\n zoom: { key: 'customers.calendar.platformFull.zoom', fallback: 'Zoom' },\n meet: { key: 'customers.calendar.platformFull.meet', fallback: 'Google Meet' },\n slack: { key: 'customers.calendar.platformFull.slack', fallback: 'Slack' },\n teams: { key: 'customers.calendar.platformFull.teams', fallback: 'Microsoft Teams' },\n}\n\nexport type EventPeekPopoverProps = {\n item: CalendarItem\n open: boolean\n joinUrl: string | null\n aiSummaries: boolean\n onOpenChange(open: boolean): void\n onJoin(item: CalendarItem): void\n onEdit(item: CalendarItem): void\n children: React.ReactNode\n}\n\nexport function EventPeekPopover({\n item,\n open,\n joinUrl,\n aiSummaries,\n onOpenChange,\n onJoin,\n onEdit,\n children,\n}: EventPeekPopoverProps) {\n const t = useT()\n const locale = useLocale()\n const title = item.title || t('customers.calendar.grid.untitled', 'Untitled')\n const dateLabel = React.useMemo(\n () => new Intl.DateTimeFormat(locale, { weekday: 'short', month: 'short', day: 'numeric' }).format(item.start),\n [locale, item.start],\n )\n const timeRange = item.allDay\n ? t('customers.calendar.grid.allDay', 'All day')\n : formatTimeRange(locale, item.start, item.end)\n\n const attendeeCount = item.participants.length\n const attendeesLabel =\n attendeeCount === 1\n ? t('customers.calendar.peek.attendee', '1 attendee')\n : t('customers.calendar.peek.attendees', '{count} attendees', { count: attendeeCount })\n const platformLabel =\n item.locationKind === 'platform' && item.platform\n ? t(PLATFORM_FULL_LABELS[item.platform].key, PLATFORM_FULL_LABELS[item.platform].fallback)\n : null\n const metaParts = [platformLabel, attendeeCount > 0 ? attendeesLabel : null].filter(\n (part): part is string => Boolean(part),\n )\n const showSummary = aiSummaries && metaParts.length > 0\n const showJoin = aiSummaries && Boolean(joinUrl)\n\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent align=\"start\" side=\"right\" sideOffset={8} className=\"w-56 p-3\">\n <div className=\"flex flex-col gap-2\">\n <p className=\"text-sm font-semibold leading-5 text-foreground\">{title}</p>\n <p className=\"text-xs leading-4 text-muted-foreground\">{`${dateLabel} \u00B7 ${timeRange}`}</p>\n {showSummary ? (\n <p className=\"flex items-center gap-1 text-xs leading-4 text-muted-foreground\">\n <Sparkles aria-hidden className=\"size-3.5 shrink-0\" />\n <span className=\"truncate\">{metaParts.join(' \u00B7 ')}</span>\n </p>\n ) : null}\n <div className=\"flex items-center gap-2 pt-1\">\n {showJoin ? (\n <Button type=\"button\" size=\"sm\" onClick={() => onJoin(item)}>\n {t('customers.calendar.peek.join', 'Join')}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => {\n onOpenChange(false)\n onEdit(item)\n }}\n >\n {t('customers.calendar.peek.edit', 'Edit')}\n </Button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n )\n}\n"],
5
+ "mappings": ";AAkEM,cAMM,YANN;AAhEN,YAAY,WAAW;AACvB,SAAS,gBAAgB;AACzB,SAAS,WAAW,YAAY;AAChC,SAAS,cAAc;AACvB,SAAS,SAAS,gBAAgB,sBAAsB;AACxD,SAAS,uBAAuB;AAGhC,MAAM,uBAAoF;AAAA,EACxF,MAAM,EAAE,KAAK,wCAAwC,UAAU,OAAO;AAAA,EACtE,MAAM,EAAE,KAAK,wCAAwC,UAAU,cAAc;AAAA,EAC7E,OAAO,EAAE,KAAK,yCAAyC,UAAU,QAAQ;AAAA,EACzE,OAAO,EAAE,KAAK,yCAAyC,UAAU,kBAAkB;AACrF;AAaO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,QAAQ,KAAK,SAAS,EAAE,oCAAoC,UAAU;AAC5E,QAAM,YAAY,MAAM;AAAA,IACtB,MAAM,IAAI,KAAK,eAAe,QAAQ,EAAE,SAAS,SAAS,OAAO,SAAS,KAAK,UAAU,CAAC,EAAE,OAAO,KAAK,KAAK;AAAA,IAC7G,CAAC,QAAQ,KAAK,KAAK;AAAA,EACrB;AACA,QAAM,YAAY,KAAK,SACnB,EAAE,kCAAkC,SAAS,IAC7C,gBAAgB,QAAQ,KAAK,OAAO,KAAK,GAAG;AAEhD,QAAM,gBAAgB,KAAK,aAAa;AACxC,QAAM,iBACJ,kBAAkB,IACd,EAAE,oCAAoC,YAAY,IAClD,EAAE,qCAAqC,qBAAqB,EAAE,OAAO,cAAc,CAAC;AAC1F,QAAM,gBACJ,KAAK,iBAAiB,cAAc,KAAK,WACrC,EAAE,qBAAqB,KAAK,QAAQ,EAAE,KAAK,qBAAqB,KAAK,QAAQ,EAAE,QAAQ,IACvF;AACN,QAAM,YAAY,CAAC,eAAe,gBAAgB,IAAI,iBAAiB,IAAI,EAAE;AAAA,IAC3E,CAAC,SAAyB,QAAQ,IAAI;AAAA,EACxC;AACA,QAAM,cAAc,eAAe,UAAU,SAAS;AACtD,QAAM,WAAW,eAAe,QAAQ,OAAO;AAE/C,SACE,qBAAC,WAAQ,MAAY,cACnB;AAAA,wBAAC,kBAAe,SAAO,MAAE,UAAS;AAAA,IAClC,oBAAC,kBAAe,OAAM,SAAQ,MAAK,SAAQ,YAAY,GAAG,WAAU,YAClE,+BAAC,SAAI,WAAU,uBACb;AAAA,0BAAC,OAAE,WAAU,mDAAmD,iBAAM;AAAA,MACtE,oBAAC,OAAE,WAAU,2CAA2C,aAAG,SAAS,SAAM,SAAS,IAAG;AAAA,MACrF,cACC,qBAAC,OAAE,WAAU,mEACX;AAAA,4BAAC,YAAS,eAAW,MAAC,WAAU,qBAAoB;AAAA,QACpD,oBAAC,UAAK,WAAU,YAAY,oBAAU,KAAK,QAAK,GAAE;AAAA,SACpD,IACE;AAAA,MACJ,qBAAC,SAAI,WAAU,gCACZ;AAAA,mBACC,oBAAC,UAAO,MAAK,UAAS,MAAK,MAAK,SAAS,MAAM,OAAO,IAAI,GACvD,YAAE,gCAAgC,MAAM,GAC3C,IACE;AAAA,QACJ;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,SAAS,MAAM;AACb,2BAAa,KAAK;AAClB,qBAAO,IAAI;AAAA,YACb;AAAA,YAEC,YAAE,gCAAgC,MAAM;AAAA;AAAA,QAC3C;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,214 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { addDays } from "date-fns/addDays";
5
+ import { format } from "date-fns/format";
6
+ import { isSameMonth } from "date-fns/isSameMonth";
7
+ import { isToday } from "date-fns/isToday";
8
+ import { CalendarDays } from "lucide-react";
9
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
10
+ import { cn } from "@open-mercato/shared/lib/utils";
11
+ import { Button } from "@open-mercato/ui/primitives/button";
12
+ import { EmptyState } from "@open-mercato/ui/primitives/empty-state";
13
+ import { getVisibleRange } from "../../lib/calendar/range.js";
14
+ const MAX_PILLS_PER_DAY = 2;
15
+ const SOFT_TINT_ALPHA = "1A";
16
+ function dayKeyOf(date) {
17
+ return format(date, "yyyy-MM-dd");
18
+ }
19
+ function formatTime(date) {
20
+ return date.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
21
+ }
22
+ function fullDateLabel(date) {
23
+ return date.toLocaleDateString(void 0, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
24
+ }
25
+ function isWeekend(date) {
26
+ const weekday = date.getDay();
27
+ return weekday === 0 || weekday === 6;
28
+ }
29
+ function buildWeeks(anchor) {
30
+ const range = getVisibleRange("month", anchor, 0);
31
+ const weeks = [];
32
+ let cursor = range.from;
33
+ while (cursor.getTime() <= range.to.getTime()) {
34
+ const week = [];
35
+ for (let dayIndex = 0; dayIndex < 7; dayIndex += 1) {
36
+ week.push(cursor);
37
+ cursor = addDays(cursor, 1);
38
+ }
39
+ weeks.push(week);
40
+ }
41
+ return weeks;
42
+ }
43
+ function groupItemsByDay(items) {
44
+ const sorted = [...items].sort((first, second) => first.start.getTime() - second.start.getTime());
45
+ const byDay = /* @__PURE__ */ new Map();
46
+ for (const item of sorted) {
47
+ const key = dayKeyOf(item.start);
48
+ const bucket = byDay.get(key);
49
+ if (bucket) bucket.push(item);
50
+ else byDay.set(key, [item]);
51
+ }
52
+ return byDay;
53
+ }
54
+ function MonthPill({ item, onItemClick }) {
55
+ const canceled = item.status === "canceled";
56
+ const timeLabel = item.allDay ? "" : ` \xB7 ${formatTime(item.start)} \u2013 ${formatTime(item.end)}`;
57
+ const tintStyle = item.color ? { backgroundColor: `${item.color}${SOFT_TINT_ALPHA}`, color: item.color } : void 0;
58
+ return /* @__PURE__ */ jsxs(
59
+ Button,
60
+ {
61
+ type: "button",
62
+ variant: "ghost",
63
+ "aria-label": `${item.title}${timeLabel}`,
64
+ onClick: (event) => {
65
+ event.stopPropagation();
66
+ onItemClick(item);
67
+ },
68
+ className: cn(
69
+ "h-4 w-full min-w-0 justify-center gap-0 rounded-full p-0 pr-2",
70
+ !item.color && "bg-muted text-muted-foreground",
71
+ canceled && "opacity-60"
72
+ ),
73
+ style: tintStyle,
74
+ children: [
75
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex size-4 shrink-0 items-center justify-center", children: /* @__PURE__ */ jsx(
76
+ "span",
77
+ {
78
+ className: cn("size-1.5 rounded-full", !item.color && "bg-muted-foreground"),
79
+ style: item.color ? { backgroundColor: item.color } : void 0
80
+ }
81
+ ) }),
82
+ /* @__PURE__ */ jsx(
83
+ "span",
84
+ {
85
+ className: cn(
86
+ "min-w-0 truncate text-overline font-medium uppercase tracking-wide",
87
+ canceled && "line-through"
88
+ ),
89
+ children: item.title
90
+ }
91
+ )
92
+ ]
93
+ }
94
+ );
95
+ }
96
+ function MonthDayCell({
97
+ day,
98
+ anchor,
99
+ items,
100
+ onItemClick,
101
+ onDayOpen
102
+ }) {
103
+ const t = useT();
104
+ const inMonth = isSameMonth(day, anchor);
105
+ const today = isToday(day);
106
+ const visibleItems = items.slice(0, MAX_PILLS_PER_DAY);
107
+ const hiddenCount = items.length - visibleItems.length;
108
+ const dayLabel = fullDateLabel(day);
109
+ return /* @__PURE__ */ jsxs(
110
+ "div",
111
+ {
112
+ className: cn(
113
+ "relative flex h-full min-w-0 flex-1 flex-col items-start gap-1 overflow-hidden border-r border-border p-2 text-left last:border-r-0",
114
+ isWeekend(day) ? "bg-muted/40" : "bg-background"
115
+ ),
116
+ children: [
117
+ /* @__PURE__ */ jsx(
118
+ Button,
119
+ {
120
+ type: "button",
121
+ variant: "ghost",
122
+ "aria-label": dayLabel,
123
+ onClick: () => onDayOpen(day),
124
+ className: "absolute inset-0 z-0 h-full w-full rounded-none p-0 hover:bg-muted/50",
125
+ children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: dayLabel })
126
+ }
127
+ ),
128
+ today ? /* @__PURE__ */ jsx("span", { className: "pointer-events-none relative z-10 flex items-center justify-center rounded-full bg-primary px-1.5 py-0.5 text-xs font-semibold text-primary-foreground", children: day.getDate() }) : /* @__PURE__ */ jsx("span", { className: cn("pointer-events-none relative z-10 text-xs font-medium", inMonth ? "text-foreground" : "text-muted-foreground"), children: day.getDate() }),
129
+ /* @__PURE__ */ jsxs("span", { className: "relative z-20 hidden w-full flex-col gap-1 sm:flex", children: [
130
+ visibleItems.map((item) => /* @__PURE__ */ jsx(MonthPill, { item, onItemClick }, item.id)),
131
+ hiddenCount > 0 ? /* @__PURE__ */ jsx(
132
+ Button,
133
+ {
134
+ type: "button",
135
+ variant: "ghost",
136
+ size: "sm",
137
+ className: "h-auto self-start p-0 text-overline font-medium text-muted-foreground hover:bg-transparent hover:underline",
138
+ onClick: (event) => {
139
+ event.stopPropagation();
140
+ onDayOpen(day);
141
+ },
142
+ children: t("customers.calendar.grid.more", "+{count} more", { count: hiddenCount })
143
+ }
144
+ ) : null
145
+ ] }),
146
+ items.length > 0 ? /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "pointer-events-none relative z-10 flex w-full flex-wrap items-center gap-0.5 sm:hidden", children: [
147
+ items.slice(0, 4).map((item) => /* @__PURE__ */ jsx(
148
+ "span",
149
+ {
150
+ className: cn("size-1.5 rounded-full", !item.color && "bg-muted-foreground"),
151
+ style: item.color ? { backgroundColor: item.color } : void 0
152
+ },
153
+ item.id
154
+ )),
155
+ items.length > 4 ? /* @__PURE__ */ jsxs("span", { className: "text-overline font-medium leading-none text-muted-foreground", children: [
156
+ "+",
157
+ items.length - 4
158
+ ] }) : null
159
+ ] }) : null
160
+ ]
161
+ }
162
+ );
163
+ }
164
+ function MonthGrid({ anchor, items, onItemClick, onDayOpen }) {
165
+ const t = useT();
166
+ const weeks = React.useMemo(() => buildWeeks(anchor), [anchor]);
167
+ const itemsByDay = React.useMemo(() => groupItemsByDay(items), [items]);
168
+ return /* @__PURE__ */ jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden border border-border bg-background", children: [
169
+ /* @__PURE__ */ jsx("div", { className: "flex h-9 w-full shrink-0 border-b border-border", children: weeks[0]?.map((day) => {
170
+ const label = day.toLocaleDateString(void 0, { weekday: "short" }).toUpperCase();
171
+ return /* @__PURE__ */ jsx(
172
+ "div",
173
+ {
174
+ className: "flex min-w-0 flex-1 items-center justify-center border-r border-border last:border-r-0 sm:justify-start sm:pl-2.5",
175
+ children: /* @__PURE__ */ jsxs("span", { className: "truncate text-overline font-medium uppercase tracking-widest text-muted-foreground", children: [
176
+ /* @__PURE__ */ jsx("span", { className: "sm:hidden", children: label.charAt(0) }),
177
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: label })
178
+ ] })
179
+ },
180
+ dayKeyOf(day)
181
+ );
182
+ }) }),
183
+ weeks.map((week) => /* @__PURE__ */ jsx(
184
+ "div",
185
+ {
186
+ className: "flex w-full flex-1 border-b border-border last:border-b-0 min-h-14 sm:min-h-[86px]",
187
+ children: week.map((day) => /* @__PURE__ */ jsx(
188
+ MonthDayCell,
189
+ {
190
+ day,
191
+ anchor,
192
+ items: itemsByDay.get(dayKeyOf(day)) ?? [],
193
+ onItemClick,
194
+ onDayOpen
195
+ },
196
+ dayKeyOf(day)
197
+ ))
198
+ },
199
+ dayKeyOf(week[0])
200
+ )),
201
+ items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center p-6", children: /* @__PURE__ */ jsx(
202
+ EmptyState,
203
+ {
204
+ icon: /* @__PURE__ */ jsx(CalendarDays, { className: "h-6 w-6", "aria-hidden": "true" }),
205
+ title: t("customers.calendar.empty.month", "Nothing scheduled this month"),
206
+ className: "bg-background/90"
207
+ }
208
+ ) }) : null
209
+ ] });
210
+ }
211
+ export {
212
+ MonthGrid
213
+ };
214
+ //# sourceMappingURL=MonthGrid.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/components/calendar/MonthGrid.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { addDays } from 'date-fns/addDays'\nimport { format } from 'date-fns/format'\nimport { isSameMonth } from 'date-fns/isSameMonth'\nimport { isToday } from 'date-fns/isToday'\nimport { CalendarDays } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { getVisibleRange } from '../../lib/calendar/range'\nimport type { CalendarItem, MonthGridProps } from './types'\n\nconst MAX_PILLS_PER_DAY = 2\nconst SOFT_TINT_ALPHA = '1A'\n\nfunction dayKeyOf(date: Date): string {\n return format(date, 'yyyy-MM-dd')\n}\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' })\n}\n\nfunction fullDateLabel(date: Date): string {\n return date.toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })\n}\n\nfunction isWeekend(date: Date): boolean {\n const weekday = date.getDay()\n return weekday === 0 || weekday === 6\n}\n\nfunction buildWeeks(anchor: Date): Date[][] {\n const range = getVisibleRange('month', anchor, 0)\n const weeks: Date[][] = []\n let cursor = range.from\n while (cursor.getTime() <= range.to.getTime()) {\n const week: Date[] = []\n for (let dayIndex = 0; dayIndex < 7; dayIndex += 1) {\n week.push(cursor)\n cursor = addDays(cursor, 1)\n }\n weeks.push(week)\n }\n return weeks\n}\n\nfunction groupItemsByDay(items: CalendarItem[]): Map<string, CalendarItem[]> {\n const sorted = [...items].sort((first, second) => first.start.getTime() - second.start.getTime())\n const byDay = new Map<string, CalendarItem[]>()\n for (const item of sorted) {\n const key = dayKeyOf(item.start)\n const bucket = byDay.get(key)\n if (bucket) bucket.push(item)\n else byDay.set(key, [item])\n }\n return byDay\n}\n\nfunction MonthPill({ item, onItemClick }: { item: CalendarItem; onItemClick: (item: CalendarItem) => void }) {\n const canceled = item.status === 'canceled'\n const timeLabel = item.allDay ? '' : ` \u00B7 ${formatTime(item.start)} \u2013 ${formatTime(item.end)}`\n const tintStyle = item.color\n ? { backgroundColor: `${item.color}${SOFT_TINT_ALPHA}`, color: item.color }\n : undefined\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n aria-label={`${item.title}${timeLabel}`}\n onClick={(event) => {\n event.stopPropagation()\n onItemClick(item)\n }}\n className={cn(\n 'h-4 w-full min-w-0 justify-center gap-0 rounded-full p-0 pr-2',\n !item.color && 'bg-muted text-muted-foreground',\n canceled && 'opacity-60',\n )}\n style={tintStyle}\n >\n <span aria-hidden=\"true\" className=\"flex size-4 shrink-0 items-center justify-center\">\n <span\n className={cn('size-1.5 rounded-full', !item.color && 'bg-muted-foreground')}\n style={item.color ? { backgroundColor: item.color } : undefined}\n />\n </span>\n <span\n className={cn(\n 'min-w-0 truncate text-overline font-medium uppercase tracking-wide',\n canceled && 'line-through',\n )}\n >\n {item.title}\n </span>\n </Button>\n )\n}\n\nfunction MonthDayCell({\n day,\n anchor,\n items,\n onItemClick,\n onDayOpen,\n}: {\n day: Date\n anchor: Date\n items: CalendarItem[]\n onItemClick: (item: CalendarItem) => void\n onDayOpen: (date: Date) => void\n}) {\n const t = useT()\n const inMonth = isSameMonth(day, anchor)\n const today = isToday(day)\n const visibleItems = items.slice(0, MAX_PILLS_PER_DAY)\n const hiddenCount = items.length - visibleItems.length\n const dayLabel = fullDateLabel(day)\n return (\n <div\n className={cn(\n 'relative flex h-full min-w-0 flex-1 flex-col items-start gap-1 overflow-hidden border-r border-border p-2 text-left last:border-r-0',\n isWeekend(day) ? 'bg-muted/40' : 'bg-background',\n )}\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n aria-label={dayLabel}\n onClick={() => onDayOpen(day)}\n className=\"absolute inset-0 z-0 h-full w-full rounded-none p-0 hover:bg-muted/50\"\n >\n <span className=\"sr-only\">{dayLabel}</span>\n </Button>\n {today ? (\n <span className=\"pointer-events-none relative z-10 flex items-center justify-center rounded-full bg-primary px-1.5 py-0.5 text-xs font-semibold text-primary-foreground\">\n {day.getDate()}\n </span>\n ) : (\n <span className={cn('pointer-events-none relative z-10 text-xs font-medium', inMonth ? 'text-foreground' : 'text-muted-foreground')}>\n {day.getDate()}\n </span>\n )}\n <span className=\"relative z-20 hidden w-full flex-col gap-1 sm:flex\">\n {visibleItems.map((item) => (\n <MonthPill key={item.id} item={item} onItemClick={onItemClick} />\n ))}\n {hiddenCount > 0 ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto self-start p-0 text-overline font-medium text-muted-foreground hover:bg-transparent hover:underline\"\n onClick={(event) => {\n event.stopPropagation()\n onDayOpen(day)\n }}\n >\n {t('customers.calendar.grid.more', '+{count} more', { count: hiddenCount })}\n </Button>\n ) : null}\n </span>\n {items.length > 0 ? (\n <span aria-hidden=\"true\" className=\"pointer-events-none relative z-10 flex w-full flex-wrap items-center gap-0.5 sm:hidden\">\n {items.slice(0, 4).map((item) => (\n <span\n key={item.id}\n className={cn('size-1.5 rounded-full', !item.color && 'bg-muted-foreground')}\n style={item.color ? { backgroundColor: item.color } : undefined}\n />\n ))}\n {items.length > 4 ? (\n <span className=\"text-overline font-medium leading-none text-muted-foreground\">\n +{items.length - 4}\n </span>\n ) : null}\n </span>\n ) : null}\n </div>\n )\n}\n\nexport function MonthGrid({ anchor, items, onItemClick, onDayOpen }: MonthGridProps) {\n const t = useT()\n const weeks = React.useMemo(() => buildWeeks(anchor), [anchor])\n const itemsByDay = React.useMemo(() => groupItemsByDay(items), [items])\n return (\n <div className=\"relative flex h-full w-full flex-col overflow-hidden border border-border bg-background\">\n <div className=\"flex h-9 w-full shrink-0 border-b border-border\">\n {weeks[0]?.map((day) => {\n const label = day.toLocaleDateString(undefined, { weekday: 'short' }).toUpperCase()\n return (\n <div\n key={dayKeyOf(day)}\n className=\"flex min-w-0 flex-1 items-center justify-center border-r border-border last:border-r-0 sm:justify-start sm:pl-2.5\"\n >\n <span className=\"truncate text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n <span className=\"sm:hidden\">{label.charAt(0)}</span>\n <span className=\"hidden sm:inline\">{label}</span>\n </span>\n </div>\n )\n })}\n </div>\n {weeks.map((week) => (\n <div\n key={dayKeyOf(week[0])}\n className=\"flex w-full flex-1 border-b border-border last:border-b-0 min-h-14 sm:min-h-[86px]\"\n >\n {week.map((day) => (\n <MonthDayCell\n key={dayKeyOf(day)}\n day={day}\n anchor={anchor}\n items={itemsByDay.get(dayKeyOf(day)) ?? []}\n onItemClick={onItemClick}\n onDayOpen={onDayOpen}\n />\n ))}\n </div>\n ))}\n {items.length === 0 ? (\n <div className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-center p-6\">\n <EmptyState\n icon={<CalendarDays className=\"h-6 w-6\" aria-hidden=\"true\" />}\n title={t('customers.calendar.empty.month', 'Nothing scheduled this month')}\n className=\"bg-background/90\"\n />\n </div>\n ) : null}\n </div>\n )\n}\n"],
5
+ "mappings": ";AAqEI,SAgBI,KAhBJ;AAnEJ,YAAY,WAAW;AACvB,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,YAAY;AACrB,SAAS,UAAU;AACnB,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAGhC,MAAM,oBAAoB;AAC1B,MAAM,kBAAkB;AAExB,SAAS,SAAS,MAAoB;AACpC,SAAO,OAAO,MAAM,YAAY;AAClC;AAEA,SAAS,WAAW,MAAoB;AACtC,SAAO,KAAK,mBAAmB,QAAW,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AAClF;AAEA,SAAS,cAAc,MAAoB;AACzC,SAAO,KAAK,mBAAmB,QAAW,EAAE,SAAS,QAAQ,MAAM,WAAW,OAAO,QAAQ,KAAK,UAAU,CAAC;AAC/G;AAEA,SAAS,UAAU,MAAqB;AACtC,QAAM,UAAU,KAAK,OAAO;AAC5B,SAAO,YAAY,KAAK,YAAY;AACtC;AAEA,SAAS,WAAW,QAAwB;AAC1C,QAAM,QAAQ,gBAAgB,SAAS,QAAQ,CAAC;AAChD,QAAM,QAAkB,CAAC;AACzB,MAAI,SAAS,MAAM;AACnB,SAAO,OAAO,QAAQ,KAAK,MAAM,GAAG,QAAQ,GAAG;AAC7C,UAAM,OAAe,CAAC;AACtB,aAAS,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG;AAClD,WAAK,KAAK,MAAM;AAChB,eAAS,QAAQ,QAAQ,CAAC;AAAA,IAC5B;AACA,UAAM,KAAK,IAAI;AAAA,EACjB;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAoD;AAC3E,QAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,OAAO,WAAW,MAAM,MAAM,QAAQ,IAAI,OAAO,MAAM,QAAQ,CAAC;AAChG,QAAM,QAAQ,oBAAI,IAA4B;AAC9C,aAAW,QAAQ,QAAQ;AACzB,UAAM,MAAM,SAAS,KAAK,KAAK;AAC/B,UAAM,SAAS,MAAM,IAAI,GAAG;AAC5B,QAAI,OAAQ,QAAO,KAAK,IAAI;AAAA,QACvB,OAAM,IAAI,KAAK,CAAC,IAAI,CAAC;AAAA,EAC5B;AACA,SAAO;AACT;AAEA,SAAS,UAAU,EAAE,MAAM,YAAY,GAAsE;AAC3G,QAAM,WAAW,KAAK,WAAW;AACjC,QAAM,YAAY,KAAK,SAAS,KAAK,SAAM,WAAW,KAAK,KAAK,CAAC,WAAM,WAAW,KAAK,GAAG,CAAC;AAC3F,QAAM,YAAY,KAAK,QACnB,EAAE,iBAAiB,GAAG,KAAK,KAAK,GAAG,eAAe,IAAI,OAAO,KAAK,MAAM,IACxE;AACJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAQ;AAAA,MACR,cAAY,GAAG,KAAK,KAAK,GAAG,SAAS;AAAA,MACrC,SAAS,CAAC,UAAU;AAClB,cAAM,gBAAgB;AACtB,oBAAY,IAAI;AAAA,MAClB;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,CAAC,KAAK,SAAS;AAAA,QACf,YAAY;AAAA,MACd;AAAA,MACA,OAAO;AAAA,MAEP;AAAA,4BAAC,UAAK,eAAY,QAAO,WAAU,oDACjC;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,GAAG,yBAAyB,CAAC,KAAK,SAAS,qBAAqB;AAAA,YAC3E,OAAO,KAAK,QAAQ,EAAE,iBAAiB,KAAK,MAAM,IAAI;AAAA;AAAA,QACxD,GACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,YAAY;AAAA,YACd;AAAA,YAEC,eAAK;AAAA;AAAA,QACR;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,IAAI,KAAK;AACf,QAAM,UAAU,YAAY,KAAK,MAAM;AACvC,QAAM,QAAQ,QAAQ,GAAG;AACzB,QAAM,eAAe,MAAM,MAAM,GAAG,iBAAiB;AACrD,QAAM,cAAc,MAAM,SAAS,aAAa;AAChD,QAAM,WAAW,cAAc,GAAG;AAClC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,UAAU,GAAG,IAAI,gBAAgB;AAAA,MACnC;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,cAAY;AAAA,YACZ,SAAS,MAAM,UAAU,GAAG;AAAA,YAC5B,WAAU;AAAA,YAEV,8BAAC,UAAK,WAAU,WAAW,oBAAS;AAAA;AAAA,QACtC;AAAA,QACC,QACC,oBAAC,UAAK,WAAU,0JACb,cAAI,QAAQ,GACf,IAEA,oBAAC,UAAK,WAAW,GAAG,yDAAyD,UAAU,oBAAoB,uBAAuB,GAC/H,cAAI,QAAQ,GACf;AAAA,QAEF,qBAAC,UAAK,WAAU,sDACb;AAAA,uBAAa,IAAI,CAAC,SACjB,oBAAC,aAAwB,MAAY,eAArB,KAAK,EAA0C,CAChE;AAAA,UACA,cAAc,IACb;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,CAAC,UAAU;AAClB,sBAAM,gBAAgB;AACtB,0BAAU,GAAG;AAAA,cACf;AAAA,cAEC,YAAE,gCAAgC,iBAAiB,EAAE,OAAO,YAAY,CAAC;AAAA;AAAA,UAC5E,IACE;AAAA,WACN;AAAA,QACC,MAAM,SAAS,IACd,qBAAC,UAAK,eAAY,QAAO,WAAU,0FAChC;AAAA,gBAAM,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,SACtB;AAAA,YAAC;AAAA;AAAA,cAEC,WAAW,GAAG,yBAAyB,CAAC,KAAK,SAAS,qBAAqB;AAAA,cAC3E,OAAO,KAAK,QAAQ,EAAE,iBAAiB,KAAK,MAAM,IAAI;AAAA;AAAA,YAFjD,KAAK;AAAA,UAGZ,CACD;AAAA,UACA,MAAM,SAAS,IACd,qBAAC,UAAK,WAAU,gEAA+D;AAAA;AAAA,YAC3E,MAAM,SAAS;AAAA,aACnB,IACE;AAAA,WACN,IACE;AAAA;AAAA;AAAA,EACN;AAEJ;AAEO,SAAS,UAAU,EAAE,QAAQ,OAAO,aAAa,UAAU,GAAmB;AACnF,QAAM,IAAI,KAAK;AACf,QAAM,QAAQ,MAAM,QAAQ,MAAM,WAAW,MAAM,GAAG,CAAC,MAAM,CAAC;AAC9D,QAAM,aAAa,MAAM,QAAQ,MAAM,gBAAgB,KAAK,GAAG,CAAC,KAAK,CAAC;AACtE,SACE,qBAAC,SAAI,WAAU,2FACb;AAAA,wBAAC,SAAI,WAAU,mDACZ,gBAAM,CAAC,GAAG,IAAI,CAAC,QAAQ;AACtB,YAAM,QAAQ,IAAI,mBAAmB,QAAW,EAAE,SAAS,QAAQ,CAAC,EAAE,YAAY;AAClF,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAEV,+BAAC,UAAK,WAAU,sFACd;AAAA,gCAAC,UAAK,WAAU,aAAa,gBAAM,OAAO,CAAC,GAAE;AAAA,YAC7C,oBAAC,UAAK,WAAU,oBAAoB,iBAAM;AAAA,aAC5C;AAAA;AAAA,QANK,SAAS,GAAG;AAAA,MAOnB;AAAA,IAEJ,CAAC,GACH;AAAA,IACC,MAAM,IAAI,CAAC,SACV;AAAA,MAAC;AAAA;AAAA,QAEC,WAAU;AAAA,QAET,eAAK,IAAI,CAAC,QACT;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA;AAAA,YACA,OAAO,WAAW,IAAI,SAAS,GAAG,CAAC,KAAK,CAAC;AAAA,YACzC;AAAA,YACA;AAAA;AAAA,UALK,SAAS,GAAG;AAAA,QAMnB,CACD;AAAA;AAAA,MAZI,SAAS,KAAK,CAAC,CAAC;AAAA,IAavB,CACD;AAAA,IACA,MAAM,WAAW,IAChB,oBAAC,SAAI,WAAU,kFACb;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,oBAAC,gBAAa,WAAU,WAAU,eAAY,QAAO;AAAA,QAC3D,OAAO,EAAE,kCAAkC,8BAA8B;AAAA,QACzE,WAAU;AAAA;AAAA,IACZ,GACF,IACE;AAAA,KACN;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,44 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ Dialog,
5
+ DialogContent,
6
+ DialogDescription,
7
+ DialogHeader,
8
+ DialogTitle
9
+ } from "@open-mercato/ui/primitives/dialog";
10
+ import { Kbd } from "@open-mercato/ui/primitives/kbd";
11
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
12
+ import { CALENDAR_SHORTCUTS } from "./CalendarFooter.js";
13
+ function ShortcutsDialog({ open, onOpenChange }) {
14
+ const t = useT();
15
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
16
+ DialogContent,
17
+ {
18
+ size: "sm",
19
+ onKeyDown: (event) => {
20
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
21
+ event.preventDefault();
22
+ onOpenChange(false);
23
+ }
24
+ },
25
+ children: [
26
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
27
+ /* @__PURE__ */ jsx(DialogTitle, { children: t("customers.calendar.shortcuts.title", "Keyboard shortcuts") }),
28
+ /* @__PURE__ */ jsx(DialogDescription, { children: t(
29
+ "customers.calendar.shortcuts.description",
30
+ "Navigate the calendar faster with these keys."
31
+ ) })
32
+ ] }),
33
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: CALENDAR_SHORTCUTS.map((shortcut) => /* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-3", children: [
34
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: t(shortcut.labelKey, shortcut.fallback) }),
35
+ /* @__PURE__ */ jsx(Kbd, { children: shortcut.key })
36
+ ] }, shortcut.key)) })
37
+ ]
38
+ }
39
+ ) });
40
+ }
41
+ export {
42
+ ShortcutsDialog
43
+ };
44
+ //# sourceMappingURL=ShortcutsDialog.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/components/calendar/ShortcutsDialog.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Kbd } from '@open-mercato/ui/primitives/kbd'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { CALENDAR_SHORTCUTS } from './CalendarFooter'\n\nexport type ShortcutsDialogProps = {\n open: boolean\n onOpenChange(open: boolean): void\n}\n\nexport function ShortcutsDialog({ open, onOpenChange }: ShortcutsDialogProps) {\n const t = useT()\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n size=\"sm\"\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n onOpenChange(false)\n }\n }}\n >\n <DialogHeader>\n <DialogTitle>\n {t('customers.calendar.shortcuts.title', 'Keyboard shortcuts')}\n </DialogTitle>\n <DialogDescription>\n {t(\n 'customers.calendar.shortcuts.description',\n 'Navigate the calendar faster with these keys.',\n )}\n </DialogDescription>\n </DialogHeader>\n <ul className=\"flex flex-col gap-2\">\n {CALENDAR_SHORTCUTS.map((shortcut) => (\n <li key={shortcut.key} className=\"flex items-center justify-between gap-3\">\n <span className=\"text-sm text-muted-foreground\">\n {t(shortcut.labelKey, shortcut.fallback)}\n </span>\n <Kbd>{shortcut.key}</Kbd>\n </li>\n ))}\n </ul>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
+ "mappings": ";AAgCQ,SACE,KADF;AA7BR;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW;AACpB,SAAS,YAAY;AACrB,SAAS,0BAA0B;AAO5B,SAAS,gBAAgB,EAAE,MAAM,aAAa,GAAyB;AAC5E,QAAM,IAAI,KAAK;AACf,SACE,oBAAC,UAAO,MAAY,cAClB;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW,CAAC,UAAU;AACpB,YAAI,MAAM,QAAQ,YAAY,MAAM,WAAW,MAAM,UAAU;AAC7D,gBAAM,eAAe;AACrB,uBAAa,KAAK;AAAA,QACpB;AAAA,MACF;AAAA,MAEA;AAAA,6BAAC,gBACC;AAAA,8BAAC,eACE,YAAE,sCAAsC,oBAAoB,GAC/D;AAAA,UACA,oBAAC,qBACE;AAAA,YACC;AAAA,YACA;AAAA,UACF,GACF;AAAA,WACF;AAAA,QACA,oBAAC,QAAG,WAAU,uBACX,6BAAmB,IAAI,CAAC,aACvB,qBAAC,QAAsB,WAAU,2CAC/B;AAAA,8BAAC,UAAK,WAAU,iCACb,YAAE,SAAS,UAAU,SAAS,QAAQ,GACzC;AAAA,UACA,oBAAC,OAAK,mBAAS,KAAI;AAAA,aAJZ,SAAS,GAKlB,CACD,GACH;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;",
6
+ "names": []
7
+ }