@open-mercato/core 0.4.5-develop-5191db4ef3 → 0.4.5-develop-9f9549ebc8

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 (385) hide show
  1. package/dist/generated/entities/message/index.js +65 -0
  2. package/dist/generated/entities/message/index.js.map +7 -0
  3. package/dist/generated/entities/message_access_token/index.js +19 -0
  4. package/dist/generated/entities/message_access_token/index.js.map +7 -0
  5. package/dist/generated/entities/message_confirmation/index.js +21 -0
  6. package/dist/generated/entities/message_confirmation/index.js.map +7 -0
  7. package/dist/generated/entities/message_object/index.js +23 -0
  8. package/dist/generated/entities/message_object/index.js.map +7 -0
  9. package/dist/generated/entities/message_recipient/index.js +31 -0
  10. package/dist/generated/entities/message_recipient/index.js.map +7 -0
  11. package/dist/generated/entities.ids.generated.js +8 -0
  12. package/dist/generated/entities.ids.generated.js.map +2 -2
  13. package/dist/generated/entity-fields-registry.js +10 -0
  14. package/dist/generated/entity-fields-registry.js.map +2 -2
  15. package/dist/modules/customers/backend/customers/deals/[id]/page.js +27 -8
  16. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  17. package/dist/modules/customers/lib/messageObjectPreviews.js +131 -0
  18. package/dist/modules/customers/lib/messageObjectPreviews.js.map +7 -0
  19. package/dist/modules/customers/message-objects.js +71 -0
  20. package/dist/modules/customers/message-objects.js.map +7 -0
  21. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js +51 -0
  22. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js.map +7 -0
  23. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js +35 -0
  24. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js.map +7 -0
  25. package/dist/modules/customers/widgets/messages/index.js +7 -0
  26. package/dist/modules/customers/widgets/messages/index.js.map +7 -0
  27. package/dist/modules/messages/acl.js +15 -0
  28. package/dist/modules/messages/acl.js.map +7 -0
  29. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js +92 -0
  30. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js.map +7 -0
  31. package/dist/modules/messages/api/[id]/archive/route.js +120 -0
  32. package/dist/modules/messages/api/[id]/archive/route.js.map +7 -0
  33. package/dist/modules/messages/api/[id]/attachments/route.js +195 -0
  34. package/dist/modules/messages/api/[id]/attachments/route.js.map +7 -0
  35. package/dist/modules/messages/api/[id]/confirmation/route.js +67 -0
  36. package/dist/modules/messages/api/[id]/confirmation/route.js.map +7 -0
  37. package/dist/modules/messages/api/[id]/conversation/archive/route.js +68 -0
  38. package/dist/modules/messages/api/[id]/conversation/archive/route.js.map +7 -0
  39. package/dist/modules/messages/api/[id]/conversation/read/route.js +68 -0
  40. package/dist/modules/messages/api/[id]/conversation/read/route.js.map +7 -0
  41. package/dist/modules/messages/api/[id]/conversation/route.js +68 -0
  42. package/dist/modules/messages/api/[id]/conversation/route.js.map +7 -0
  43. package/dist/modules/messages/api/[id]/forward/route.js +85 -0
  44. package/dist/modules/messages/api/[id]/forward/route.js.map +7 -0
  45. package/dist/modules/messages/api/[id]/forward-preview/route.js +70 -0
  46. package/dist/modules/messages/api/[id]/forward-preview/route.js.map +7 -0
  47. package/dist/modules/messages/api/[id]/read/route.js +120 -0
  48. package/dist/modules/messages/api/[id]/read/route.js.map +7 -0
  49. package/dist/modules/messages/api/[id]/reply/route.js +87 -0
  50. package/dist/modules/messages/api/[id]/reply/route.js.map +7 -0
  51. package/dist/modules/messages/api/[id]/route.js +350 -0
  52. package/dist/modules/messages/api/[id]/route.js.map +7 -0
  53. package/dist/modules/messages/api/object-types/route.js +54 -0
  54. package/dist/modules/messages/api/object-types/route.js.map +7 -0
  55. package/dist/modules/messages/api/openapi.js +261 -0
  56. package/dist/modules/messages/api/openapi.js.map +7 -0
  57. package/dist/modules/messages/api/route.js +262 -0
  58. package/dist/modules/messages/api/route.js.map +7 -0
  59. package/dist/modules/messages/api/token/[token]/route.js +99 -0
  60. package/dist/modules/messages/api/token/[token]/route.js.map +7 -0
  61. package/dist/modules/messages/api/types/route.js +40 -0
  62. package/dist/modules/messages/api/types/route.js.map +7 -0
  63. package/dist/modules/messages/api/unread-count/route.js +43 -0
  64. package/dist/modules/messages/api/unread-count/route.js.map +7 -0
  65. package/dist/modules/messages/backend/messages/[id]/page.js +10 -0
  66. package/dist/modules/messages/backend/messages/[id]/page.js.map +7 -0
  67. package/dist/modules/messages/backend/messages/[id]/page.meta.js +16 -0
  68. package/dist/modules/messages/backend/messages/[id]/page.meta.js.map +7 -0
  69. package/dist/modules/messages/backend/messages/compose/page.js +10 -0
  70. package/dist/modules/messages/backend/messages/compose/page.js.map +7 -0
  71. package/dist/modules/messages/backend/messages/compose/page.meta.js +17 -0
  72. package/dist/modules/messages/backend/messages/compose/page.meta.js.map +7 -0
  73. package/dist/modules/messages/backend/page.js +10 -0
  74. package/dist/modules/messages/backend/page.js.map +7 -0
  75. package/dist/modules/messages/backend/page.meta.js +33 -0
  76. package/dist/modules/messages/backend/page.meta.js.map +7 -0
  77. package/dist/modules/messages/commands/actions.js +265 -0
  78. package/dist/modules/messages/commands/actions.js.map +7 -0
  79. package/dist/modules/messages/commands/attachments.js +217 -0
  80. package/dist/modules/messages/commands/attachments.js.map +7 -0
  81. package/dist/modules/messages/commands/confirmations.js +151 -0
  82. package/dist/modules/messages/commands/confirmations.js.map +7 -0
  83. package/dist/modules/messages/commands/conversation.js +240 -0
  84. package/dist/modules/messages/commands/conversation.js.map +7 -0
  85. package/dist/modules/messages/commands/messages.js +748 -0
  86. package/dist/modules/messages/commands/messages.js.map +7 -0
  87. package/dist/modules/messages/commands/recipients.js +259 -0
  88. package/dist/modules/messages/commands/recipients.js.map +7 -0
  89. package/dist/modules/messages/commands/shared.js +258 -0
  90. package/dist/modules/messages/commands/shared.js.map +7 -0
  91. package/dist/modules/messages/commands/tokens.js +69 -0
  92. package/dist/modules/messages/commands/tokens.js.map +7 -0
  93. package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -0
  94. package/dist/modules/messages/components/ComposeMessagePageClient.js.map +7 -0
  95. package/dist/modules/messages/components/MessageDetailPageClient.js +261 -0
  96. package/dist/modules/messages/components/MessageDetailPageClient.js.map +7 -0
  97. package/dist/modules/messages/components/MessagesInboxPageClient.js +390 -0
  98. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +7 -0
  99. package/dist/modules/messages/components/confirmation/MessageConfirmationActions.js +31 -0
  100. package/dist/modules/messages/components/confirmation/MessageConfirmationActions.js.map +7 -0
  101. package/dist/modules/messages/components/confirmation/MessageConfirmationContent.js +69 -0
  102. package/dist/modules/messages/components/confirmation/MessageConfirmationContent.js.map +7 -0
  103. package/dist/modules/messages/components/defaults/DefaultMessageActions.js +31 -0
  104. package/dist/modules/messages/components/defaults/DefaultMessageActions.js.map +7 -0
  105. package/dist/modules/messages/components/defaults/DefaultMessageContent.js +19 -0
  106. package/dist/modules/messages/components/defaults/DefaultMessageContent.js.map +7 -0
  107. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js +90 -0
  108. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js.map +7 -0
  109. package/dist/modules/messages/components/defaults/MessageRecordObjectDetail.js +86 -0
  110. package/dist/modules/messages/components/defaults/MessageRecordObjectDetail.js.map +7 -0
  111. package/dist/modules/messages/components/defaults/MessageRecordObjectPreview.js +61 -0
  112. package/dist/modules/messages/components/defaults/MessageRecordObjectPreview.js.map +7 -0
  113. package/dist/modules/messages/components/message-detail/detail-panels.js +27 -0
  114. package/dist/modules/messages/components/message-detail/detail-panels.js.map +7 -0
  115. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js +52 -0
  116. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js.map +7 -0
  117. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js +289 -0
  118. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js.map +7 -0
  119. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js +103 -0
  120. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js.map +7 -0
  121. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js +78 -0
  122. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js.map +7 -0
  123. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js +94 -0
  124. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js.map +7 -0
  125. package/dist/modules/messages/components/message-detail/panels/MessageHeader.js +110 -0
  126. package/dist/modules/messages/components/message-detail/panels/MessageHeader.js.map +7 -0
  127. package/dist/modules/messages/components/message-detail/panels/MessageListComponent.js +58 -0
  128. package/dist/modules/messages/components/message-detail/panels/MessageListComponent.js.map +7 -0
  129. package/dist/modules/messages/components/message-detail/panels/actions-panel.js +51 -0
  130. package/dist/modules/messages/components/message-detail/panels/actions-panel.js.map +7 -0
  131. package/dist/modules/messages/components/message-detail/panels/attachments-panel.js +66 -0
  132. package/dist/modules/messages/components/message-detail/panels/attachments-panel.js.map +7 -0
  133. package/dist/modules/messages/components/message-detail/panels/body-panel.js +20 -0
  134. package/dist/modules/messages/components/message-detail/panels/body-panel.js.map +7 -0
  135. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js +36 -0
  136. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js.map +7 -0
  137. package/dist/modules/messages/components/message-detail/panels/dialogs.js +96 -0
  138. package/dist/modules/messages/components/message-detail/panels/dialogs.js.map +7 -0
  139. package/dist/modules/messages/components/message-detail/panels/index.js +25 -0
  140. package/dist/modules/messages/components/message-detail/panels/index.js.map +7 -0
  141. package/dist/modules/messages/components/message-detail/panels/meta-panel.js +14 -0
  142. package/dist/modules/messages/components/message-detail/panels/meta-panel.js.map +7 -0
  143. package/dist/modules/messages/components/message-detail/panels/objects-panel.js +51 -0
  144. package/dist/modules/messages/components/message-detail/panels/objects-panel.js.map +7 -0
  145. package/dist/modules/messages/components/message-detail/panels/thread-panel.js +54 -0
  146. package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +7 -0
  147. package/dist/modules/messages/components/message-detail/types.js +1 -0
  148. package/dist/modules/messages/components/message-detail/types.js.map +7 -0
  149. package/dist/modules/messages/components/message-detail/utils.js +54 -0
  150. package/dist/modules/messages/components/message-detail/utils.js.map +7 -0
  151. package/dist/modules/messages/components/utils/PriorityBadge.js +52 -0
  152. package/dist/modules/messages/components/utils/PriorityBadge.js.map +7 -0
  153. package/dist/modules/messages/components/utils/typeUiRegistry.js +77 -0
  154. package/dist/modules/messages/components/utils/typeUiRegistry.js.map +7 -0
  155. package/dist/modules/messages/data/entities.js +309 -0
  156. package/dist/modules/messages/data/entities.js.map +7 -0
  157. package/dist/modules/messages/data/validators.js +272 -0
  158. package/dist/modules/messages/data/validators.js.map +7 -0
  159. package/dist/modules/messages/emails/MessageEmail.js +108 -0
  160. package/dist/modules/messages/emails/MessageEmail.js.map +7 -0
  161. package/dist/modules/messages/events.js +24 -0
  162. package/dist/modules/messages/events.js.map +7 -0
  163. package/dist/modules/messages/frontend/messages/view/[token]/page.js +247 -0
  164. package/dist/modules/messages/frontend/messages/view/[token]/page.js.map +7 -0
  165. package/dist/modules/messages/frontend/messages/view/[token]/page.meta.js +9 -0
  166. package/dist/modules/messages/frontend/messages/view/[token]/page.meta.js.map +7 -0
  167. package/dist/modules/messages/index.js +21 -0
  168. package/dist/modules/messages/index.js.map +7 -0
  169. package/dist/modules/messages/lib/actions.js +141 -0
  170. package/dist/modules/messages/lib/actions.js.map +7 -0
  171. package/dist/modules/messages/lib/attachments.js +131 -0
  172. package/dist/modules/messages/lib/attachments.js.map +7 -0
  173. package/dist/modules/messages/lib/constants.js +7 -0
  174. package/dist/modules/messages/lib/constants.js.map +7 -0
  175. package/dist/modules/messages/lib/email-sender.js +201 -0
  176. package/dist/modules/messages/lib/email-sender.js.map +7 -0
  177. package/dist/modules/messages/lib/forwarding.js +179 -0
  178. package/dist/modules/messages/lib/forwarding.js.map +7 -0
  179. package/dist/modules/messages/lib/message-objects-registry.js +49 -0
  180. package/dist/modules/messages/lib/message-objects-registry.js.map +7 -0
  181. package/dist/modules/messages/lib/message-types-registry.js +41 -0
  182. package/dist/modules/messages/lib/message-types-registry.js.map +7 -0
  183. package/dist/modules/messages/lib/object-validation.js +20 -0
  184. package/dist/modules/messages/lib/object-validation.js.map +7 -0
  185. package/dist/modules/messages/lib/operationMetadata.js +21 -0
  186. package/dist/modules/messages/lib/operationMetadata.js.map +7 -0
  187. package/dist/modules/messages/lib/priorityUtils.js +61 -0
  188. package/dist/modules/messages/lib/priorityUtils.js.map +7 -0
  189. package/dist/modules/messages/lib/routeHelpers.js +44 -0
  190. package/dist/modules/messages/lib/routeHelpers.js.map +7 -0
  191. package/dist/modules/messages/message-objects.js +7 -0
  192. package/dist/modules/messages/message-objects.js.map +7 -0
  193. package/dist/modules/messages/message-types.js +67 -0
  194. package/dist/modules/messages/message-types.js.map +7 -0
  195. package/dist/modules/messages/migrations/Migration20260213181243.js +31 -0
  196. package/dist/modules/messages/migrations/Migration20260213181243.js.map +7 -0
  197. package/dist/modules/messages/migrations/Migration20260215165126.js +16 -0
  198. package/dist/modules/messages/migrations/Migration20260215165126.js.map +7 -0
  199. package/dist/modules/messages/notifications.js +27 -0
  200. package/dist/modules/messages/notifications.js.map +7 -0
  201. package/dist/modules/messages/setup.js +21 -0
  202. package/dist/modules/messages/setup.js.map +7 -0
  203. package/dist/modules/messages/subscribers/message-notification.js +108 -0
  204. package/dist/modules/messages/subscribers/message-notification.js.map +7 -0
  205. package/dist/modules/messages/workers/send-email.worker.js +253 -0
  206. package/dist/modules/messages/workers/send-email.worker.js.map +7 -0
  207. package/dist/modules/sales/backend/sales/documents/[id]/page.js +30 -11
  208. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  209. package/dist/modules/sales/commands/payments.js +12 -6
  210. package/dist/modules/sales/commands/payments.js.map +2 -2
  211. package/dist/modules/sales/lib/messageObjectPreviews.js +114 -0
  212. package/dist/modules/sales/lib/messageObjectPreviews.js.map +7 -0
  213. package/dist/modules/sales/message-objects.js +57 -0
  214. package/dist/modules/sales/message-objects.js.map +7 -0
  215. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js +51 -0
  216. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js.map +7 -0
  217. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js +36 -0
  218. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js.map +7 -0
  219. package/dist/modules/sales/widgets/messages/index.js +7 -0
  220. package/dist/modules/sales/widgets/messages/index.js.map +7 -0
  221. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +55 -1
  222. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  223. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +60 -1
  224. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  225. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +2 -19
  226. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  227. package/dist/modules/staff/components/LeaveRequestDetail.js +112 -0
  228. package/dist/modules/staff/components/LeaveRequestDetail.js.map +7 -0
  229. package/dist/modules/staff/components/LeaveRequestForm.js +3 -1
  230. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  231. package/dist/modules/staff/components/LeaveRequestPreview.js +43 -0
  232. package/dist/modules/staff/components/LeaveRequestPreview.js.map +7 -0
  233. package/dist/modules/staff/lib/messageObjectPreviews.js +148 -0
  234. package/dist/modules/staff/lib/messageObjectPreviews.js.map +7 -0
  235. package/dist/modules/staff/message-objects.js +104 -0
  236. package/dist/modules/staff/message-objects.js.map +7 -0
  237. package/dist/modules/staff/message-types.js +23 -0
  238. package/dist/modules/staff/message-types.js.map +7 -0
  239. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js +51 -0
  240. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js.map +7 -0
  241. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js +34 -0
  242. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js.map +7 -0
  243. package/dist/modules/staff/widgets/messages/index.js +7 -0
  244. package/dist/modules/staff/widgets/messages/index.js.map +7 -0
  245. package/generated/entities/message/index.ts +31 -0
  246. package/generated/entities/message_access_token/index.ts +8 -0
  247. package/generated/entities/message_confirmation/index.ts +9 -0
  248. package/generated/entities/message_object/index.ts +10 -0
  249. package/generated/entities/message_recipient/index.ts +14 -0
  250. package/generated/entities.ids.generated.ts +8 -0
  251. package/generated/entity-fields-registry.ts +10 -0
  252. package/jest.setup.ts +5 -0
  253. package/package.json +2 -2
  254. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +20 -4
  255. package/src/modules/customers/i18n/de.json +4 -0
  256. package/src/modules/customers/i18n/en.json +4 -0
  257. package/src/modules/customers/i18n/es.json +4 -0
  258. package/src/modules/customers/i18n/pl.json +4 -0
  259. package/src/modules/customers/lib/messageObjectPreviews.ts +154 -0
  260. package/src/modules/customers/message-objects.ts +70 -0
  261. package/src/modules/customers/widgets/messages/CustomerMessageObjectDetail.tsx +57 -0
  262. package/src/modules/customers/widgets/messages/CustomerMessageObjectPreview.tsx +49 -0
  263. package/src/modules/customers/widgets/messages/index.ts +2 -0
  264. package/src/modules/messages/acl.ts +11 -0
  265. package/src/modules/messages/api/[id]/actions/[actionId]/route.ts +103 -0
  266. package/src/modules/messages/api/[id]/archive/route.ts +138 -0
  267. package/src/modules/messages/api/[id]/attachments/route.ts +217 -0
  268. package/src/modules/messages/api/[id]/confirmation/route.ts +73 -0
  269. package/src/modules/messages/api/[id]/conversation/archive/route.ts +69 -0
  270. package/src/modules/messages/api/[id]/conversation/read/route.ts +69 -0
  271. package/src/modules/messages/api/[id]/conversation/route.ts +69 -0
  272. package/src/modules/messages/api/[id]/forward/route.ts +87 -0
  273. package/src/modules/messages/api/[id]/forward-preview/route.ts +75 -0
  274. package/src/modules/messages/api/[id]/read/route.ts +138 -0
  275. package/src/modules/messages/api/[id]/reply/route.ts +89 -0
  276. package/src/modules/messages/api/[id]/route.ts +401 -0
  277. package/src/modules/messages/api/object-types/route.ts +54 -0
  278. package/src/modules/messages/api/openapi.ts +261 -0
  279. package/src/modules/messages/api/route.ts +374 -0
  280. package/src/modules/messages/api/token/[token]/route.ts +103 -0
  281. package/src/modules/messages/api/types/route.ts +39 -0
  282. package/src/modules/messages/api/unread-count/route.ts +55 -0
  283. package/src/modules/messages/backend/messages/[id]/page.meta.ts +12 -0
  284. package/src/modules/messages/backend/messages/[id]/page.tsx +12 -0
  285. package/src/modules/messages/backend/messages/compose/page.meta.ts +13 -0
  286. package/src/modules/messages/backend/messages/compose/page.tsx +12 -0
  287. package/src/modules/messages/backend/page.meta.ts +31 -0
  288. package/src/modules/messages/backend/page.tsx +12 -0
  289. package/src/modules/messages/commands/actions.ts +307 -0
  290. package/src/modules/messages/commands/attachments.ts +227 -0
  291. package/src/modules/messages/commands/confirmations.ts +183 -0
  292. package/src/modules/messages/commands/conversation.ts +292 -0
  293. package/src/modules/messages/commands/messages.ts +845 -0
  294. package/src/modules/messages/commands/recipients.ts +281 -0
  295. package/src/modules/messages/commands/shared.ts +350 -0
  296. package/src/modules/messages/commands/tokens.ts +80 -0
  297. package/src/modules/messages/components/ComposeMessagePageClient.tsx +23 -0
  298. package/src/modules/messages/components/MessageDetailPageClient.tsx +287 -0
  299. package/src/modules/messages/components/MessagesInboxPageClient.tsx +469 -0
  300. package/src/modules/messages/components/confirmation/MessageConfirmationActions.tsx +35 -0
  301. package/src/modules/messages/components/confirmation/MessageConfirmationContent.tsx +88 -0
  302. package/src/modules/messages/components/defaults/DefaultMessageActions.tsx +37 -0
  303. package/src/modules/messages/components/defaults/DefaultMessageContent.tsx +21 -0
  304. package/src/modules/messages/components/defaults/DefaultMessageListItem.tsx +102 -0
  305. package/src/modules/messages/components/defaults/MessageRecordObjectDetail.tsx +114 -0
  306. package/src/modules/messages/components/defaults/MessageRecordObjectPreview.tsx +74 -0
  307. package/src/modules/messages/components/message-detail/detail-panels.ts +13 -0
  308. package/src/modules/messages/components/message-detail/hooks/useMessageDetails.ts +56 -0
  309. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsActions.ts +367 -0
  310. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.ts +134 -0
  311. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.ts +102 -0
  312. package/src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx +108 -0
  313. package/src/modules/messages/components/message-detail/panels/MessageHeader.tsx +144 -0
  314. package/src/modules/messages/components/message-detail/panels/MessageListComponent.tsx +63 -0
  315. package/src/modules/messages/components/message-detail/panels/actions-panel.tsx +66 -0
  316. package/src/modules/messages/components/message-detail/panels/attachments-panel.tsx +86 -0
  317. package/src/modules/messages/components/message-detail/panels/body-panel.tsx +32 -0
  318. package/src/modules/messages/components/message-detail/panels/composer-dialogs.tsx +42 -0
  319. package/src/modules/messages/components/message-detail/panels/dialogs.tsx +107 -0
  320. package/src/modules/messages/components/message-detail/panels/index.ts +11 -0
  321. package/src/modules/messages/components/message-detail/panels/meta-panel.tsx +19 -0
  322. package/src/modules/messages/components/message-detail/panels/objects-panel.tsx +65 -0
  323. package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +65 -0
  324. package/src/modules/messages/components/message-detail/types.ts +114 -0
  325. package/src/modules/messages/components/message-detail/utils.ts +62 -0
  326. package/src/modules/messages/components/utils/PriorityBadge.tsx +63 -0
  327. package/src/modules/messages/components/utils/typeUiRegistry.ts +106 -0
  328. package/src/modules/messages/data/entities.ts +284 -0
  329. package/src/modules/messages/data/validators.ts +297 -0
  330. package/src/modules/messages/emails/MessageEmail.tsx +143 -0
  331. package/src/modules/messages/events.ts +24 -0
  332. package/src/modules/messages/frontend/messages/view/[token]/page.meta.ts +5 -0
  333. package/src/modules/messages/frontend/messages/view/[token]/page.tsx +389 -0
  334. package/src/modules/messages/i18n/de.json +240 -0
  335. package/src/modules/messages/i18n/en.json +240 -0
  336. package/src/modules/messages/i18n/es.json +240 -0
  337. package/src/modules/messages/i18n/pl.json +240 -0
  338. package/src/modules/messages/index.ts +19 -0
  339. package/src/modules/messages/lib/actions.ts +204 -0
  340. package/src/modules/messages/lib/attachments.ts +197 -0
  341. package/src/modules/messages/lib/constants.ts +2 -0
  342. package/src/modules/messages/lib/email-sender.ts +255 -0
  343. package/src/modules/messages/lib/forwarding.ts +240 -0
  344. package/src/modules/messages/lib/message-objects-registry.ts +60 -0
  345. package/src/modules/messages/lib/message-types-registry.ts +48 -0
  346. package/src/modules/messages/lib/object-validation.ts +26 -0
  347. package/src/modules/messages/lib/operationMetadata.ts +43 -0
  348. package/src/modules/messages/lib/priorityUtils.ts +76 -0
  349. package/src/modules/messages/lib/routeHelpers.ts +65 -0
  350. package/src/modules/messages/message-objects.ts +5 -0
  351. package/src/modules/messages/message-types.ts +65 -0
  352. package/src/modules/messages/migrations/.snapshot-open-mercato.json +957 -0
  353. package/src/modules/messages/migrations/Migration20260213181243.ts +34 -0
  354. package/src/modules/messages/migrations/Migration20260215165126.ts +16 -0
  355. package/src/modules/messages/notifications.ts +25 -0
  356. package/src/modules/messages/setup.ts +19 -0
  357. package/src/modules/messages/subscribers/message-notification.ts +138 -0
  358. package/src/modules/messages/workers/send-email.worker.ts +321 -0
  359. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +23 -7
  360. package/src/modules/sales/commands/payments.ts +12 -6
  361. package/src/modules/sales/i18n/de.json +3 -0
  362. package/src/modules/sales/i18n/en.json +3 -0
  363. package/src/modules/sales/i18n/es.json +3 -0
  364. package/src/modules/sales/i18n/pl.json +3 -0
  365. package/src/modules/sales/lib/messageObjectPreviews.ts +150 -0
  366. package/src/modules/sales/message-objects.ts +56 -0
  367. package/src/modules/sales/widgets/messages/SalesDocumentMessageDetail.tsx +57 -0
  368. package/src/modules/sales/widgets/messages/SalesDocumentMessagePreview.tsx +46 -0
  369. package/src/modules/sales/widgets/messages/index.ts +2 -0
  370. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +54 -0
  371. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +58 -0
  372. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +2 -32
  373. package/src/modules/staff/components/LeaveRequestDetail.tsx +135 -0
  374. package/src/modules/staff/components/LeaveRequestForm.tsx +3 -0
  375. package/src/modules/staff/components/LeaveRequestPreview.tsx +74 -0
  376. package/src/modules/staff/i18n/de.json +8 -0
  377. package/src/modules/staff/i18n/en.json +8 -0
  378. package/src/modules/staff/i18n/es.json +8 -0
  379. package/src/modules/staff/i18n/pl.json +8 -0
  380. package/src/modules/staff/lib/messageObjectPreviews.ts +182 -0
  381. package/src/modules/staff/message-objects.ts +102 -0
  382. package/src/modules/staff/message-types.ts +21 -0
  383. package/src/modules/staff/widgets/messages/StaffMessageObjectDetail.tsx +57 -0
  384. package/src/modules/staff/widgets/messages/StaffMessageObjectPreview.tsx +44 -0
  385. package/src/modules/staff/widgets/messages/index.ts +2 -0
@@ -0,0 +1,135 @@
1
+ "use client"
2
+
3
+ import * as React from 'react'
4
+ import type { ObjectDetailProps } from '@open-mercato/shared/modules/messages/types'
5
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
6
+ import { Button } from '@open-mercato/ui/primitives/button'
7
+ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
8
+ import { LeaveRequestPreview } from './LeaveRequestPreview'
9
+
10
+ export function LeaveRequestDetail(props: ObjectDetailProps) {
11
+ const t = useT()
12
+ const [executingActionId, setExecutingActionId] = React.useState<string | null>(null)
13
+ const [actionTakenByName, setActionTakenByName] = React.useState<string | null>(null)
14
+ const actionTakenAtLabel = formatDateTime(props.actionTakenAt)
15
+ const hasActionTaken = Boolean(props.actionTaken)
16
+ const actionTakenId = extractActionId(props.actionTaken)
17
+ const actionTakenLabel = resolveActionLabel(actionTakenId, props.actions, t)
18
+ const actionTakenByLabel = formatUserLabel(props.actionTakenByUserId, actionTakenByName, t)
19
+
20
+ React.useEffect(() => {
21
+ const userId = props.actionTakenByUserId
22
+ if (typeof userId !== 'string' || userId.trim().length === 0) {
23
+ setActionTakenByName(null)
24
+ return
25
+ }
26
+
27
+ let cancelled = false
28
+ const safeUserId = userId.trim()
29
+ async function loadActionTakenByUserName() {
30
+ const call = await apiCall<{ items?: Array<{ id?: string; name?: string | null; email?: string | null }> }>(
31
+ `/api/auth/users?id=${encodeURIComponent(safeUserId)}`,
32
+ )
33
+ const entry = Array.isArray(call.result?.items) ? call.result.items[0] : null
34
+ const resolvedName = typeof entry?.name === 'string' && entry.name.trim().length > 0
35
+ ? entry.name.trim()
36
+ : typeof entry?.email === 'string' && entry.email.trim().length > 0
37
+ ? entry.email.trim()
38
+ : null
39
+ if (!cancelled) {
40
+ setActionTakenByName(resolvedName)
41
+ }
42
+ }
43
+
44
+ void loadActionTakenByUserName()
45
+ return () => { cancelled = true }
46
+ }, [props.actionTakenByUserId])
47
+
48
+ return (
49
+ <div className="space-y-3 rounded border p-3">
50
+ <LeaveRequestPreview
51
+ entityId={props.entityId}
52
+ entityModule={props.entityModule}
53
+ entityType={props.entityType}
54
+ snapshot={props.snapshot}
55
+ previewData={props.previewData}
56
+ actionRequired={props.actionRequired}
57
+ actionType={props.actionType}
58
+ actionLabel={props.actionLabel}
59
+ />
60
+
61
+ {props.actions.length ? (
62
+ <div className="flex flex-wrap gap-2">
63
+ {props.actions.map((action) => (
64
+ <Button
65
+ key={action.id}
66
+ type="button"
67
+ size="sm"
68
+ variant={action.variant ?? 'default'}
69
+ disabled={executingActionId !== null || hasActionTaken}
70
+ onClick={async () => {
71
+ if (executingActionId !== null || hasActionTaken) return
72
+ setExecutingActionId(action.id)
73
+ try {
74
+ await props.onAction(action.id, { id: props.entityId })
75
+ } finally {
76
+ setExecutingActionId(null)
77
+ }
78
+ }}
79
+ >
80
+ {executingActionId === action.id
81
+ ? t('messages.actions.executing', 'Executing...')
82
+ : t(action.labelKey ?? action.id, action.id)}
83
+ </Button>
84
+ ))}
85
+ </div>
86
+ ) : null}
87
+
88
+ {hasActionTaken ? (
89
+ <p className="text-xs text-muted-foreground">
90
+ {t('messages.actions.taken', 'Action taken')}: {actionTakenLabel}
91
+ {actionTakenAtLabel ? ` (${actionTakenAtLabel})` : ''}
92
+ {actionTakenByLabel ? ` ${t('messages.actions.by', 'by')} ${actionTakenByLabel}` : ''}
93
+ </p>
94
+ ) : null}
95
+ </div>
96
+ )
97
+ }
98
+
99
+ function formatDateTime(value?: Date | string | null): string {
100
+ if (!value) return ''
101
+ const date = value instanceof Date ? value : new Date(value)
102
+ if (Number.isNaN(date.getTime())) return ''
103
+ return date.toLocaleString()
104
+ }
105
+
106
+ function extractActionId(actionTaken?: string | null): string | null {
107
+ if (!actionTaken) return null
108
+ const value = actionTaken.trim()
109
+ if (value.length === 0) return null
110
+ const parts = value.split(':')
111
+ return parts[parts.length - 1] ?? value
112
+ }
113
+
114
+ function resolveActionLabel(
115
+ actionId: string | null,
116
+ actions: ObjectDetailProps['actions'],
117
+ t: ReturnType<typeof useT>,
118
+ ): string {
119
+ if (!actionId) return '-'
120
+ const action = actions.find((item) => item.id === actionId)
121
+ if (!action) return actionId
122
+ return t(action.labelKey ?? action.id, action.id)
123
+ }
124
+
125
+ function formatUserLabel(
126
+ userId: string | null | undefined,
127
+ userName: string | null,
128
+ t: ReturnType<typeof useT>,
129
+ ): string {
130
+ if (!userId) return ''
131
+ if (userName) return userName
132
+ return t('common.user', 'user')
133
+ }
134
+
135
+ export default LeaveRequestDetail
@@ -46,6 +46,7 @@ export type LeaveRequestFormProps = {
46
46
  loadingMessage?: string
47
47
  allowMemberSelect?: boolean
48
48
  memberLabel?: string | null
49
+ extraActions?: React.ReactNode
49
50
  }
50
51
 
51
52
  const DEFAULT_TIMEZONE = 'UTC'
@@ -97,6 +98,7 @@ export function LeaveRequestForm(props: LeaveRequestFormProps) {
97
98
  loadingMessage,
98
99
  allowMemberSelect = true,
99
100
  memberLabel,
101
+ extraActions,
100
102
  } = props
101
103
  const t = useT()
102
104
  const scopeVersion = useOrganizationScopeVersion()
@@ -334,6 +336,7 @@ export function LeaveRequestForm(props: LeaveRequestFormProps) {
334
336
  cancelHref={cancelHref}
335
337
  onSubmit={onSubmit}
336
338
  onDelete={onDelete}
339
+ extraActions={extraActions}
337
340
  isLoading={isLoading}
338
341
  loadingMessage={loadingMessage}
339
342
  />
@@ -0,0 +1,74 @@
1
+ "use client"
2
+
3
+ import type { ObjectPreviewProps } from '@open-mercato/shared/modules/messages/types'
4
+ import { CalendarClock } from 'lucide-react'
5
+ import { Badge } from '@open-mercato/ui/primitives/badge'
6
+
7
+ export function LeaveRequestPreview({
8
+ snapshot,
9
+ previewData,
10
+ actionRequired,
11
+ actionLabel
12
+ }: ObjectPreviewProps) {
13
+ // Use previewData if available, otherwise fall back to snapshot
14
+ const data = snapshot as {
15
+ employeeName?: string
16
+ startDate?: string
17
+ endDate?: string
18
+ status?: string
19
+ type?: string
20
+ } | undefined
21
+
22
+ const title = previewData?.title || 'Leave Request'
23
+ const subtitle = previewData?.subtitle || (data ?
24
+ `${data.employeeName} - ${data.startDate} to ${data.endDate}` :
25
+ 'Leave Request Details'
26
+ )
27
+ const status = previewData?.status || data?.status
28
+ const statusColor = previewData?.statusColor || 'amber'
29
+
30
+ return (
31
+ <div className="flex items-start gap-3 rounded-md border p-3 bg-muted/30">
32
+ <CalendarClock className="h-5 w-5 text-muted-foreground mt-0.5 flex-shrink-0" />
33
+ <div className="flex-1 min-w-0">
34
+ <div className="flex items-center gap-2 flex-wrap">
35
+ <span className="font-medium text-sm">{title}</span>
36
+ {actionRequired && (
37
+ <Badge variant="secondary" className="text-xs">
38
+ {actionLabel || 'Action Required'}
39
+ </Badge>
40
+ )}
41
+ </div>
42
+ {subtitle && (
43
+ <p className="text-sm text-muted-foreground mt-1">
44
+ {subtitle}
45
+ </p>
46
+ )}
47
+ <div className="flex items-center gap-2 mt-2">
48
+ {status && (
49
+ <Badge variant="outline" className="text-xs">
50
+ {status}
51
+ </Badge>
52
+ )}
53
+ {data?.type && (
54
+ <Badge variant="secondary" className="text-xs">
55
+ {data.type}
56
+ </Badge>
57
+ )}
58
+ </div>
59
+ {previewData?.metadata && Object.keys(previewData.metadata).length > 0 && (
60
+ <div className="mt-2 space-y-1">
61
+ {Object.entries(previewData.metadata).slice(0, 3).map(([key, value]) => (
62
+ <div key={key} className="flex items-center gap-1 text-xs text-muted-foreground">
63
+ <span className="font-medium">{key}:</span>
64
+ <span className="truncate">{value}</span>
65
+ </div>
66
+ ))}
67
+ </div>
68
+ )}
69
+ </div>
70
+ </div>
71
+ )
72
+ }
73
+
74
+ export default LeaveRequestPreview
@@ -257,6 +257,10 @@
257
257
  "staff.leaveRequests.form.reason.valueLabel": "Grund",
258
258
  "staff.leaveRequests.form.reason.valuePlaceholder": "Grundname",
259
259
  "staff.leaveRequests.messages.accepted": "Urlaubsantrag genehmigt.",
260
+ "staff.leaveRequests.messages.compose.action": "Zur Prüfung senden",
261
+ "staff.leaveRequests.messages.compose.body": "Bitte prüfe diesen Urlaubsantrag und führe die passende Aktion aus.",
262
+ "staff.leaveRequests.messages.compose.subject": "Urlaubsantrag wartet auf Genehmigung",
263
+ "staff.leaveRequests.messages.contextTitle": "Verknüpfter Urlaubsantrag",
260
264
  "staff.leaveRequests.messages.rejected": "Urlaubsantrag abgelehnt.",
261
265
  "staff.leaveRequests.my.description": "Verfolge deine Urlaubsanträge.",
262
266
  "staff.leaveRequests.my.title": "Meine Urlaubsanträge",
@@ -272,6 +276,10 @@
272
276
  "staff.leaveRequests.table.search": "Urlaubsanträge suchen...",
273
277
  "staff.leaveRequests.table.status": "Status",
274
278
  "staff.leaveRequests.table.updatedAt": "Aktualisiert",
279
+ "staff.messageObjects.leaveRequest.title": "Urlaubsantrag",
280
+ "staff.messageObjects.notFound": "Nicht gefunden",
281
+ "staff.messageObjects.team.title": "Team",
282
+ "staff.messageObjects.teamMember.title": "Teammitglied",
275
283
  "staff.myAvailability.empty.profileRequired": "Erstelle dein Teamprofil, um Verfügbarkeit zu verwalten.",
276
284
  "staff.myAvailability.errors.load": "Verfügbarkeit konnte nicht geladen werden.",
277
285
  "staff.myAvailability.loading": "Verfügbarkeit wird geladen...",
@@ -257,6 +257,10 @@
257
257
  "staff.leaveRequests.form.reason.valueLabel": "Reason",
258
258
  "staff.leaveRequests.form.reason.valuePlaceholder": "Reason name",
259
259
  "staff.leaveRequests.messages.accepted": "Leave request approved.",
260
+ "staff.leaveRequests.messages.compose.action": "Send for review",
261
+ "staff.leaveRequests.messages.compose.body": "Please review this leave request and take action.",
262
+ "staff.leaveRequests.messages.compose.subject": "Leave request approval needed",
263
+ "staff.leaveRequests.messages.contextTitle": "Linked leave request",
260
264
  "staff.leaveRequests.messages.rejected": "Leave request rejected.",
261
265
  "staff.leaveRequests.my.description": "Track your submitted leave requests.",
262
266
  "staff.leaveRequests.my.title": "My leave requests",
@@ -272,6 +276,10 @@
272
276
  "staff.leaveRequests.table.search": "Search leave requests...",
273
277
  "staff.leaveRequests.table.status": "Status",
274
278
  "staff.leaveRequests.table.updatedAt": "Updated",
279
+ "staff.messageObjects.leaveRequest.title": "Leave request",
280
+ "staff.messageObjects.notFound": "Not found",
281
+ "staff.messageObjects.team.title": "Team",
282
+ "staff.messageObjects.teamMember.title": "Team member",
275
283
  "staff.myAvailability.empty.profileRequired": "Create your team member profile to manage availability.",
276
284
  "staff.myAvailability.errors.load": "Failed to load availability.",
277
285
  "staff.myAvailability.loading": "Loading availability...",
@@ -257,6 +257,10 @@
257
257
  "staff.leaveRequests.form.reason.valueLabel": "Motivo",
258
258
  "staff.leaveRequests.form.reason.valuePlaceholder": "Nombre del motivo",
259
259
  "staff.leaveRequests.messages.accepted": "Solicitud de ausencia aprobada.",
260
+ "staff.leaveRequests.messages.compose.action": "Send for review",
261
+ "staff.leaveRequests.messages.compose.body": "Please review this leave request and take action.",
262
+ "staff.leaveRequests.messages.compose.subject": "Leave request approval needed",
263
+ "staff.leaveRequests.messages.contextTitle": "Linked leave request",
260
264
  "staff.leaveRequests.messages.rejected": "Solicitud de ausencia rechazada.",
261
265
  "staff.leaveRequests.my.description": "Sigue tus solicitudes de ausencia enviadas.",
262
266
  "staff.leaveRequests.my.title": "Mis solicitudes de ausencia",
@@ -272,6 +276,10 @@
272
276
  "staff.leaveRequests.table.search": "Buscar solicitudes de ausencia...",
273
277
  "staff.leaveRequests.table.status": "Estado",
274
278
  "staff.leaveRequests.table.updatedAt": "Actualizado",
279
+ "staff.messageObjects.leaveRequest.title": "Solicitud de permiso",
280
+ "staff.messageObjects.notFound": "No encontrado",
281
+ "staff.messageObjects.team.title": "Equipo",
282
+ "staff.messageObjects.teamMember.title": "Miembro del equipo",
275
283
  "staff.myAvailability.empty.profileRequired": "Crea tu perfil de miembro para gestionar la disponibilidad.",
276
284
  "staff.myAvailability.errors.load": "No se pudo cargar la disponibilidad.",
277
285
  "staff.myAvailability.loading": "Cargando disponibilidad...",
@@ -257,6 +257,10 @@
257
257
  "staff.leaveRequests.form.reason.valueLabel": "Powód",
258
258
  "staff.leaveRequests.form.reason.valuePlaceholder": "Nazwa powodu",
259
259
  "staff.leaveRequests.messages.accepted": "Wniosek urlopowy zatwierdzony.",
260
+ "staff.leaveRequests.messages.compose.action": "Wyślij do akceptacji",
261
+ "staff.leaveRequests.messages.compose.body": "Proszę sprawdzić ten wniosek urlopowy i wykonać odpowiednią akcję.",
262
+ "staff.leaveRequests.messages.compose.subject": "Wniosek urlopowy wymaga akceptacji",
263
+ "staff.leaveRequests.messages.contextTitle": "Powiązany wniosek urlopowy",
260
264
  "staff.leaveRequests.messages.rejected": "Wniosek urlopowy odrzucony.",
261
265
  "staff.leaveRequests.my.description": "Śledź swoje wnioski urlopowe.",
262
266
  "staff.leaveRequests.my.title": "Moje wnioski urlopowe",
@@ -272,6 +276,10 @@
272
276
  "staff.leaveRequests.table.search": "Szukaj wniosków urlopowych...",
273
277
  "staff.leaveRequests.table.status": "Status",
274
278
  "staff.leaveRequests.table.updatedAt": "Zaktualizowano",
279
+ "staff.messageObjects.leaveRequest.title": "Wniosek urlopowy",
280
+ "staff.messageObjects.notFound": "Nie znaleziono",
281
+ "staff.messageObjects.team.title": "Zespół",
282
+ "staff.messageObjects.teamMember.title": "Członek zespołu",
275
283
  "staff.myAvailability.empty.profileRequired": "Utwórz profil pracownika, aby zarządzać dostępnością.",
276
284
  "staff.myAvailability.errors.load": "Nie udało się załadować dostępności.",
277
285
  "staff.myAvailability.loading": "Ładowanie dostępności...",
@@ -0,0 +1,182 @@
1
+ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
2
+ import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
3
+ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
4
+ import type { ObjectPreviewData } from '@open-mercato/shared/modules/messages/types'
5
+ import type { EntityManager } from '@mikro-orm/postgresql'
6
+ import { StaffLeaveRequest, StaffTeam, StaffTeamMember } from '../data/entities'
7
+
8
+ type PreviewContext = {
9
+ tenantId: string
10
+ organizationId?: string | null
11
+ }
12
+
13
+ function mapStatus(status: string): { label: string; color: string } {
14
+ if (status === 'approved') {
15
+ return { label: 'Approved', color: 'green' }
16
+ }
17
+ if (status === 'rejected') {
18
+ return { label: 'Rejected', color: 'red' }
19
+ }
20
+ return { label: 'Pending', color: 'amber' }
21
+ }
22
+
23
+ function formatDate(value: Date): string {
24
+ return value.toISOString().slice(0, 10)
25
+ }
26
+
27
+ export async function loadLeaveRequestPreview(
28
+ entityId: string,
29
+ ctx: PreviewContext,
30
+ ): Promise<ObjectPreviewData> {
31
+ const { t } = await resolveTranslations()
32
+ const defaultTitle = t('staff.messageObjects.leaveRequest.title')
33
+
34
+ if (!ctx.organizationId) {
35
+ return {
36
+ title: defaultTitle,
37
+ subtitle: entityId,
38
+ }
39
+ }
40
+
41
+ const { resolve } = await createRequestContainer()
42
+ const em = resolve('em') as EntityManager
43
+
44
+ const request = await findOneWithDecryption(
45
+ em,
46
+ StaffLeaveRequest,
47
+ {
48
+ id: entityId,
49
+ tenantId: ctx.tenantId,
50
+ organizationId: ctx.organizationId,
51
+ deletedAt: null,
52
+ },
53
+ undefined,
54
+ { tenantId: ctx.tenantId, organizationId: ctx.organizationId },
55
+ )
56
+
57
+ if (!request) {
58
+ return {
59
+ title: defaultTitle,
60
+ subtitle: entityId,
61
+ status: t('staff.messageObjects.notFound'),
62
+ statusColor: 'gray',
63
+ }
64
+ }
65
+
66
+ const status = mapStatus(request.status)
67
+ const memberName = typeof request.member?.displayName === 'string' ? request.member.displayName : null
68
+ const subtitle = memberName
69
+ ? `${memberName} - ${formatDate(request.startDate)} to ${formatDate(request.endDate)}`
70
+ : `${formatDate(request.startDate)} to ${formatDate(request.endDate)}`
71
+
72
+ return {
73
+ title: 'Leave request',
74
+ subtitle,
75
+ status: status.label,
76
+ statusColor: status.color,
77
+ metadata: {
78
+ 'Start date': formatDate(request.startDate),
79
+ 'End date': formatDate(request.endDate),
80
+ Timezone: request.timezone,
81
+ },
82
+ }
83
+ }
84
+
85
+ export async function loadTeamPreview(
86
+ entityId: string,
87
+ ctx: PreviewContext,
88
+ ): Promise<ObjectPreviewData> {
89
+ const { t } = await resolveTranslations()
90
+ const defaultTitle = t('staff.messageObjects.team.title')
91
+
92
+ if (!ctx.organizationId) {
93
+ return {
94
+ title: defaultTitle,
95
+ subtitle: entityId,
96
+ }
97
+ }
98
+
99
+ const { resolve } = await createRequestContainer()
100
+ const em = resolve('em') as EntityManager
101
+
102
+ const team = await findOneWithDecryption(
103
+ em,
104
+ StaffTeam,
105
+ {
106
+ id: entityId,
107
+ tenantId: ctx.tenantId,
108
+ organizationId: ctx.organizationId,
109
+ deletedAt: null,
110
+ },
111
+ undefined,
112
+ { tenantId: ctx.tenantId, organizationId: ctx.organizationId },
113
+ )
114
+
115
+ if (!team) {
116
+ return {
117
+ title: defaultTitle,
118
+ subtitle: entityId,
119
+ status: t('staff.messageObjects.notFound'),
120
+ statusColor: 'gray',
121
+ }
122
+ }
123
+
124
+ return {
125
+ title: team.name,
126
+ subtitle: team.description ?? entityId,
127
+ status: team.isActive ? 'Active' : 'Inactive',
128
+ statusColor: team.isActive ? 'green' : 'gray',
129
+ }
130
+ }
131
+
132
+ export async function loadTeamMemberPreview(
133
+ entityId: string,
134
+ ctx: PreviewContext,
135
+ ): Promise<ObjectPreviewData> {
136
+ const { t } = await resolveTranslations()
137
+ const defaultTitle = t('staff.messageObjects.teamMember.title')
138
+
139
+ if (!ctx.organizationId) {
140
+ return {
141
+ title: defaultTitle,
142
+ subtitle: entityId,
143
+ }
144
+ }
145
+
146
+ const { resolve } = await createRequestContainer()
147
+ const em = resolve('em') as EntityManager
148
+
149
+ const member = await findOneWithDecryption(
150
+ em,
151
+ StaffTeamMember,
152
+ {
153
+ id: entityId,
154
+ tenantId: ctx.tenantId,
155
+ organizationId: ctx.organizationId,
156
+ deletedAt: null,
157
+ },
158
+ undefined,
159
+ { tenantId: ctx.tenantId, organizationId: ctx.organizationId },
160
+ )
161
+
162
+ if (!member) {
163
+ return {
164
+ title: defaultTitle,
165
+ subtitle: entityId,
166
+ status: t('staff.messageObjects.notFound'),
167
+ statusColor: 'gray',
168
+ }
169
+ }
170
+
171
+ const tags = Array.isArray(member.tags) ? member.tags : []
172
+ const metadata: Record<string, string> = {}
173
+ if (tags.length > 0) metadata.Tags = tags.slice(0, 5).join(', ')
174
+
175
+ return {
176
+ title: member.displayName,
177
+ subtitle: member.description ?? entityId,
178
+ status: member.isActive ? 'Active' : 'Inactive',
179
+ statusColor: member.isActive ? 'green' : 'gray',
180
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
181
+ }
182
+ }
@@ -0,0 +1,102 @@
1
+ import type { MessageObjectTypeDefinition } from '@open-mercato/shared/modules/messages/types'
2
+ import { LeaveRequestDetail } from './components/LeaveRequestDetail'
3
+ import { LeaveRequestPreview } from './components/LeaveRequestPreview'
4
+ import { StaffMessageObjectDetail } from './widgets/messages/StaffMessageObjectDetail'
5
+ import { StaffMessageObjectPreview } from './widgets/messages/StaffMessageObjectPreview'
6
+
7
+ export const messageObjectTypes: MessageObjectTypeDefinition[] = [
8
+ {
9
+ module: 'staff',
10
+ entityType: 'leave_request',
11
+ messageTypes: ['default', 'messages.defaultWithObjects', 'staff.leave_request_approval', 'staff.leave_request_status'],
12
+ entityId: 'staff:staff_leave_request',
13
+ optionLabelField: 'id',
14
+ optionSubtitleField: 'status',
15
+ labelKey: 'staff.leaveRequests.page.title',
16
+ icon: 'calendar-clock',
17
+ PreviewComponent: LeaveRequestPreview,
18
+ DetailComponent: LeaveRequestDetail,
19
+ actions: [
20
+ {
21
+ id: 'approve',
22
+ labelKey: 'staff.notifications.leaveRequest.actions.approve',
23
+ variant: 'default',
24
+ commandId: 'staff.leave-requests.accept',
25
+ icon: 'check',
26
+ },
27
+ {
28
+ id: 'reject',
29
+ labelKey: 'staff.notifications.leaveRequest.actions.reject',
30
+ variant: 'destructive',
31
+ commandId: 'staff.leave-requests.reject',
32
+ icon: 'x',
33
+ },
34
+ {
35
+ id: 'view',
36
+ labelKey: 'common.view',
37
+ variant: 'outline',
38
+ href: '/backend/staff/leave-requests/{entityId}',
39
+ icon: 'external-link',
40
+ isTerminal: false,
41
+ },
42
+ ],
43
+ loadPreview: async (entityId, ctx) => {
44
+ if (typeof window !== 'undefined') {
45
+ return {
46
+ title: 'Leave request',
47
+ subtitle: entityId,
48
+ }
49
+ }
50
+ const { loadLeaveRequestPreview } = await import('./lib/messageObjectPreviews')
51
+ return loadLeaveRequestPreview(entityId, ctx)
52
+ },
53
+ },
54
+ {
55
+ module: 'staff',
56
+ entityType: 'team',
57
+ messageTypes: ['default', 'messages.defaultWithObjects'],
58
+ entityId: 'staff:staff_team',
59
+ optionLabelField: 'name',
60
+ optionSubtitleField: 'description',
61
+ labelKey: 'staff.teams.page.title',
62
+ icon: 'users',
63
+ PreviewComponent: StaffMessageObjectPreview,
64
+ DetailComponent: StaffMessageObjectDetail,
65
+ actions: [],
66
+ loadPreview: async (entityId, ctx) => {
67
+ if (typeof window !== 'undefined') {
68
+ return {
69
+ title: 'Team',
70
+ subtitle: entityId,
71
+ }
72
+ }
73
+ const { loadTeamPreview } = await import('./lib/messageObjectPreviews')
74
+ return loadTeamPreview(entityId, ctx)
75
+ },
76
+ },
77
+ {
78
+ module: 'staff',
79
+ entityType: 'team_member',
80
+ messageTypes: ['default', 'messages.defaultWithObjects'],
81
+ entityId: 'staff:staff_team_member',
82
+ optionLabelField: 'displayName',
83
+ optionSubtitleField: 'email',
84
+ labelKey: 'staff.teamMembers.page.title',
85
+ icon: 'user-round',
86
+ PreviewComponent: StaffMessageObjectPreview,
87
+ DetailComponent: StaffMessageObjectDetail,
88
+ actions: [],
89
+ loadPreview: async (entityId, ctx) => {
90
+ if (typeof window !== 'undefined') {
91
+ return {
92
+ title: 'Team member',
93
+ subtitle: entityId,
94
+ }
95
+ }
96
+ const { loadTeamMemberPreview } = await import('./lib/messageObjectPreviews')
97
+ return loadTeamMemberPreview(entityId, ctx)
98
+ },
99
+ },
100
+ ]
101
+
102
+ export default messageObjectTypes
@@ -0,0 +1,21 @@
1
+ import type { MessageTypeDefinition } from '@open-mercato/shared/modules/messages/types'
2
+
3
+ export const messageTypes: MessageTypeDefinition[] = [
4
+ {
5
+ type: 'staff.leave_request_approval',
6
+ module: 'staff',
7
+ labelKey: 'staff.messages.leaveRequestApproval',
8
+ icon: 'calendar-clock',
9
+ color: 'amber',
10
+ ui: {
11
+ listItemComponent: 'messages.default.listItem',
12
+ contentComponent: 'messages.default.content',
13
+ actionsComponent: 'messages.default.actions',
14
+ },
15
+ allowReply: true,
16
+ allowForward: true,
17
+ actionsExpireAfterHours: 168,
18
+ }
19
+ ]
20
+
21
+ export default messageTypes