@open-mercato/core 0.4.5-develop-5191db4ef3 → 0.4.5-develop-033a719bf2

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,108 @@
1
+ "use client"
2
+
3
+ import * as React from 'react'
4
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
5
+ import { FormHeader, type ActionItem } from '@open-mercato/ui/backend/forms'
6
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
7
+ import { Archive, Forward, MailMinus, Reply, Trash2 } from 'lucide-react'
8
+ import { PriorityBadge } from '../../utils/PriorityBadge'
9
+
10
+ type MainMessageHeaderProps = {
11
+ subject: string
12
+ priority: 'low' | 'normal' | 'high' | 'urgent'
13
+ canReply: boolean
14
+ canForwardAll: boolean
15
+ actionsDisabled?: boolean
16
+ activeActionId?: 'forwardAll' | 'archiveConversation' | 'markAllUnread' | 'deleteConversation' | null
17
+ onReply: () => void
18
+ onForwardAll: () => void
19
+ onArchiveConversation: () => void
20
+ onMarkAllUnread: () => void
21
+ onDeleteConversation: () => void
22
+ }
23
+
24
+ export function MainMessageHeader(props: MainMessageHeaderProps) {
25
+ const t = useT()
26
+
27
+ const menuActions = React.useMemo<ActionItem[]>(() => [
28
+ {
29
+ id: 'reply',
30
+ label: t('messages.reply', 'Reply'),
31
+ icon: Reply,
32
+ onSelect: props.onReply,
33
+ disabled: props.actionsDisabled || !props.canReply,
34
+ },
35
+ {
36
+ id: 'forward-all',
37
+ label: t('messages.actions.forwardAll', 'Forward all'),
38
+ icon: Forward,
39
+ onSelect: props.onForwardAll,
40
+ disabled: props.actionsDisabled || !props.canForwardAll,
41
+ loading: props.activeActionId === 'forwardAll',
42
+ },
43
+ {
44
+ id: 'archive-conversation',
45
+ label: t('messages.actions.archiveConversation', 'Archive conversation'),
46
+ icon: Archive,
47
+ onSelect: props.onArchiveConversation,
48
+ disabled: props.actionsDisabled,
49
+ loading: props.activeActionId === 'archiveConversation',
50
+ },
51
+ {
52
+ id: 'mark-all-unread',
53
+ label: t('messages.actions.markAllUnread', 'Mark all unread'),
54
+ icon: MailMinus,
55
+ onSelect: props.onMarkAllUnread,
56
+ disabled: props.actionsDisabled,
57
+ loading: props.activeActionId === 'markAllUnread',
58
+ },
59
+ {
60
+ id: 'delete-conversation',
61
+ label: t('messages.actions.deleteConversation', 'Delete conversation'),
62
+ icon: Trash2,
63
+ onSelect: props.onDeleteConversation,
64
+ disabled: props.actionsDisabled,
65
+ loading: props.activeActionId === 'deleteConversation',
66
+ },
67
+ ], [
68
+ props.actionsDisabled,
69
+ props.canForwardAll,
70
+ props.canReply,
71
+ props.onArchiveConversation,
72
+ props.onDeleteConversation,
73
+ props.onForwardAll,
74
+ props.onMarkAllUnread,
75
+ props.onReply,
76
+ props.activeActionId,
77
+ t,
78
+ ])
79
+
80
+ return (
81
+ <FormHeader
82
+ mode="detail"
83
+ backHref="/backend/messages"
84
+ backLabel={t('messages.actions.backToList', 'Back to messages')}
85
+ title={(
86
+ <span className="inline-flex items-center gap-2">
87
+ <span className="truncate">{props.subject}</span>
88
+ <PriorityBadge priority={props.priority} />
89
+ </span>
90
+ )}
91
+ utilityActions={props.canReply ? (
92
+ <IconButton
93
+ type="button"
94
+ variant="outline"
95
+ size="default"
96
+ aria-label={t('messages.reply', 'Reply')}
97
+ onClick={props.onReply}
98
+ disabled={props.actionsDisabled || !props.canReply}
99
+ >
100
+ <Reply className="h-4 w-4" aria-hidden />
101
+ </IconButton>
102
+ ) : undefined}
103
+ menuTriggerMode="icon"
104
+ menuAriaLabel={t('messages.actions.conversationActions', 'Conversation actions')}
105
+ menuActions={menuActions}
106
+ />
107
+ )
108
+ }
@@ -0,0 +1,144 @@
1
+ "use client"
2
+
3
+ import * as React from 'react'
4
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
5
+ import { FormHeader, type ActionItem } from '@open-mercato/ui/backend/forms'
6
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
7
+ import {
8
+ Archive,
9
+ ArchiveRestore,
10
+ ChevronDown,
11
+ ChevronUp,
12
+ FilePenLine,
13
+ Forward,
14
+ Mail,
15
+ MailOpen,
16
+ Reply,
17
+ Trash2,
18
+ } from 'lucide-react'
19
+ import type { MessageDetail } from '../types'
20
+ import { formatDateTime } from '../utils'
21
+
22
+ type MessageHeaderProps = {
23
+ detail: MessageDetail
24
+ updatingState: boolean
25
+ isArchived: boolean
26
+ showSubject?: boolean
27
+ onReply: () => void
28
+ onForward: () => void
29
+ onEdit: () => void
30
+ onToggleRead: () => void
31
+ onToggleArchive: () => void
32
+ onDelete: () => void
33
+ collapseToggle?: {
34
+ expanded: boolean
35
+ onToggle: () => void
36
+ }
37
+ }
38
+
39
+ export function MessageHeader(props: MessageHeaderProps) {
40
+ const t = useT()
41
+ const showSubject = props.showSubject !== false
42
+ const canReply = !props.detail.isDraft && props.detail.typeDefinition.allowReply
43
+ const actionItems = React.useMemo(() => {
44
+ const items: ActionItem[] = []
45
+
46
+ if (props.detail.isDraft && props.detail.canEditDraft) {
47
+ items.push({
48
+ id: 'edit',
49
+ label: t('messages.actions.edit', 'Edit'),
50
+ icon: FilePenLine,
51
+ onSelect: props.onEdit,
52
+ })
53
+ }
54
+
55
+ if (!props.detail.isDraft && props.detail.typeDefinition.allowForward) {
56
+ items.push({
57
+ id: 'forward',
58
+ label: t('messages.forward', 'Forward'),
59
+ icon: Forward,
60
+ onSelect: props.onForward,
61
+ })
62
+ }
63
+
64
+ if (!props.detail.isDraft) {
65
+ items.push({
66
+ id: 'toggle-read',
67
+ label: props.detail.isRead
68
+ ? t('messages.actions.markUnread', 'Mark unread')
69
+ : t('messages.actions.markRead', 'Mark read'),
70
+ icon: props.detail.isRead ? Mail : MailOpen,
71
+ onSelect: props.onToggleRead,
72
+ disabled: props.updatingState,
73
+ })
74
+ }
75
+
76
+ if (!props.detail.isDraft) {
77
+ items.push({
78
+ id: 'toggle-archive',
79
+ label: props.isArchived
80
+ ? t('messages.actions.unarchive', 'Unarchive')
81
+ : t('messages.actions.archive', 'Archive'),
82
+ icon: props.isArchived ? ArchiveRestore : Archive,
83
+ onSelect: props.onToggleArchive,
84
+ disabled: props.updatingState,
85
+ })
86
+ }
87
+
88
+ items.push({
89
+ id: 'delete',
90
+ label: t('messages.actions.delete', 'Delete'),
91
+ icon: Trash2,
92
+ onSelect: props.onDelete,
93
+ disabled: props.updatingState,
94
+ })
95
+
96
+ return items
97
+ }, [props, t])
98
+
99
+ return (
100
+ <div className="flex items-start gap-2">
101
+ {props.collapseToggle ? (
102
+ <IconButton
103
+ type="button"
104
+ onClick={props.collapseToggle.onToggle}
105
+ variant="ghost"
106
+ size="sm"
107
+ className="mt-1 text-muted-foreground hover:text-foreground"
108
+ aria-label={props.collapseToggle.expanded
109
+ ? t('messages.detail.hideDetails', 'Hide details')
110
+ : t('messages.detail.showDetails', 'Show details')}
111
+ >
112
+ {props.collapseToggle.expanded ? (
113
+ <ChevronUp className="h-4 w-4" aria-hidden />
114
+ ) : (
115
+ <ChevronDown className="h-4 w-4" aria-hidden />
116
+ )}
117
+ </IconButton>
118
+ ) : null}
119
+
120
+ <div className="min-w-0 flex-1">
121
+ <FormHeader
122
+ mode="detail"
123
+ title={showSubject ? props.detail.subject : undefined}
124
+ subtitle={`${t('messages.detail.from', 'From')}: ${props.detail.senderName || props.detail.senderEmail || props.detail.senderUserId}`}
125
+ statusBadge={<p className="text-xs text-muted-foreground">{formatDateTime(props.detail.sentAt)}</p>}
126
+ utilityActions={canReply ? (
127
+ <IconButton
128
+ type="button"
129
+ variant="outline"
130
+ size="default"
131
+ aria-label={t('messages.reply', 'Reply')}
132
+ onClick={props.onReply}
133
+ >
134
+ <Reply className="h-4 w-4" aria-hidden />
135
+ </IconButton>
136
+ ) : undefined}
137
+ menuTriggerMode="icon"
138
+ menuAriaLabel={t('ui.actions.actions', 'Actions')}
139
+ menuActions={actionItems}
140
+ />
141
+ </div>
142
+ </div>
143
+ )
144
+ }
@@ -0,0 +1,63 @@
1
+ "use client"
2
+
3
+ import type { MessageListItemProps } from '@open-mercato/shared/modules/messages/types'
4
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
5
+ import { cn } from '@open-mercato/shared/lib/utils'
6
+
7
+ function formatSentTime(value: Date | null): string {
8
+ if (!value || Number.isNaN(value.getTime())) return '—'
9
+
10
+ const now = new Date()
11
+ if (now.toDateString() === value.toDateString()) {
12
+ return value.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
13
+ }
14
+
15
+ return value.toLocaleDateString([], { month: 'short', day: 'numeric' })
16
+ }
17
+
18
+ function normalizeBody(value: string | null): string {
19
+ const normalized = (value ?? '').trim().replace(/\s+/g, ' ')
20
+ return normalized || '—'
21
+ }
22
+
23
+ export function MessageListComponent({ message, onClick }: MessageListItemProps) {
24
+ const t = useT()
25
+ const senderLabel = message.senderName || '—'
26
+ const body = normalizeBody(message.body)
27
+ const sentAtLabel = formatSentTime(message.sentAt)
28
+
29
+ return (
30
+ <div
31
+ className={cn(
32
+ 'group min-w-0 w-full cursor-pointer rounded-md px-2 py-2 transition-colors hover:bg-muted/40',
33
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
34
+ )}
35
+ role="button"
36
+ tabIndex={0}
37
+ aria-label={t('messages.openMessageA11y', 'Open message from {sender}', { sender: senderLabel })}
38
+ onClick={onClick}
39
+ onKeyDown={(event) => {
40
+ if (event.key === 'Enter' || event.key === ' ') {
41
+ event.preventDefault()
42
+ onClick()
43
+ }
44
+ }}
45
+ >
46
+ <div className="flex items-center gap-3">
47
+ <span className={cn('w-40 flex-shrink-0 truncate text-sm md:w-56', message.unread ? 'font-semibold' : 'font-normal')}>
48
+ {senderLabel}
49
+ </span>
50
+
51
+ <span className="min-w-0 flex-1 truncate text-sm text-muted-foreground">{body}</span>
52
+
53
+ <span
54
+ className={cn('flex-shrink-0 text-xs', message.unread ? 'font-semibold text-foreground' : 'font-normal text-muted-foreground')}
55
+ >
56
+ {sentAtLabel}
57
+ </span>
58
+ </div>
59
+ </div>
60
+ )
61
+ }
62
+
63
+ export default MessageListComponent
@@ -0,0 +1,66 @@
1
+ "use client"
2
+
3
+ import type { ComponentType } from 'react'
4
+ import type { MessageActionsProps } 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 type { MessageAction, MessageDetail } from '../types'
8
+ import { formatDateTime } from '../utils'
9
+
10
+ type ActionsPanelProps = {
11
+ detail: MessageDetail
12
+ messageActions: MessageAction[]
13
+ executingActionId: string | null
14
+ ActionsComponent: ComponentType<MessageActionsProps> | null
15
+ onExecuteActionById: MessageActionsProps['onExecuteAction']
16
+ onExecuteAction: (action: MessageAction, payload?: Record<string, unknown>) => Promise<void>
17
+ }
18
+
19
+ export function MessageDetailActionsSection(props: ActionsPanelProps) {
20
+ const t = useT()
21
+
22
+ if (!props.messageActions.length) return null
23
+
24
+ return (
25
+ <section className="space-y-3 border-l pl-4 py-2">
26
+ <h2 className="text-base font-semibold">{t('messages.actions.title', 'Actions')}</h2>
27
+ {props.ActionsComponent ? (
28
+ <props.ActionsComponent
29
+ message={{
30
+ id: props.detail.id,
31
+ type: props.detail.type,
32
+ actionData: {
33
+ ...(props.detail.actionData ?? {}),
34
+ actions: props.messageActions,
35
+ },
36
+ actionTaken: props.detail.actionTaken ?? null,
37
+ }}
38
+ onExecuteAction={props.onExecuteActionById}
39
+ isExecuting={props.executingActionId !== null}
40
+ executingActionId={props.executingActionId}
41
+ />
42
+ ) : (
43
+ <div className="flex flex-wrap gap-2">
44
+ {props.messageActions.map((action) => (
45
+ <Button
46
+ key={action.id}
47
+ type="button"
48
+ variant={action.variant ?? 'default'}
49
+ disabled={Boolean(props.detail.actionTaken) || props.executingActionId !== null}
50
+ onClick={() => void props.onExecuteAction(action)}
51
+ >
52
+ {props.executingActionId === action.id
53
+ ? t('messages.actions.executing', 'Executing...')
54
+ : t(action.labelKey || action.label, action.label)}
55
+ </Button>
56
+ ))}
57
+ </div>
58
+ )}
59
+ {props.detail.actionTaken ? (
60
+ <p className="text-xs text-muted-foreground">
61
+ {t('messages.actions.taken', 'Action taken')}: {props.detail.actionTaken} ({formatDateTime(props.detail.actionTakenAt)})
62
+ </p>
63
+ ) : null}
64
+ </section>
65
+ )
66
+ }
@@ -0,0 +1,86 @@
1
+ "use client"
2
+
3
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
4
+ import {
5
+ AttachmentVisualPreview,
6
+ formatAttachmentFileSize,
7
+ } from '@open-mercato/ui/backend/detail/AttachmentVisualPreview'
8
+ import {
9
+ buildAttachmentImageUrl,
10
+ slugifyAttachmentFileName,
11
+ } from '@open-mercato/core/modules/attachments/lib/imageUrls'
12
+ import type { MessageAttachment } from '../types'
13
+
14
+ type AttachmentsPanelProps = {
15
+ attachmentsQuery: { isLoading: boolean; error: unknown }
16
+ attachments: MessageAttachment[] | undefined
17
+ }
18
+
19
+ export function MessageDetailAttachmentsSection(props: AttachmentsPanelProps) {
20
+ const t = useT()
21
+
22
+ if (props.attachmentsQuery.isLoading) {
23
+ return (
24
+ <section className="space-y-3 pl-4 py-2">
25
+ <h2 className="text-base font-semibold">{t('messages.attachedFiles', 'Attachments')}</h2>
26
+ <p className="text-sm text-muted-foreground">{t('messages.loading.attachments', 'Loading attachments...')}</p>
27
+ </section>
28
+ )
29
+ }
30
+
31
+ if (props.attachmentsQuery.error) {
32
+ return (
33
+ <section className="space-y-3 pl-4 py-2">
34
+ <h2 className="text-base font-semibold">{t('messages.attachedFiles', 'Attachments')}</h2>
35
+ <p className="text-sm text-destructive">
36
+ {props.attachmentsQuery.error instanceof Error
37
+ ? props.attachmentsQuery.error.message
38
+ : t('messages.errors.loadAttachmentsFailed', 'Failed to load attachments.')}
39
+ </p>
40
+ </section>
41
+ )
42
+ }
43
+
44
+ if ((props.attachments ?? []).length === 0) return null
45
+
46
+ return (
47
+ <section className="space-y-3 pl-4 py-2">
48
+ <h2 className="text-base font-semibold">{t('messages.attachedFiles', 'Attachments')}</h2>
49
+ <div className="space-y-2">
50
+ {(props.attachments ?? []).map((attachment) => (
51
+ <a
52
+ key={attachment.id}
53
+ href={attachment.url}
54
+ target="_blank"
55
+ rel="noreferrer"
56
+ className="flex items-center gap-3 rounded px-3 py-2 text-sm hover:bg-muted"
57
+ >
58
+ <AttachmentVisualPreview
59
+ fileName={attachment.fileName}
60
+ mimeType={attachment.mimeType}
61
+ thumbnailUrl={
62
+ attachment.mimeType?.toLowerCase().startsWith('image/')
63
+ ? buildAttachmentImageUrl(attachment.id, {
64
+ width: 120,
65
+ height: 120,
66
+ slug: slugifyAttachmentFileName(attachment.fileName),
67
+ cropType: 'cover',
68
+ })
69
+ : null
70
+ }
71
+ className="h-11 w-11 shrink-0 overflow-hidden rounded"
72
+ iconClassName="mb-0 h-4 w-4"
73
+ labelClassName="text-[10px]"
74
+ />
75
+ <div className="min-w-0 flex-1">
76
+ <p className="truncate">{attachment.fileName}</p>
77
+ <p className="text-xs text-muted-foreground">
78
+ {formatAttachmentFileSize(attachment.fileSize)}
79
+ </p>
80
+ </div>
81
+ </a>
82
+ ))}
83
+ </div>
84
+ </section>
85
+ )
86
+ }
@@ -0,0 +1,32 @@
1
+ "use client"
2
+
3
+ import * as React from 'react'
4
+ import type { MessageContentProps } from '@open-mercato/shared/modules/messages/types'
5
+ import { MarkdownContent } from '@open-mercato/ui/backend/markdown/MarkdownContent'
6
+ import type { MessageDetail } from '../types'
7
+
8
+ type BodyPanelProps = {
9
+ detail: MessageDetail
10
+ contentProps: MessageContentProps
11
+ ContentComponent: React.ComponentType<MessageContentProps> | null
12
+ }
13
+
14
+ export function MessageDetailBodySection(props: BodyPanelProps) {
15
+ if (props.ContentComponent) {
16
+ return (
17
+ <div className="rounded border bg-muted/30 p-3">
18
+ <props.ContentComponent {...props.contentProps} />
19
+ </div>
20
+ )
21
+ }
22
+
23
+ return (
24
+ <div className="rounded border bg-muted/30 p-3 text-sm whitespace-pre-wrap">
25
+ <MarkdownContent
26
+ body={props.detail.body}
27
+ format={props.detail.bodyFormat}
28
+ className="text-sm whitespace-pre-wrap [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs"
29
+ />
30
+ </div>
31
+ )
32
+ }
@@ -0,0 +1,42 @@
1
+ "use client"
2
+
3
+ import { MessageComposer } from '@open-mercato/ui/backend/messages'
4
+ import type { MessageAttachment, MessageDetail } from '../types'
5
+
6
+ type ComposerDialogsProps = {
7
+ id: string
8
+ detail: MessageDetail
9
+ attachments: MessageAttachment[] | undefined
10
+ editOpen: boolean
11
+ setEditOpen: (value: boolean) => void
12
+ onRefresh: () => Promise<unknown>
13
+ }
14
+
15
+ export function MessageDetailComposerDialogs(props: ComposerDialogsProps) {
16
+ return (
17
+ <MessageComposer
18
+ variant="compose"
19
+ messageId={props.id}
20
+ open={props.editOpen && props.detail.isDraft && props.detail.canEditDraft}
21
+ onOpenChange={props.setEditOpen}
22
+ defaultValues={{
23
+ type: props.detail.type,
24
+ recipients: props.detail.recipients.map((recipient) => recipient.userId),
25
+ subject: props.detail.subject,
26
+ body: props.detail.body,
27
+ bodyFormat: props.detail.bodyFormat,
28
+ priority: props.detail.priority as 'low' | 'normal' | 'high' | 'urgent',
29
+ visibility: props.detail.visibility ?? 'internal',
30
+ sourceEntityType: props.detail.sourceEntityType ?? null,
31
+ sourceEntityId: props.detail.sourceEntityId ?? null,
32
+ externalEmail: props.detail.externalEmail ?? null,
33
+ externalName: props.detail.externalName ?? null,
34
+ attachmentIds: props.attachments?.map((attachment) => attachment.id) ?? [],
35
+ }}
36
+ onSuccess={() => {
37
+ props.setEditOpen(false)
38
+ void props.onRefresh()
39
+ }}
40
+ />
41
+ )
42
+ }
@@ -0,0 +1,107 @@
1
+ "use client"
2
+
3
+ import * as React from 'react'
4
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
5
+ import { Button } from '@open-mercato/ui/primitives/button'
6
+ import {
7
+ Dialog,
8
+ DialogContent,
9
+ DialogDescription,
10
+ DialogFooter,
11
+ DialogHeader,
12
+ DialogTitle,
13
+ } from '@open-mercato/ui/primitives/dialog'
14
+ import type { PendingActionConfirmation } from '../types'
15
+
16
+ type DialogsProps = {
17
+ pendingActionConfirmation: PendingActionConfirmation | null
18
+ setPendingActionConfirmation: (value: PendingActionConfirmation | null) => void
19
+ executingActionId: string | null
20
+ handleConfirmPendingAction: () => Promise<void>
21
+ handleActionConfirmDialogKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => void
22
+ deleteConfirmationOpen: boolean
23
+ setDeleteConfirmationOpen: (value: boolean) => void
24
+ updatingState: boolean
25
+ handleDelete: () => Promise<void>
26
+ handleDeleteDialogKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => void
27
+ }
28
+
29
+ export function MessageDetailDialogs(props: DialogsProps) {
30
+ const t = useT()
31
+
32
+ return (
33
+ <>
34
+ <Dialog
35
+ open={Boolean(props.pendingActionConfirmation)}
36
+ onOpenChange={(open) => {
37
+ if (!open) props.setPendingActionConfirmation(null)
38
+ }}
39
+ >
40
+ <DialogContent className="sm:max-w-md" onKeyDown={props.handleActionConfirmDialogKeyDown}>
41
+ <DialogHeader>
42
+ <DialogTitle>{t('messages.confirm.actionTitle', 'Confirm action')}</DialogTitle>
43
+ <DialogDescription>
44
+ {props.pendingActionConfirmation?.action.confirmMessage
45
+ || t('messages.confirm.action', 'Are you sure you want to continue?')}
46
+ </DialogDescription>
47
+ </DialogHeader>
48
+ <DialogFooter>
49
+ <Button
50
+ type="button"
51
+ variant="outline"
52
+ onClick={() => props.setPendingActionConfirmation(null)}
53
+ disabled={props.executingActionId !== null}
54
+ >
55
+ {t('common.cancel', 'Cancel')}
56
+ </Button>
57
+ <Button
58
+ type="button"
59
+ variant={props.pendingActionConfirmation?.action.variant === 'destructive' ? 'destructive' : 'default'}
60
+ onClick={() => void props.handleConfirmPendingAction()}
61
+ disabled={props.executingActionId !== null}
62
+ >
63
+ {props.executingActionId === props.pendingActionConfirmation?.action.id
64
+ ? t('messages.actions.executing', 'Executing...')
65
+ : t(
66
+ props.pendingActionConfirmation?.action.labelKey || props.pendingActionConfirmation?.action.label || 'messages.confirm.actionConfirm',
67
+ props.pendingActionConfirmation?.action.label || t('messages.confirm.actionConfirm', 'Confirm'),
68
+ )}
69
+ </Button>
70
+ </DialogFooter>
71
+ </DialogContent>
72
+ </Dialog>
73
+
74
+ <Dialog
75
+ open={props.deleteConfirmationOpen}
76
+ onOpenChange={props.setDeleteConfirmationOpen}
77
+ >
78
+ <DialogContent className="sm:max-w-md" onKeyDown={props.handleDeleteDialogKeyDown}>
79
+ <DialogHeader>
80
+ <DialogTitle>{t('messages.confirm.deleteTitle', 'Delete message')}</DialogTitle>
81
+ <DialogDescription>
82
+ {t('messages.confirm.delete', 'Delete this message from your view?')}
83
+ </DialogDescription>
84
+ </DialogHeader>
85
+ <DialogFooter>
86
+ <Button
87
+ type="button"
88
+ variant="outline"
89
+ onClick={() => props.setDeleteConfirmationOpen(false)}
90
+ disabled={props.updatingState}
91
+ >
92
+ {t('common.cancel', 'Cancel')}
93
+ </Button>
94
+ <Button
95
+ type="button"
96
+ variant="destructive"
97
+ onClick={() => void props.handleDelete()}
98
+ disabled={props.updatingState}
99
+ >
100
+ {t('messages.actions.delete', 'Delete')}
101
+ </Button>
102
+ </DialogFooter>
103
+ </DialogContent>
104
+ </Dialog>
105
+ </>
106
+ )
107
+ }
@@ -0,0 +1,11 @@
1
+ export { MessageHeader } from './MessageHeader'
2
+ export { MainMessageHeader } from './MainMessageHeader'
3
+ export { MessageListComponent } from './MessageListComponent'
4
+ export { MessageDetailBodySection } from './body-panel'
5
+ export { MessageDetailMetaSection } from './meta-panel'
6
+ export { MessageDetailActionsSection } from './actions-panel'
7
+ export { MessageDetailObjectsSection } from './objects-panel'
8
+ export { MessageDetailAttachmentsSection } from './attachments-panel'
9
+ export { MessageDetailThreadSection } from './thread-panel'
10
+ export { MessageDetailComposerDialogs } from './composer-dialogs'
11
+ export { MessageDetailDialogs } from './dialogs'
@@ -0,0 +1,19 @@
1
+ "use client"
2
+
3
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
4
+ import type { MessageDetail } from '../types'
5
+
6
+ export function MessageDetailMetaSection({ detail }: { detail: MessageDetail }) {
7
+ const t = useT()
8
+
9
+ return (
10
+ <div className="grid gap-3 sm:grid-cols-2">
11
+ {detail.externalEmail ? (
12
+ <div className="space-y-1 rounded border p-3 text-sm">
13
+ <p className="font-medium">{t('messages.externalEmail', 'External email')}</p>
14
+ <p>{detail.externalEmail}</p>
15
+ </div>
16
+ ) : null}
17
+ </div>
18
+ )
19
+ }