@open-mercato/core 0.8.1-develop.7275.1.f772b944d4 → 0.8.1-develop.7295.1.d0e0e33014

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 (261) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  3. package/dist/modules/auth/components/AclEditor.js +21 -3
  4. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  5. package/dist/modules/customers/backend/customers/companies/page.js +6 -4
  6. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  7. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapView.js +6 -4
  8. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapView.js.map +2 -2
  9. package/dist/modules/customers/backend/customers/deals/page.js +6 -4
  10. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  11. package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js +5 -3
  12. package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js.map +2 -2
  13. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +6 -4
  14. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  15. package/dist/modules/customers/backend/customers/people/page.js +6 -4
  16. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  17. package/dist/modules/customers/components/calendar/editor/PeopleField.js +9 -2
  18. package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
  19. package/dist/modules/customers/components/calendar/editor/hooks.js +4 -2
  20. package/dist/modules/customers/components/calendar/editor/hooks.js.map +2 -2
  21. package/dist/modules/customers/components/calendar/editor/lookups.js +7 -3
  22. package/dist/modules/customers/components/calendar/editor/lookups.js.map +2 -2
  23. package/dist/modules/customers/components/detail/AssignRoleDialog.js +5 -2
  24. package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +2 -2
  25. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +4 -2
  26. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  27. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +8 -5
  28. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  29. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +10 -7
  30. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +2 -2
  31. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +4 -2
  32. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +2 -2
  33. package/dist/modules/customers/components/detail/schedule/fieldConfig.js +9 -0
  34. package/dist/modules/customers/components/detail/schedule/fieldConfig.js.map +2 -2
  35. package/dist/modules/customers/components/detail/schedule/index.js +3 -1
  36. package/dist/modules/customers/components/detail/schedule/index.js.map +2 -2
  37. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +11 -4
  38. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  39. package/dist/modules/customers/components/formConfig.js +17 -9
  40. package/dist/modules/customers/components/formConfig.js.map +2 -2
  41. package/dist/modules/customers/data/validators.js +12 -7
  42. package/dist/modules/customers/data/validators.js.map +2 -2
  43. package/dist/modules/customers/lib/assignableStaff.js +103 -22
  44. package/dist/modules/customers/lib/assignableStaff.js.map +2 -2
  45. package/dist/modules/customers/setup.js +10 -2
  46. package/dist/modules/customers/setup.js.map +2 -2
  47. package/dist/modules/data_sync/api/schedules/[id]/route.js +5 -0
  48. package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
  49. package/dist/modules/data_sync/api/schedules/route.js +5 -0
  50. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  51. package/dist/modules/data_sync/backend/data-sync/page.js +29 -5
  52. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  53. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +48 -11
  54. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  55. package/dist/modules/data_sync/data/validators.js +13 -2
  56. package/dist/modules/data_sync/data/validators.js.map +2 -2
  57. package/dist/modules/data_sync/lib/schedule-value.js +30 -0
  58. package/dist/modules/data_sync/lib/schedule-value.js.map +7 -0
  59. package/dist/modules/eudr/data/validators.js.map +2 -2
  60. package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js +3 -4
  61. package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js.map +2 -2
  62. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +3 -1
  63. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +2 -2
  64. package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js +2 -1
  65. package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js.map +2 -2
  66. package/dist/modules/portal/frontend/[orgSlug]/portal/page.js +3 -4
  67. package/dist/modules/portal/frontend/[orgSlug]/portal/page.js.map +2 -2
  68. package/dist/modules/portal/frontend/[orgSlug]/portal/profile/page.js +3 -4
  69. package/dist/modules/portal/frontend/[orgSlug]/portal/profile/page.js.map +2 -2
  70. package/dist/modules/portal/lib/navigation.js +3 -4
  71. package/dist/modules/portal/lib/navigation.js.map +2 -2
  72. package/dist/modules/query_index/lib/engine.js +155 -15
  73. package/dist/modules/query_index/lib/engine.js.map +2 -2
  74. package/dist/modules/staff/backend/staff/time-tracking/page.js +122 -86
  75. package/dist/modules/staff/backend/staff/time-tracking/page.js.map +2 -2
  76. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +38 -17
  77. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
  78. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js +45 -18
  79. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js.map +2 -2
  80. package/dist/modules/staff/extension-points.js +16 -0
  81. package/dist/modules/staff/extension-points.js.map +2 -2
  82. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js +3 -4
  83. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js.map +2 -2
  84. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js +3 -4
  85. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js.map +2 -2
  86. package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js +14 -13
  87. package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js.map +2 -2
  88. package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js +60 -41
  89. package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js.map +2 -2
  90. package/dist/modules/warranty_claims/api/ai/assess/route.js +2 -2
  91. package/dist/modules/warranty_claims/api/ai/assess/route.js.map +2 -2
  92. package/dist/modules/warranty_claims/api/ai/draft-reply/route.js +3 -4
  93. package/dist/modules/warranty_claims/api/ai/draft-reply/route.js.map +3 -3
  94. package/dist/modules/warranty_claims/api/ai/suggest/route.js +3 -3
  95. package/dist/modules/warranty_claims/api/ai/suggest/route.js.map +2 -2
  96. package/dist/modules/warranty_claims/api/assign/route.js +3 -3
  97. package/dist/modules/warranty_claims/api/assign/route.js.map +2 -2
  98. package/dist/modules/warranty_claims/api/credit-memo/route.js +2 -2
  99. package/dist/modules/warranty_claims/api/credit-memo/route.js.map +2 -2
  100. package/dist/modules/warranty_claims/api/entitlement/route.js +2 -2
  101. package/dist/modules/warranty_claims/api/entitlement/route.js.map +2 -2
  102. package/dist/modules/warranty_claims/api/events/route.js +4 -4
  103. package/dist/modules/warranty_claims/api/events/route.js.map +2 -2
  104. package/dist/modules/warranty_claims/api/external/claims/route.js +3 -3
  105. package/dist/modules/warranty_claims/api/external/claims/route.js.map +2 -2
  106. package/dist/modules/warranty_claims/api/portal/claims/[id]/submit/route.js +2 -2
  107. package/dist/modules/warranty_claims/api/portal/claims/[id]/submit/route.js.map +2 -2
  108. package/dist/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.js +2 -2
  109. package/dist/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.js.map +2 -2
  110. package/dist/modules/warranty_claims/api/portal/claims/route.js +2 -2
  111. package/dist/modules/warranty_claims/api/portal/claims/route.js.map +2 -2
  112. package/dist/modules/warranty_claims/api/portal/events/route.js +2 -2
  113. package/dist/modules/warranty_claims/api/portal/events/route.js.map +2 -2
  114. package/dist/modules/warranty_claims/api/receiving/route.js +2 -2
  115. package/dist/modules/warranty_claims/api/receiving/route.js.map +2 -2
  116. package/dist/modules/warranty_claims/api/replacement-order/route.js +2 -2
  117. package/dist/modules/warranty_claims/api/replacement-order/route.js.map +2 -2
  118. package/dist/modules/warranty_claims/api/return-label/route.js +2 -2
  119. package/dist/modules/warranty_claims/api/return-label/route.js.map +2 -2
  120. package/dist/modules/warranty_claims/api/risk/route.js +2 -2
  121. package/dist/modules/warranty_claims/api/risk/route.js.map +2 -2
  122. package/dist/modules/warranty_claims/api/sales-return/route.js +2 -2
  123. package/dist/modules/warranty_claims/api/sales-return/route.js.map +2 -2
  124. package/dist/modules/warranty_claims/api/settings-general/route.js +4 -4
  125. package/dist/modules/warranty_claims/api/settings-general/route.js.map +2 -2
  126. package/dist/modules/warranty_claims/api/stats/route.js +2 -2
  127. package/dist/modules/warranty_claims/api/stats/route.js.map +2 -2
  128. package/dist/modules/warranty_claims/api/submit/route.js +3 -3
  129. package/dist/modules/warranty_claims/api/submit/route.js.map +2 -2
  130. package/dist/modules/warranty_claims/api/transition/route.js +3 -3
  131. package/dist/modules/warranty_claims/api/transition/route.js.map +2 -2
  132. package/dist/modules/warranty_claims/api/vendor-recovery/route.js +3 -3
  133. package/dist/modules/warranty_claims/api/vendor-recovery/route.js.map +2 -2
  134. package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js +2 -2
  135. package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js.map +2 -2
  136. package/dist/modules/warranty_claims/backend/page.js +4 -2
  137. package/dist/modules/warranty_claims/backend/page.js.map +2 -2
  138. package/dist/modules/warranty_claims/backend/warranty_claims/[id]/page.js +9 -2
  139. package/dist/modules/warranty_claims/backend/warranty_claims/[id]/page.js.map +2 -2
  140. package/dist/modules/warranty_claims/backend/warranty_claims/settings/page.js +4 -2
  141. package/dist/modules/warranty_claims/backend/warranty_claims/settings/page.js.map +2 -2
  142. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/[id]/page.js +3 -4
  143. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/[id]/page.js.map +2 -2
  144. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/new/page.js +3 -2
  145. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/new/page.js.map +2 -2
  146. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -2
  147. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
  148. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -1
  149. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  150. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.js +2 -2
  151. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.js.map +2 -2
  152. package/dist/modules/workflows/lib/event-trigger-service.js +56 -1
  153. package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
  154. package/package.json +7 -7
  155. package/src/modules/auth/api/users/acl/route.ts +4 -3
  156. package/src/modules/auth/components/AclEditor.tsx +38 -2
  157. package/src/modules/auth/i18n/de.json +5 -1
  158. package/src/modules/auth/i18n/en.json +5 -1
  159. package/src/modules/auth/i18n/es.json +5 -1
  160. package/src/modules/auth/i18n/ko.json +5 -1
  161. package/src/modules/auth/i18n/pl.json +5 -1
  162. package/src/modules/customers/backend/customers/companies/page.tsx +6 -4
  163. package/src/modules/customers/backend/customers/deals/map/components/DealsMapView.tsx +6 -4
  164. package/src/modules/customers/backend/customers/deals/page.tsx +6 -4
  165. package/src/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.tsx +5 -3
  166. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +6 -4
  167. package/src/modules/customers/backend/customers/people/page.tsx +6 -4
  168. package/src/modules/customers/components/calendar/editor/PeopleField.tsx +9 -2
  169. package/src/modules/customers/components/calendar/editor/hooks.ts +4 -2
  170. package/src/modules/customers/components/calendar/editor/lookups.ts +12 -4
  171. package/src/modules/customers/components/detail/AssignRoleDialog.tsx +4 -1
  172. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +4 -2
  173. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +15 -7
  174. package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +16 -7
  175. package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +4 -2
  176. package/src/modules/customers/components/detail/schedule/fieldConfig.ts +15 -0
  177. package/src/modules/customers/components/detail/schedule/index.ts +1 -1
  178. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +16 -9
  179. package/src/modules/customers/components/formConfig.tsx +35 -12
  180. package/src/modules/customers/data/validators.ts +14 -8
  181. package/src/modules/customers/i18n/de.json +1 -0
  182. package/src/modules/customers/i18n/en.json +1 -0
  183. package/src/modules/customers/i18n/es.json +1 -0
  184. package/src/modules/customers/i18n/ko.json +1 -0
  185. package/src/modules/customers/i18n/pl.json +1 -0
  186. package/src/modules/customers/lib/assignableStaff.ts +172 -34
  187. package/src/modules/customers/setup.ts +8 -0
  188. package/src/modules/data_sync/api/schedules/[id]/route.ts +5 -0
  189. package/src/modules/data_sync/api/schedules/route.ts +5 -0
  190. package/src/modules/data_sync/backend/data-sync/page.tsx +48 -4
  191. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +61 -2
  192. package/src/modules/data_sync/data/validators.ts +26 -2
  193. package/src/modules/data_sync/i18n/de.json +2 -0
  194. package/src/modules/data_sync/i18n/en.json +2 -0
  195. package/src/modules/data_sync/i18n/es.json +2 -0
  196. package/src/modules/data_sync/i18n/ko.json +2 -0
  197. package/src/modules/data_sync/i18n/pl.json +2 -0
  198. package/src/modules/data_sync/lib/schedule-value.ts +45 -0
  199. package/src/modules/eudr/data/validators.ts +3 -4
  200. package/src/modules/portal/frontend/[orgSlug]/portal/dashboard/page.tsx +5 -4
  201. package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +3 -1
  202. package/src/modules/portal/frontend/[orgSlug]/portal/login/page.tsx +2 -1
  203. package/src/modules/portal/frontend/[orgSlug]/portal/page.tsx +5 -5
  204. package/src/modules/portal/frontend/[orgSlug]/portal/profile/page.tsx +5 -4
  205. package/src/modules/portal/i18n/de.json +1 -0
  206. package/src/modules/portal/i18n/en.json +1 -0
  207. package/src/modules/portal/i18n/es.json +1 -0
  208. package/src/modules/portal/i18n/ko.json +1 -0
  209. package/src/modules/portal/i18n/pl.json +1 -0
  210. package/src/modules/portal/lib/navigation.ts +8 -3
  211. package/src/modules/query_index/lib/engine.ts +238 -17
  212. package/src/modules/staff/backend/staff/time-tracking/page.tsx +161 -130
  213. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +55 -43
  214. package/src/modules/staff/backend/staff/time-tracking/reports/[id]/page.tsx +61 -38
  215. package/src/modules/staff/extension-points.ts +16 -0
  216. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.tsx +3 -4
  217. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/page.tsx +3 -4
  218. package/src/modules/staff/i18n/de.json +3 -0
  219. package/src/modules/staff/i18n/en.json +3 -0
  220. package/src/modules/staff/i18n/es.json +3 -0
  221. package/src/modules/staff/i18n/ko.json +3 -0
  222. package/src/modules/staff/i18n/pl.json +3 -0
  223. package/src/modules/staff/lib/time-tracking-ui/ReportSheet.tsx +32 -29
  224. package/src/modules/staff/lib/time-tracking-ui/TaskListView.tsx +89 -79
  225. package/src/modules/warranty_claims/api/ai/assess/route.ts +2 -2
  226. package/src/modules/warranty_claims/api/ai/draft-reply/route.ts +2 -3
  227. package/src/modules/warranty_claims/api/ai/suggest/route.ts +3 -3
  228. package/src/modules/warranty_claims/api/assign/route.ts +3 -3
  229. package/src/modules/warranty_claims/api/credit-memo/route.ts +2 -2
  230. package/src/modules/warranty_claims/api/entitlement/route.ts +2 -2
  231. package/src/modules/warranty_claims/api/events/route.ts +4 -4
  232. package/src/modules/warranty_claims/api/external/claims/route.ts +3 -3
  233. package/src/modules/warranty_claims/api/portal/claims/[id]/submit/route.ts +2 -2
  234. package/src/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.ts +2 -2
  235. package/src/modules/warranty_claims/api/portal/claims/route.ts +2 -2
  236. package/src/modules/warranty_claims/api/portal/events/route.ts +2 -2
  237. package/src/modules/warranty_claims/api/receiving/route.ts +2 -2
  238. package/src/modules/warranty_claims/api/replacement-order/route.ts +2 -2
  239. package/src/modules/warranty_claims/api/return-label/route.ts +2 -2
  240. package/src/modules/warranty_claims/api/risk/route.ts +2 -2
  241. package/src/modules/warranty_claims/api/sales-return/route.ts +2 -2
  242. package/src/modules/warranty_claims/api/settings-general/route.ts +4 -4
  243. package/src/modules/warranty_claims/api/stats/route.ts +2 -2
  244. package/src/modules/warranty_claims/api/submit/route.ts +3 -3
  245. package/src/modules/warranty_claims/api/transition/route.ts +3 -3
  246. package/src/modules/warranty_claims/api/vendor-recovery/route.ts +3 -3
  247. package/src/modules/warranty_claims/api/vendor-recovery-suggestions/route.ts +2 -2
  248. package/src/modules/warranty_claims/backend/page.tsx +4 -2
  249. package/src/modules/warranty_claims/backend/warranty_claims/[id]/page.tsx +9 -2
  250. package/src/modules/warranty_claims/backend/warranty_claims/settings/page.tsx +4 -2
  251. package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/[id]/page.tsx +5 -4
  252. package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/new/page.tsx +5 -2
  253. package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +5 -2
  254. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -1
  255. package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.tsx +2 -2
  256. package/src/modules/workflows/i18n/de.json +1 -1
  257. package/src/modules/workflows/i18n/en.json +1 -1
  258. package/src/modules/workflows/i18n/es.json +1 -1
  259. package/src/modules/workflows/i18n/ko.json +1 -1
  260. package/src/modules/workflows/i18n/pl.json +1 -1
  261. package/src/modules/workflows/lib/event-trigger-service.ts +139 -0
@@ -1242,6 +1242,9 @@
1242
1242
  "staff.time_tracking.myWork.recentTasks.empty": "Noch keine Zeit auf Aufgaben erfasst.",
1243
1243
  "staff.time_tracking.myWork.recentTasks.title": "Letzte Aufgaben",
1244
1244
  "staff.time_tracking.myWork.today.allEntries": "Alle Einträge",
1245
+ "staff.time_tracking.myWork.today.columns.duration": "Dauer",
1246
+ "staff.time_tracking.myWork.today.columns.task": "Aufgabe",
1247
+ "staff.time_tracking.myWork.today.columns.time": "Zeit",
1245
1248
  "staff.time_tracking.myWork.today.copyYesterday": "Gestern kopieren",
1246
1249
  "staff.time_tracking.myWork.today.empty": "Heute wurde noch nichts erfasst.",
1247
1250
  "staff.time_tracking.myWork.today.title": "Heutige Einträge",
@@ -1242,6 +1242,9 @@
1242
1242
  "staff.time_tracking.myWork.recentTasks.empty": "No tasks logged against yet.",
1243
1243
  "staff.time_tracking.myWork.recentTasks.title": "Recent tasks",
1244
1244
  "staff.time_tracking.myWork.today.allEntries": "All entries",
1245
+ "staff.time_tracking.myWork.today.columns.duration": "Duration",
1246
+ "staff.time_tracking.myWork.today.columns.task": "Task",
1247
+ "staff.time_tracking.myWork.today.columns.time": "Time",
1245
1248
  "staff.time_tracking.myWork.today.copyYesterday": "Copy yesterday",
1246
1249
  "staff.time_tracking.myWork.today.empty": "Nothing logged today yet.",
1247
1250
  "staff.time_tracking.myWork.today.title": "Today’s entries",
@@ -1242,6 +1242,9 @@
1242
1242
  "staff.time_tracking.myWork.recentTasks.empty": "Aún no has registrado tiempo en ninguna tarea.",
1243
1243
  "staff.time_tracking.myWork.recentTasks.title": "Tareas recientes",
1244
1244
  "staff.time_tracking.myWork.today.allEntries": "Todas las entradas",
1245
+ "staff.time_tracking.myWork.today.columns.duration": "Duración",
1246
+ "staff.time_tracking.myWork.today.columns.task": "Tarea",
1247
+ "staff.time_tracking.myWork.today.columns.time": "Tiempo",
1245
1248
  "staff.time_tracking.myWork.today.copyYesterday": "Copiar ayer",
1246
1249
  "staff.time_tracking.myWork.today.empty": "Aún no hay nada registrado hoy.",
1247
1250
  "staff.time_tracking.myWork.today.title": "Entradas de hoy",
@@ -1242,6 +1242,9 @@
1242
1242
  "staff.time_tracking.myWork.recentTasks.empty": "아직 작업에 기록된 시간이 없습니다.",
1243
1243
  "staff.time_tracking.myWork.recentTasks.title": "최근 작업",
1244
1244
  "staff.time_tracking.myWork.today.allEntries": "전체 기록",
1245
+ "staff.time_tracking.myWork.today.columns.duration": "소요 시간",
1246
+ "staff.time_tracking.myWork.today.columns.task": "작업",
1247
+ "staff.time_tracking.myWork.today.columns.time": "시간",
1245
1248
  "staff.time_tracking.myWork.today.copyYesterday": "어제 복사",
1246
1249
  "staff.time_tracking.myWork.today.empty": "오늘 기록된 시간이 없습니다.",
1247
1250
  "staff.time_tracking.myWork.today.title": "오늘의 기록",
@@ -1242,6 +1242,9 @@
1242
1242
  "staff.time_tracking.myWork.recentTasks.empty": "Nie zalogowano jeszcze czasu do żadnego zadania.",
1243
1243
  "staff.time_tracking.myWork.recentTasks.title": "Ostatnie zadania",
1244
1244
  "staff.time_tracking.myWork.today.allEntries": "Wszystkie wpisy",
1245
+ "staff.time_tracking.myWork.today.columns.duration": "Czas trwania",
1246
+ "staff.time_tracking.myWork.today.columns.task": "Zadanie",
1247
+ "staff.time_tracking.myWork.today.columns.time": "Czas",
1245
1248
  "staff.time_tracking.myWork.today.copyYesterday": "Kopiuj wczorajszy dzień",
1246
1249
  "staff.time_tracking.myWork.today.empty": "Nic jeszcze nie zalogowano dzisiaj.",
1247
1250
  "staff.time_tracking.myWork.today.title": "Dzisiejsze wpisy",
@@ -29,6 +29,7 @@ import * as React from 'react'
29
29
  import { z } from 'zod'
30
30
  import { ChevronDown, ChevronRight } from 'lucide-react'
31
31
  import { Badge } from '@open-mercato/ui/primitives/badge'
32
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@open-mercato/ui/primitives/table'
32
33
  import { formatCurrency } from '@open-mercato/ui/utils/format'
33
34
  import { useT } from '@open-mercato/shared/lib/i18n/context'
34
35
  import { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'
@@ -202,26 +203,26 @@ function ReportSheetGroup({ group, showRates, money }: GroupProps) {
202
203
  </div>
203
204
 
204
205
  <div className="overflow-x-auto">
205
- <table className="w-full text-sm">
206
- <thead>
207
- <tr className="border-b border-border text-xs uppercase tracking-wide text-muted-foreground">
208
- <th className="px-6 py-2 text-left font-medium">
206
+ <Table>
207
+ <TableHeader>
208
+ <TableRow className="text-xs uppercase tracking-wide text-muted-foreground">
209
+ <TableHead className="px-6 py-2 text-left">
209
210
  {t('staff.time_tracking.reports.sheet.lineLabel', 'Line')}
210
- </th>
211
- <th className="px-3 py-2 text-right font-medium">
211
+ </TableHead>
212
+ <TableHead className="px-3 py-2 text-right">
212
213
  {t('staff.time_tracking.reports.sheet.time', 'Time')}
213
- </th>
214
+ </TableHead>
214
215
  {showRates ? (
215
- <th className="px-3 py-2 text-right font-medium">
216
+ <TableHead className="px-3 py-2 text-right">
216
217
  {t('staff.time_tracking.reports.sheet.rate', 'Rate')}
217
- </th>
218
+ </TableHead>
218
219
  ) : null}
219
- <th className="px-6 py-2 text-right font-medium">
220
+ <TableHead className="px-6 py-2 text-right">
220
221
  {t('staff.time_tracking.reports.sheet.amount', 'Amount')}
221
- </th>
222
- </tr>
223
- </thead>
224
- <tbody>
222
+ </TableHead>
223
+ </TableRow>
224
+ </TableHeader>
225
+ <TableBody>
225
226
  {group.lines.map((line) => (
226
227
  <ReportSheetLine
227
228
  key={line.key}
@@ -232,8 +233,8 @@ function ReportSheetGroup({ group, showRates, money }: GroupProps) {
232
233
  money={money}
233
234
  />
234
235
  ))}
235
- </tbody>
236
- </table>
236
+ </TableBody>
237
+ </Table>
237
238
  </div>
238
239
  </div>
239
240
  )
@@ -255,8 +256,8 @@ function ReportSheetLine({ line, depth, isNonBillable, showRates, money }: LineP
255
256
 
256
257
  return (
257
258
  <>
258
- <tr className="border-b border-border/60 last:border-b-0">
259
- <td className="px-6 py-2" style={{ paddingLeft: `${1.5 + depth * 1.25}rem` }}>
259
+ <TableRow>
260
+ <TableCell className="px-6 py-2" style={{ paddingLeft: `${1.5 + depth * 1.25}rem` }}>
260
261
  <div className="flex items-center gap-2">
261
262
  {hasChildren ? (
262
263
  <button
@@ -284,17 +285,19 @@ function ReportSheetLine({ line, depth, isNonBillable, showRates, money }: LineP
284
285
  </Badge>
285
286
  ) : null}
286
287
  </div>
287
- </td>
288
- <td className="px-3 py-2 text-right font-mono tabular-nums">{formatReportMinutes(line.minutes)}</td>
288
+ </TableCell>
289
+ <TableCell className="px-3 py-2 text-right font-mono tabular-nums">
290
+ {formatReportMinutes(line.minutes)}
291
+ </TableCell>
289
292
  {showRates ? (
290
- <td className="px-3 py-2 text-right font-mono tabular-nums">
293
+ <TableCell className="px-3 py-2 text-right font-mono tabular-nums">
291
294
  {isNonBillable ? EM_DASH : money(line.rate)}
292
- </td>
295
+ </TableCell>
293
296
  ) : null}
294
- <td className="px-6 py-2 text-right font-mono tabular-nums">
297
+ <TableCell className="px-6 py-2 text-right font-mono tabular-nums">
295
298
  {isNonBillable ? EM_DASH : money(line.amount)}
296
- </td>
297
- </tr>
299
+ </TableCell>
300
+ </TableRow>
298
301
  {expanded
299
302
  ? line.children.map((child) => (
300
303
  <ReportSheetLine
@@ -308,11 +311,11 @@ function ReportSheetLine({ line, depth, isNonBillable, showRates, money }: LineP
308
311
  ))
309
312
  : null}
310
313
  {expanded && line.children.length === 0 ? (
311
- <tr>
312
- <td colSpan={columns} className="px-6 py-2 text-xs text-muted-foreground">
314
+ <TableRow>
315
+ <TableCell colSpan={columns} className="px-6 py-2 text-xs text-muted-foreground">
313
316
  {t('staff.time_tracking.reports.sheet.noSubtasks', 'No subtasks')}
314
- </td>
315
- </tr>
317
+ </TableCell>
318
+ </TableRow>
316
319
  ) : null}
317
320
  </>
318
321
  )
@@ -2,13 +2,16 @@
2
2
 
3
3
  import * as React from 'react'
4
4
  import { useQuery } from '@tanstack/react-query'
5
+ import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'
5
6
  import { Badge } from '@open-mercato/ui/primitives/badge'
6
7
  import { Button } from '@open-mercato/ui/primitives/button'
7
8
  import { EmptyState } from '@open-mercato/ui/primitives/empty-state'
8
9
  import { Spinner } from '@open-mercato/ui/primitives/spinner'
10
+ import { DataTable } from '@open-mercato/ui/backend/DataTable'
9
11
  import { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'
10
12
  import { useT } from '@open-mercato/shared/lib/i18n/context'
11
13
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
14
+ import { extensionPoints } from '@open-mercato/core/modules/staff/extension-points'
12
15
  import { sumTaskLoggedMinutes } from '../timesheets-tasks/taskHoursTotals'
13
16
  import {
14
17
  BOARD_PAGE_SIZE,
@@ -121,6 +124,85 @@ export function TaskListView({
121
124
  onSummaryChange?.(summary)
122
125
  }, [onSummaryChange, summary])
123
126
 
127
+ const columns = React.useMemo<ColumnDef<BoardTask>[]>(
128
+ () => [
129
+ {
130
+ accessorKey: 'reference',
131
+ header: t('staff.time_tracking.board.list.columns.reference', 'Ref.'),
132
+ cell: ({ row }) => (
133
+ <span className="text-xs tabular-nums text-muted-foreground">
134
+ {row.original.reference ?? '—'}
135
+ </span>
136
+ ),
137
+ },
138
+ {
139
+ accessorKey: 'title',
140
+ header: t('staff.time_tracking.board.list.columns.title', 'Task'),
141
+ cell: ({ row }) => (
142
+ <span data-task-row={row.original.id}>
143
+ <Button
144
+ type="button"
145
+ variant="link"
146
+ size="2xs"
147
+ onClick={() => onOpenTask(row.original.id)}
148
+ className="h-auto px-0 text-left text-sm font-semibold text-foreground"
149
+ >
150
+ {row.original.title}
151
+ </Button>
152
+ </span>
153
+ ),
154
+ },
155
+ {
156
+ id: 'status',
157
+ header: t('staff.time_tracking.board.list.columns.status', 'Status'),
158
+ cell: ({ row }) =>
159
+ row.original.taskStatusId ? statusNames.get(row.original.taskStatusId) ?? '—' : '—',
160
+ },
161
+ {
162
+ id: 'assignee',
163
+ header: t('staff.time_tracking.board.list.columns.assignee', 'Assignee'),
164
+ cell: ({ row }) =>
165
+ row.original.assigneeStaffMemberId
166
+ ? assigneeNames.data?.get(row.original.assigneeStaffMemberId) ??
167
+ t('staff.time_tracking.board.card.unassigned', 'Unassigned')
168
+ : t('staff.time_tracking.board.card.unassigned', 'Unassigned'),
169
+ },
170
+ {
171
+ id: 'tags',
172
+ header: t('staff.time_tracking.board.list.columns.tags', 'Tags'),
173
+ cell: ({ row }) => (
174
+ <span className="flex flex-wrap gap-1">
175
+ {row.original.tagIds.map((tagId) => {
176
+ // Same rule as the board card: a tag whose label has not
177
+ // arrived yet is skipped, never drawn as its raw id.
178
+ const label = tagLabels.data?.get(tagId)
179
+ if (!label) return null
180
+ return (
181
+ <Badge key={tagId} variant="neutral" size="sm">
182
+ {label}
183
+ </Badge>
184
+ )
185
+ })}
186
+ </span>
187
+ ),
188
+ },
189
+ {
190
+ id: 'hours',
191
+ header: () => (
192
+ <span className="block text-right">
193
+ {t('staff.time_tracking.board.list.columns.hours', 'Logged')}
194
+ </span>
195
+ ),
196
+ cell: ({ row }) => (
197
+ <span className="block text-right font-semibold tabular-nums text-foreground">
198
+ {formatBoardMinutes(row.original.loggedMinutes)}
199
+ </span>
200
+ ),
201
+ },
202
+ ],
203
+ [assigneeNames.data, onOpenTask, statusNames, t, tagLabels.data],
204
+ )
205
+
124
206
  if (tasksQuery.isLoading) {
125
207
  return <LoadingMessage label={t('staff.time_tracking.board.loading', 'Loading the board…')} />
126
208
  }
@@ -155,85 +237,13 @@ export function TaskListView({
155
237
 
156
238
  return (
157
239
  <div className="flex flex-col gap-3">
158
- <div className="overflow-x-auto rounded-lg border border-border">
159
- <table className="w-full border-collapse text-sm" data-testid="board-task-list">
160
- <caption className="sr-only">
161
- {t('staff.time_tracking.board.list.caption', 'Tasks')}
162
- </caption>
163
- <thead>
164
- <tr className="border-b border-border bg-muted/40 text-left">
165
- <th scope="col" className="px-3 py-2.5 font-semibold text-muted-foreground">
166
- {t('staff.time_tracking.board.list.columns.reference', 'Ref.')}
167
- </th>
168
- <th scope="col" className="px-3 py-2.5 font-semibold text-muted-foreground">
169
- {t('staff.time_tracking.board.list.columns.title', 'Task')}
170
- </th>
171
- <th scope="col" className="px-3 py-2.5 font-semibold text-muted-foreground">
172
- {t('staff.time_tracking.board.list.columns.status', 'Status')}
173
- </th>
174
- <th scope="col" className="px-3 py-2.5 font-semibold text-muted-foreground">
175
- {t('staff.time_tracking.board.list.columns.assignee', 'Assignee')}
176
- </th>
177
- <th scope="col" className="px-3 py-2.5 font-semibold text-muted-foreground">
178
- {t('staff.time_tracking.board.list.columns.tags', 'Tags')}
179
- </th>
180
- <th scope="col" className="px-3 py-2.5 text-right font-semibold text-muted-foreground">
181
- {t('staff.time_tracking.board.list.columns.hours', 'Logged')}
182
- </th>
183
- </tr>
184
- </thead>
185
- <tbody>
186
- {tasks.map((task) => (
187
- <tr
188
- key={task.id}
189
- data-task-row={task.id}
190
- className="border-b border-border last:border-b-0 hover:bg-muted/40"
191
- >
192
- <td className="px-3 py-2.5 text-xs tabular-nums text-muted-foreground">
193
- {task.reference ?? '—'}
194
- </td>
195
- <td className="px-3 py-2.5">
196
- <Button
197
- type="button"
198
- variant="link"
199
- size="2xs"
200
- onClick={() => onOpenTask(task.id)}
201
- className="h-auto px-0 text-left text-sm font-semibold text-foreground"
202
- >
203
- {task.title}
204
- </Button>
205
- </td>
206
- <td className="px-3 py-2.5 text-muted-foreground">
207
- {task.taskStatusId ? statusNames.get(task.taskStatusId) ?? '—' : '—'}
208
- </td>
209
- <td className="px-3 py-2.5 text-muted-foreground">
210
- {task.assigneeStaffMemberId
211
- ? assigneeNames.data?.get(task.assigneeStaffMemberId) ??
212
- t('staff.time_tracking.board.card.unassigned', 'Unassigned')
213
- : t('staff.time_tracking.board.card.unassigned', 'Unassigned')}
214
- </td>
215
- <td className="px-3 py-2.5">
216
- <span className="flex flex-wrap gap-1">
217
- {task.tagIds.map((tagId) => {
218
- // Same rule as the board card: a tag whose label has not
219
- // arrived yet is skipped, never drawn as its raw id.
220
- const label = tagLabels.data?.get(tagId)
221
- if (!label) return null
222
- return (
223
- <Badge key={tagId} variant="neutral" size="sm">
224
- {label}
225
- </Badge>
226
- )
227
- })}
228
- </span>
229
- </td>
230
- <td className="px-3 py-2.5 text-right font-semibold tabular-nums text-foreground">
231
- {formatBoardMinutes(task.loggedMinutes)}
232
- </td>
233
- </tr>
234
- ))}
235
- </tbody>
236
- </table>
240
+ <div data-testid="board-task-list">
241
+ <DataTable<BoardTask>
242
+ extensionTableId={extensionPoints.hosts.taskBoardListViewTable.tableId}
243
+ disableRowClick
244
+ columns={columns}
245
+ data={tasks}
246
+ />
237
247
  </div>
238
248
 
239
249
  {remaining > 0 ? (
@@ -6,7 +6,7 @@ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
6
6
  import { getAuthFromRequest, type AuthContext } from '@open-mercato/shared/lib/auth/server'
7
7
  import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
8
8
  import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
9
- import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
9
+ import { CrudHttpError, isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
10
10
  import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
11
11
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
12
12
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
@@ -344,7 +344,7 @@ export async function POST(req: Request) {
344
344
  }
345
345
  return NextResponse.json({ status: 'ok', extraction })
346
346
  } catch (err) {
347
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
347
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
348
348
  const interceptorRejection = getCommandInterceptorHttpRejection(err)
349
349
  if (interceptorRejection) {
350
350
  return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
@@ -7,7 +7,7 @@ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
7
7
  import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
8
8
  import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
9
9
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
10
- import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
10
+ import { CrudHttpError, isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
11
11
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
12
12
  import { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'
13
13
  import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
@@ -101,10 +101,9 @@ export async function POST(req: Request) {
101
101
  })
102
102
  return NextResponse.json({ ok: true, draft })
103
103
  } catch (err) {
104
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
105
104
  const { translate } = await resolveTranslations()
105
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
106
106
  if (isWarrantyAiUnavailableError(err)) {
107
- const { translate } = await resolveTranslations()
108
107
  return NextResponse.json(
109
108
  { ok: false, aiUnavailable: true, error: translate('warranty_claims.errors.aiUnavailable', 'AI drafting is temporarily unavailable') },
110
109
  { status: 502 },
@@ -5,7 +5,7 @@ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
5
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
6
6
  import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
7
7
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
8
- import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
8
+ import { CrudHttpError, isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
9
9
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
10
10
  import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
11
11
  import { buildWarrantyClaimTriageSuggestion } from '../../../lib/triage'
@@ -134,8 +134,8 @@ export async function GET(req: Request) {
134
134
  const input = suggestSchema.parse({ claimId: url.searchParams.get('claimId') ?? undefined })
135
135
  return buildResponse(context, input)
136
136
  } catch (err) {
137
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
138
137
  const { translate } = await resolveTranslations()
138
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
139
139
  if (err instanceof z.ZodError) {
140
140
  return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
141
141
  }
@@ -150,8 +150,8 @@ export async function POST(req: Request) {
150
150
  const input = suggestSchema.parse(toRecord(await readJsonSafe(req, {})))
151
151
  return buildResponse(context, input)
152
152
  } catch (err) {
153
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
154
153
  const { translate } = await resolveTranslations()
154
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
155
155
  if (err instanceof z.ZodError) {
156
156
  return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
157
157
  }
@@ -5,7 +5,7 @@ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
5
5
  import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
6
6
  import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
7
7
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
8
- import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
8
+ import { CrudHttpError, isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
9
9
  import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
10
10
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
11
11
  import { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'
@@ -114,12 +114,12 @@ export async function POST(req: Request) {
114
114
 
115
115
  return NextResponse.json({ ok: true, claimId: result?.claimId ?? commandInput.id })
116
116
  } catch (err) {
117
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
117
+ const { translate } = await resolveTranslations()
118
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
118
119
  const interceptorRejection = getCommandInterceptorHttpRejection(err)
119
120
  if (interceptorRejection) {
120
121
  return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
121
122
  }
122
- const { translate } = await resolveTranslations()
123
123
  if (err instanceof z.ZodError) {
124
124
  return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
125
125
  }
@@ -4,7 +4,7 @@ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
4
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
5
5
  import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
6
6
  import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
7
- import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
7
+ import { CrudHttpError, isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
8
8
  import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
9
9
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
10
10
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
@@ -160,7 +160,7 @@ export async function POST(req: Request) {
160
160
  currencyCode: result.currencyCode,
161
161
  })
162
162
  } catch (err) {
163
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
163
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
164
164
  const interceptorRejection = getCommandInterceptorHttpRejection(err)
165
165
  if (interceptorRejection) {
166
166
  return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
@@ -4,7 +4,7 @@ import type { EntityManager } from '@mikro-orm/postgresql'
4
4
  import { sql } from 'kysely'
5
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
6
6
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
7
- import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
7
+ import { CrudHttpError, isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
8
8
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
9
9
  import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
10
10
  import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
@@ -195,8 +195,8 @@ export async function GET(req: Request) {
195
195
  )
196
196
  return NextResponse.json({ ...result, ...history })
197
197
  } catch (err) {
198
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
199
198
  const { translate } = await resolveTranslations()
199
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
200
200
  if (err instanceof z.ZodError) {
201
201
  return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
202
202
  }
@@ -6,7 +6,7 @@ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
6
6
  import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
7
7
  import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
8
8
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
9
- import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
9
+ import { CrudHttpError, isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
10
10
  import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
11
11
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
12
12
  import { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'
@@ -141,8 +141,8 @@ export async function GET(req: Request) {
141
141
  )
142
142
  return NextResponse.json({ items: events.map(serializeEvent) })
143
143
  } catch (err) {
144
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
145
144
  const { translate } = await resolveTranslations()
145
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
146
146
  if (err instanceof z.ZodError) {
147
147
  return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
148
148
  }
@@ -175,12 +175,12 @@ export async function POST(req: Request) {
175
175
 
176
176
  return NextResponse.json({ ok: true, claimId: result?.claimId ?? commandInput.claimId })
177
177
  } catch (err) {
178
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
178
+ const { translate } = await resolveTranslations()
179
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
179
180
  const interceptorRejection = getCommandInterceptorHttpRejection(err)
180
181
  if (interceptorRejection) {
181
182
  return NextResponse.json(interceptorRejection.body, { status: interceptorRejection.status })
182
183
  }
183
- const { translate } = await resolveTranslations()
184
184
  if (err instanceof z.ZodError) {
185
185
  return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
186
186
  }
@@ -5,7 +5,7 @@ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
5
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
6
6
  import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
7
7
  import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
8
- import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
8
+ import { CrudHttpError, isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
9
9
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
10
10
  import { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'
11
11
  import { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
@@ -394,8 +394,8 @@ export async function POST(req: Request) {
394
394
  }
395
395
  return submitResponseForClaim(context, claim, 201)
396
396
  } catch (err) {
397
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
398
397
  const { translate } = await resolveTranslations()
398
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
399
399
  if (err instanceof z.ZodError) {
400
400
  return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
401
401
  }
@@ -422,8 +422,8 @@ export async function GET(req: Request) {
422
422
  ])
423
423
  return NextResponse.json(serializeLookupResponse(claim, lines, events))
424
424
  } catch (err) {
425
- if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
426
425
  const { translate } = await resolveTranslations()
426
+ if (isCrudHttpError(err)) return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
427
427
  if (err instanceof z.ZodError) {
428
428
  return NextResponse.json({ error: translate('warranty_claims.errors.invalidInput', 'Invalid input') }, { status: 400 })
429
429
  }
@@ -1,7 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
3
  import type { CommandBus } from '@open-mercato/shared/lib/commands'
4
- import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
4
+ import { isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
5
5
  import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
6
6
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
7
7
  import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
@@ -54,7 +54,7 @@ export async function POST(req: Request, ctx: PortalClaimActionRouteContext) {
54
54
  )
55
55
  } catch (err) {
56
56
  if (isCrudHttpError(err)) {
57
- return NextResponse.json(err.body, { status: err.status })
57
+ return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
58
58
  }
59
59
  const interceptorRejection = getCommandInterceptorHttpRejection(err)
60
60
  if (interceptorRejection) {
@@ -1,7 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
3
  import type { CommandBus } from '@open-mercato/shared/lib/commands'
4
- import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
4
+ import { isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
5
5
  import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
6
6
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
7
7
  import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
@@ -60,7 +60,7 @@ export async function POST(req: Request, ctx: PortalClaimActionRouteContext) {
60
60
  )
61
61
  } catch (err) {
62
62
  if (isCrudHttpError(err)) {
63
- return NextResponse.json(err.body, { status: err.status })
63
+ return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
64
64
  }
65
65
  const interceptorRejection = getCommandInterceptorHttpRejection(err)
66
66
  if (interceptorRejection) {
@@ -4,7 +4,7 @@ import type { EntityManager } from '@mikro-orm/postgresql'
4
4
  import type { AuthContext } from '@open-mercato/shared/lib/auth/server'
5
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
6
6
  import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
7
- import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
7
+ import { isCrudHttpError, translateCrudErrorBody } from '@open-mercato/shared/lib/crud/errors'
8
8
  import { getCommandInterceptorHttpRejection } from '@open-mercato/shared/lib/commands/errors'
9
9
  import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
10
10
  import { runRouteMutationGuards, type RouteMutationGuardResult } from '@open-mercato/shared/lib/crud/route-mutation-guard'
@@ -517,7 +517,7 @@ export async function POST(req: Request) {
517
517
  return NextResponse.json({ ok: true, claimId }, { status: 201 })
518
518
  } catch (err) {
519
519
  if (isCrudHttpError(err)) {
520
- return NextResponse.json(err.body, { status: err.status })
520
+ return NextResponse.json(translateCrudErrorBody(err.body, translate), { status: err.status })
521
521
  }
522
522
  const interceptorRejection = getCommandInterceptorHttpRejection(err)
523
523
  if (interceptorRejection) {