@open-mercato/core 0.7.1-develop.7152.1.a69e92f9c9 → 0.7.1-develop.7153.1.7145d295e6

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 (439) hide show
  1. package/dist/modules/api_keys/backend/api-keys/create/page.js +1 -0
  2. package/dist/modules/api_keys/backend/api-keys/create/page.js.map +2 -2
  3. package/dist/modules/api_keys/backend/api-keys/page.js +1 -0
  4. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  5. package/dist/modules/attachments/components/AttachmentLibrary.js +1 -0
  6. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  7. package/dist/modules/audit_logs/backend/audit-logs/page.js +53 -50
  8. package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
  9. package/dist/modules/audit_logs/components/AccessLogsTable.js +1 -0
  10. package/dist/modules/audit_logs/components/AccessLogsTable.js.map +2 -2
  11. package/dist/modules/audit_logs/components/AuditLogsActions.js +1 -0
  12. package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
  13. package/dist/modules/auth/backend/roles/[id]/edit/page.js +1 -0
  14. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  15. package/dist/modules/auth/backend/roles/create/page.js +1 -0
  16. package/dist/modules/auth/backend/roles/create/page.js.map +2 -2
  17. package/dist/modules/auth/backend/roles/page.js +1 -0
  18. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  19. package/dist/modules/auth/backend/users/[id]/edit/page.js +1 -0
  20. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  21. package/dist/modules/auth/backend/users/create/page.js +1 -0
  22. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  23. package/dist/modules/auth/backend/users/page.js +1 -0
  24. package/dist/modules/auth/backend/users/page.js.map +2 -2
  25. package/dist/modules/business_rules/backend/logs/page.js +1 -0
  26. package/dist/modules/business_rules/backend/logs/page.js.map +2 -2
  27. package/dist/modules/business_rules/backend/rules/[id]/page.js +1 -0
  28. package/dist/modules/business_rules/backend/rules/[id]/page.js.map +2 -2
  29. package/dist/modules/business_rules/backend/rules/create/page.js +1 -0
  30. package/dist/modules/business_rules/backend/rules/create/page.js.map +2 -2
  31. package/dist/modules/business_rules/backend/rules/page.js +1 -0
  32. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  33. package/dist/modules/business_rules/backend/sets/[id]/page.js +1 -0
  34. package/dist/modules/business_rules/backend/sets/[id]/page.js.map +2 -2
  35. package/dist/modules/business_rules/backend/sets/create/page.js +1 -0
  36. package/dist/modules/business_rules/backend/sets/create/page.js.map +2 -2
  37. package/dist/modules/business_rules/backend/sets/page.js +1 -0
  38. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  39. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +1 -0
  40. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
  41. package/dist/modules/catalog/backend/catalog/categories/create/page.js +1 -0
  42. package/dist/modules/catalog/backend/catalog/categories/create/page.js.map +2 -2
  43. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +1 -0
  44. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  45. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +1 -0
  46. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  47. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js +1 -0
  48. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js.map +2 -2
  49. package/dist/modules/catalog/backend/catalog/products/create/page.js +1 -0
  50. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  51. package/dist/modules/catalog/components/categories/CategoriesDataTable.js +1 -0
  52. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  53. package/dist/modules/catalog/components/products/ProductsDataTable.js +1 -0
  54. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  55. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +1 -0
  56. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
  57. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +2 -1
  58. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  59. package/dist/modules/currencies/backend/currencies/[id]/page.js +1 -0
  60. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  61. package/dist/modules/currencies/backend/currencies/create/page.js +1 -0
  62. package/dist/modules/currencies/backend/currencies/create/page.js.map +2 -2
  63. package/dist/modules/currencies/backend/currencies/page.js +1 -0
  64. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  65. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +1 -0
  66. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
  67. package/dist/modules/currencies/backend/exchange-rates/create/page.js +1 -0
  68. package/dist/modules/currencies/backend/exchange-rates/create/page.js.map +2 -2
  69. package/dist/modules/currencies/backend/exchange-rates/page.js +1 -0
  70. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  71. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +1 -0
  72. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  73. package/dist/modules/customer_accounts/backend/customer_accounts/roles/create/page.js +1 -0
  74. package/dist/modules/customer_accounts/backend/customer_accounts/roles/create/page.js.map +2 -2
  75. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +1 -0
  76. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  77. package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js +1 -0
  78. package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js.map +2 -2
  79. package/dist/modules/customers/backend/customers/companies/create/page.js +1 -0
  80. package/dist/modules/customers/backend/customers/companies/create/page.js.map +2 -2
  81. package/dist/modules/customers/backend/customers/companies/page.js +1 -0
  82. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  83. package/dist/modules/customers/backend/customers/deals/page.js +1 -0
  84. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  85. package/dist/modules/customers/backend/customers/people/create/page.js +1 -0
  86. package/dist/modules/customers/backend/customers/people/create/page.js.map +2 -2
  87. package/dist/modules/customers/backend/customers/people/page.js +1 -0
  88. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  89. package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
  90. package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
  91. package/dist/modules/customers/components/detail/DealForm.js +1 -0
  92. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  93. package/dist/modules/data_sync/backend/data-sync/page.js +1 -0
  94. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  95. package/dist/modules/devices/backend/devices/[id]/page.js +1 -0
  96. package/dist/modules/devices/backend/devices/[id]/page.js.map +2 -2
  97. package/dist/modules/devices/backend/devices/create/page.js +1 -0
  98. package/dist/modules/devices/backend/devices/create/page.js.map +2 -2
  99. package/dist/modules/devices/backend/devices/page.js +1 -0
  100. package/dist/modules/devices/backend/devices/page.js.map +2 -2
  101. package/dist/modules/dictionaries/components/DictionaryTable.js +1 -0
  102. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  103. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +1 -0
  104. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
  105. package/dist/modules/directory/backend/directory/organizations/create/page.js +1 -0
  106. package/dist/modules/directory/backend/directory/organizations/create/page.js.map +2 -2
  107. package/dist/modules/directory/backend/directory/organizations/page.js +1 -0
  108. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  109. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +1 -0
  110. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
  111. package/dist/modules/directory/backend/directory/tenants/create/page.js +1 -0
  112. package/dist/modules/directory/backend/directory/tenants/create/page.js.map +2 -2
  113. package/dist/modules/directory/backend/directory/tenants/page.js +1 -0
  114. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  115. package/dist/modules/entities/backend/entities/user/[entityId]/page.js +1 -0
  116. package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
  117. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +1 -0
  118. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  119. package/dist/modules/entities/backend/entities/user/[entityId]/records/create/page.js +1 -0
  120. package/dist/modules/entities/backend/entities/user/[entityId]/records/create/page.js.map +2 -2
  121. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +1 -0
  122. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  123. package/dist/modules/entities/backend/entities/user/create/page.js +1 -0
  124. package/dist/modules/entities/backend/entities/user/create/page.js.map +2 -2
  125. package/dist/modules/entities/components/SystemEntitiesTable.js +1 -0
  126. package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
  127. package/dist/modules/entities/components/UserEntitiesTable.js +1 -0
  128. package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
  129. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js +1 -0
  130. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js.map +2 -2
  131. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js +1 -0
  132. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js.map +2 -2
  133. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +1 -0
  134. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +2 -2
  135. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js +1 -0
  136. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js.map +2 -2
  137. package/dist/modules/eudr/backend/eudr/plots/create/page.js +1 -0
  138. package/dist/modules/eudr/backend/eudr/plots/create/page.js.map +2 -2
  139. package/dist/modules/eudr/backend/eudr/plots/page.js +1 -0
  140. package/dist/modules/eudr/backend/eudr/plots/page.js.map +2 -2
  141. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js +1 -0
  142. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js.map +2 -2
  143. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js +1 -0
  144. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js.map +2 -2
  145. package/dist/modules/eudr/backend/eudr/product-mappings/page.js +1 -0
  146. package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +2 -2
  147. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js +1 -0
  148. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js.map +2 -2
  149. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js +1 -0
  150. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js.map +2 -2
  151. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +1 -0
  152. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +2 -2
  153. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js +2 -0
  154. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js.map +2 -2
  155. package/dist/modules/eudr/backend/eudr/statements/create/page.js +1 -0
  156. package/dist/modules/eudr/backend/eudr/statements/create/page.js.map +2 -2
  157. package/dist/modules/eudr/backend/eudr/statements/page.js +1 -0
  158. package/dist/modules/eudr/backend/eudr/statements/page.js.map +2 -2
  159. package/dist/modules/eudr/components/MappingSuggestionsDialog.js +1 -0
  160. package/dist/modules/eudr/components/MappingSuggestionsDialog.js.map +2 -2
  161. package/dist/modules/eudr/components/MitigationActionsSection.js +1 -0
  162. package/dist/modules/eudr/components/MitigationActionsSection.js.map +2 -2
  163. package/dist/modules/eudr/components/StatementRiskSection.js +1 -0
  164. package/dist/modules/eudr/components/StatementRiskSection.js.map +2 -2
  165. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js +1 -0
  166. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js.map +2 -2
  167. package/dist/modules/feature_toggles/backend/feature-toggles/global/create/page.js +1 -0
  168. package/dist/modules/feature_toggles/backend/feature-toggles/global/create/page.js.map +2 -2
  169. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +1 -0
  170. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  171. package/dist/modules/feature_toggles/components/OverridesTable.js +1 -0
  172. package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
  173. package/dist/modules/inbox_ops/backend/inbox-ops/page.js +1 -0
  174. package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
  175. package/dist/modules/integrations/backend/integrations/[id]/page.js +1 -0
  176. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  177. package/dist/modules/messages/components/MessagesInboxPageClient.js +1 -0
  178. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  179. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js +1 -1
  180. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js.map +2 -2
  181. package/dist/modules/payment_gateways/backend/payment-gateways/page.js +1 -0
  182. package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
  183. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +1 -0
  184. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  185. package/dist/modules/planner/components/AvailabilityRuleSetForm.js +1 -0
  186. package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +2 -2
  187. package/dist/modules/push_notifications/backend/push_notifications/page.js +1 -0
  188. package/dist/modules/push_notifications/backend/push_notifications/page.js.map +2 -2
  189. package/dist/modules/push_notifications/backend/push_notifications/send/page.js +1 -0
  190. package/dist/modules/push_notifications/backend/push_notifications/send/page.js.map +2 -2
  191. package/dist/modules/query_index/components/QueryIndexesTable.js +1 -0
  192. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  193. package/dist/modules/resources/backend/resources/resource-types/page.js +1 -0
  194. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  195. package/dist/modules/resources/backend/resources/resources/create/page.js +1 -0
  196. package/dist/modules/resources/backend/resources/resources/create/page.js.map +2 -2
  197. package/dist/modules/resources/backend/resources/resources/page.js +1 -0
  198. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  199. package/dist/modules/resources/components/ResourceCrudForm.js +2 -0
  200. package/dist/modules/resources/components/ResourceCrudForm.js.map +2 -2
  201. package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -0
  202. package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
  203. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +1 -0
  204. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  205. package/dist/modules/sales/backend/sales/channels/create/page.js +1 -0
  206. package/dist/modules/sales/backend/sales/channels/create/page.js.map +2 -2
  207. package/dist/modules/sales/backend/sales/channels/offers/page.js +2 -2
  208. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  209. package/dist/modules/sales/backend/sales/channels/page.js +2 -1
  210. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  211. package/dist/modules/sales/components/channels/ChannelOfferForm.js +1 -0
  212. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  213. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +1 -1
  214. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  215. package/dist/modules/sales/components/documents/SalesDocumentForm.js +1 -0
  216. package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
  217. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -1
  218. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  219. package/dist/modules/shipping_carriers/backend/shipping-carriers/create/page.js +2 -1
  220. package/dist/modules/shipping_carriers/backend/shipping-carriers/create/page.js.map +2 -2
  221. package/dist/modules/staff/backend/staff/leave-requests/page.js +1 -0
  222. package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
  223. package/dist/modules/staff/backend/staff/my-leave-requests/page.js +1 -0
  224. package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
  225. package/dist/modules/staff/backend/staff/profile/create/page.js +1 -0
  226. package/dist/modules/staff/backend/staff/profile/create/page.js.map +2 -2
  227. package/dist/modules/staff/backend/staff/team-members/create/page.js +1 -0
  228. package/dist/modules/staff/backend/staff/team-members/create/page.js.map +2 -2
  229. package/dist/modules/staff/backend/staff/team-members/page.js +1 -0
  230. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  231. package/dist/modules/staff/backend/staff/team-roles/page.js +1 -0
  232. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  233. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +1 -0
  234. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  235. package/dist/modules/staff/backend/staff/teams/page.js +1 -0
  236. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  237. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +1 -0
  238. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +2 -2
  239. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +1 -0
  240. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +2 -2
  241. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +1 -0
  242. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  243. package/dist/modules/staff/components/LeaveRequestForm.js +1 -0
  244. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  245. package/dist/modules/staff/components/TeamForm.js +1 -0
  246. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  247. package/dist/modules/staff/components/TeamMemberForm.js +2 -0
  248. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  249. package/dist/modules/staff/components/TeamRoleForm.js +1 -0
  250. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  251. package/dist/modules/warranty_claims/backend/warranty_claims/[id]/edit/page.js +1 -0
  252. package/dist/modules/warranty_claims/backend/warranty_claims/[id]/edit/page.js.map +2 -2
  253. package/dist/modules/warranty_claims/backend/warranty_claims/create/page.js +1 -0
  254. package/dist/modules/warranty_claims/backend/warranty_claims/create/page.js.map +2 -2
  255. package/dist/modules/warranty_claims/backend/warranty_claims/registrations/[id]/edit/page.js +1 -0
  256. package/dist/modules/warranty_claims/backend/warranty_claims/registrations/[id]/edit/page.js.map +2 -2
  257. package/dist/modules/warranty_claims/backend/warranty_claims/registrations/create/page.js +1 -0
  258. package/dist/modules/warranty_claims/backend/warranty_claims/registrations/create/page.js.map +2 -2
  259. package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/[id]/edit/page.js +1 -0
  260. package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/[id]/edit/page.js.map +2 -2
  261. package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/create/page.js +1 -0
  262. package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/create/page.js.map +2 -2
  263. package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/[id]/edit/page.js +1 -0
  264. package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/[id]/edit/page.js.map +2 -2
  265. package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/create/page.js +1 -0
  266. package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/create/page.js.map +2 -2
  267. package/dist/modules/wms/components/backend/WmsConfigurationPage.js +4 -0
  268. package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +2 -2
  269. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +1 -0
  270. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
  271. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +1 -0
  272. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +2 -2
  273. package/dist/modules/wms/components/backend/WmsLotDetailPage.js +1 -0
  274. package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +2 -2
  275. package/dist/modules/wms/components/backend/WmsLotsListPage.js +1 -0
  276. package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
  277. package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js +1 -0
  278. package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js.map +2 -2
  279. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +1 -0
  280. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +2 -2
  281. package/dist/modules/workflows/backend/definitions/[id]/page.js +1 -0
  282. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  283. package/dist/modules/workflows/backend/definitions/create/page.js +1 -0
  284. package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
  285. package/dist/modules/workflows/backend/definitions/page.js +1 -0
  286. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  287. package/dist/modules/workflows/backend/events/page.js +1 -0
  288. package/dist/modules/workflows/backend/events/page.js.map +2 -2
  289. package/dist/modules/workflows/backend/instances/page.js +1 -0
  290. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  291. package/dist/modules/workflows/backend/tasks/page.js +1 -0
  292. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  293. package/package.json +7 -7
  294. package/src/modules/api_keys/backend/api-keys/create/page.tsx +1 -0
  295. package/src/modules/api_keys/backend/api-keys/page.tsx +2 -1
  296. package/src/modules/attachments/components/AttachmentLibrary.tsx +1 -0
  297. package/src/modules/audit_logs/backend/audit-logs/page.tsx +2 -1
  298. package/src/modules/audit_logs/components/AccessLogsTable.tsx +1 -0
  299. package/src/modules/audit_logs/components/AuditLogsActions.tsx +1 -0
  300. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +1 -0
  301. package/src/modules/auth/backend/roles/create/page.tsx +1 -0
  302. package/src/modules/auth/backend/roles/page.tsx +2 -1
  303. package/src/modules/auth/backend/users/[id]/edit/page.tsx +1 -0
  304. package/src/modules/auth/backend/users/create/page.tsx +1 -0
  305. package/src/modules/auth/backend/users/page.tsx +2 -1
  306. package/src/modules/business_rules/backend/logs/page.tsx +2 -1
  307. package/src/modules/business_rules/backend/rules/[id]/page.tsx +1 -0
  308. package/src/modules/business_rules/backend/rules/create/page.tsx +1 -0
  309. package/src/modules/business_rules/backend/rules/page.tsx +2 -1
  310. package/src/modules/business_rules/backend/sets/[id]/page.tsx +1 -0
  311. package/src/modules/business_rules/backend/sets/create/page.tsx +1 -0
  312. package/src/modules/business_rules/backend/sets/page.tsx +2 -1
  313. package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +1 -0
  314. package/src/modules/catalog/backend/catalog/categories/create/page.tsx +1 -0
  315. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +1 -0
  316. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +1 -0
  317. package/src/modules/catalog/backend/catalog/products/[productId]/variants/create/page.tsx +1 -0
  318. package/src/modules/catalog/backend/catalog/products/create/page.tsx +1 -0
  319. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -1
  320. package/src/modules/catalog/components/products/ProductsDataTable.tsx +2 -1
  321. package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +1 -0
  322. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +3 -2
  323. package/src/modules/currencies/backend/currencies/[id]/page.tsx +1 -0
  324. package/src/modules/currencies/backend/currencies/create/page.tsx +1 -0
  325. package/src/modules/currencies/backend/currencies/page.tsx +2 -1
  326. package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +1 -0
  327. package/src/modules/currencies/backend/exchange-rates/create/page.tsx +1 -0
  328. package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -1
  329. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +1 -0
  330. package/src/modules/customer_accounts/backend/customer_accounts/roles/create/page.tsx +1 -0
  331. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +2 -1
  332. package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx +1 -0
  333. package/src/modules/customers/backend/customers/companies/create/page.tsx +1 -0
  334. package/src/modules/customers/backend/customers/companies/page.tsx +1 -0
  335. package/src/modules/customers/backend/customers/deals/page.tsx +1 -0
  336. package/src/modules/customers/backend/customers/people/create/page.tsx +1 -0
  337. package/src/modules/customers/backend/customers/people/page.tsx +1 -0
  338. package/src/modules/customers/components/CustomerTodosTable.tsx +1 -0
  339. package/src/modules/customers/components/detail/DealForm.tsx +1 -0
  340. package/src/modules/data_sync/backend/data-sync/page.tsx +1 -0
  341. package/src/modules/devices/backend/devices/[id]/page.tsx +1 -0
  342. package/src/modules/devices/backend/devices/create/page.tsx +1 -0
  343. package/src/modules/devices/backend/devices/page.tsx +2 -1
  344. package/src/modules/dictionaries/components/DictionaryTable.tsx +1 -0
  345. package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +1 -0
  346. package/src/modules/directory/backend/directory/organizations/create/page.tsx +1 -0
  347. package/src/modules/directory/backend/directory/organizations/page.tsx +2 -1
  348. package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +1 -0
  349. package/src/modules/directory/backend/directory/tenants/create/page.tsx +1 -0
  350. package/src/modules/directory/backend/directory/tenants/page.tsx +2 -1
  351. package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +1 -0
  352. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +1 -0
  353. package/src/modules/entities/backend/entities/user/[entityId]/records/create/page.tsx +1 -0
  354. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -1
  355. package/src/modules/entities/backend/entities/user/create/page.tsx +1 -0
  356. package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -0
  357. package/src/modules/entities/components/UserEntitiesTable.tsx +1 -0
  358. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.tsx +1 -0
  359. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.tsx +1 -0
  360. package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +2 -1
  361. package/src/modules/eudr/backend/eudr/plots/[id]/page.tsx +1 -0
  362. package/src/modules/eudr/backend/eudr/plots/create/page.tsx +1 -0
  363. package/src/modules/eudr/backend/eudr/plots/page.tsx +2 -1
  364. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.tsx +1 -0
  365. package/src/modules/eudr/backend/eudr/product-mappings/create/page.tsx +1 -0
  366. package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +2 -1
  367. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.tsx +1 -0
  368. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.tsx +1 -0
  369. package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +2 -1
  370. package/src/modules/eudr/backend/eudr/statements/[id]/page.tsx +2 -0
  371. package/src/modules/eudr/backend/eudr/statements/create/page.tsx +1 -0
  372. package/src/modules/eudr/backend/eudr/statements/page.tsx +2 -1
  373. package/src/modules/eudr/components/MappingSuggestionsDialog.tsx +1 -0
  374. package/src/modules/eudr/components/MitigationActionsSection.tsx +1 -0
  375. package/src/modules/eudr/components/StatementRiskSection.tsx +1 -0
  376. package/src/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.tsx +1 -0
  377. package/src/modules/feature_toggles/backend/feature-toggles/global/create/page.tsx +1 -0
  378. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +2 -1
  379. package/src/modules/feature_toggles/components/OverridesTable.tsx +2 -1
  380. package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +2 -1
  381. package/src/modules/integrations/backend/integrations/[id]/page.tsx +2 -1
  382. package/src/modules/messages/components/MessagesInboxPageClient.tsx +1 -0
  383. package/src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx +2 -2
  384. package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +1 -0
  385. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -1
  386. package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +1 -0
  387. package/src/modules/push_notifications/backend/push_notifications/page.tsx +2 -1
  388. package/src/modules/push_notifications/backend/push_notifications/send/page.tsx +1 -0
  389. package/src/modules/query_index/components/QueryIndexesTable.tsx +2 -1
  390. package/src/modules/resources/backend/resources/resource-types/page.tsx +1 -0
  391. package/src/modules/resources/backend/resources/resources/create/page.tsx +1 -0
  392. package/src/modules/resources/backend/resources/resources/page.tsx +1 -0
  393. package/src/modules/resources/components/ResourceCrudForm.tsx +3 -0
  394. package/src/modules/resources/components/ResourceTypeCrudForm.tsx +1 -0
  395. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +1 -0
  396. package/src/modules/sales/backend/sales/channels/create/page.tsx +1 -0
  397. package/src/modules/sales/backend/sales/channels/offers/page.tsx +3 -3
  398. package/src/modules/sales/backend/sales/channels/page.tsx +3 -2
  399. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +1 -0
  400. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +2 -2
  401. package/src/modules/sales/components/documents/SalesDocumentForm.tsx +1 -0
  402. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +3 -2
  403. package/src/modules/shipping_carriers/backend/shipping-carriers/create/page.tsx +2 -1
  404. package/src/modules/staff/backend/staff/leave-requests/page.tsx +2 -1
  405. package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +2 -1
  406. package/src/modules/staff/backend/staff/profile/create/page.tsx +1 -0
  407. package/src/modules/staff/backend/staff/team-members/create/page.tsx +1 -0
  408. package/src/modules/staff/backend/staff/team-members/page.tsx +2 -2
  409. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  410. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +1 -0
  411. package/src/modules/staff/backend/staff/teams/page.tsx +2 -1
  412. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +1 -0
  413. package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +1 -0
  414. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +2 -1
  415. package/src/modules/staff/components/LeaveRequestForm.tsx +1 -0
  416. package/src/modules/staff/components/TeamForm.tsx +1 -0
  417. package/src/modules/staff/components/TeamMemberForm.tsx +3 -0
  418. package/src/modules/staff/components/TeamRoleForm.tsx +1 -0
  419. package/src/modules/warranty_claims/backend/warranty_claims/[id]/edit/page.tsx +1 -0
  420. package/src/modules/warranty_claims/backend/warranty_claims/create/page.tsx +1 -0
  421. package/src/modules/warranty_claims/backend/warranty_claims/registrations/[id]/edit/page.tsx +1 -0
  422. package/src/modules/warranty_claims/backend/warranty_claims/registrations/create/page.tsx +1 -0
  423. package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/[id]/edit/page.tsx +1 -0
  424. package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/create/page.tsx +1 -0
  425. package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/[id]/edit/page.tsx +1 -0
  426. package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/create/page.tsx +1 -0
  427. package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +4 -0
  428. package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +1 -0
  429. package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +1 -0
  430. package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +1 -0
  431. package/src/modules/wms/components/backend/WmsLotsListPage.tsx +1 -0
  432. package/src/modules/wms/components/backend/WmsOperationalDashboardPage.tsx +1 -0
  433. package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +1 -0
  434. package/src/modules/workflows/backend/definitions/[id]/page.tsx +1 -0
  435. package/src/modules/workflows/backend/definitions/create/page.tsx +1 -0
  436. package/src/modules/workflows/backend/definitions/page.tsx +2 -1
  437. package/src/modules/workflows/backend/events/page.tsx +2 -1
  438. package/src/modules/workflows/backend/instances/page.tsx +2 -1
  439. package/src/modules/workflows/backend/tasks/page.tsx +2 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/eudr/backend/eudr/statements/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { ListEmptyState } from '@open-mercato/ui/backend/filters/ListEmptyState'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport { Plus } from 'lucide-react'\nimport type { SortingState } from '@tanstack/react-table'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { EudrActivityType, EudrCommodity, EudrRiskConclusion, EudrRiskTier, EudrStatementStatus } from '../../../data/validators'\nimport { commodityOptions, statementStatusOptions, statusBadgeVariant, translateEudrErrorMessage } from '../../../components/formConfig'\nimport { canDeleteStatement } from '../../../lib/statement-lifecycle'\nimport {\n riskConclusionBadgeVariant,\n riskTierBadgeVariant,\n} from '../../../components/StatementRiskSection'\n\ntype StatementRow = {\n id: string\n title: string\n commodity: EudrCommodity\n referenceNumber: string | null\n verificationNumber: string | null\n status: EudrStatementStatus\n activityType: EudrActivityType | null\n quantityKg: number | string | null\n orderId: string | null\n notes: string | null\n latestRisk: {\n conclusion: EudrRiskConclusion\n overallTier: EudrRiskTier\n reviewDueAt: string | null\n } | null\n createdAt: string\n updatedAt: string\n}\n\ntype StatementsResponse = {\n items: StatementRow[]\n total: number\n totalPages: number\n totalIsCapped?: boolean\n}\n\nfunction formatDateTime(value: string | null | undefined, emptyLabel: string, locale: string): string {\n if (!value) return emptyLabel\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return emptyLabel\n return date.toLocaleString(locale || undefined)\n}\n\nfunction formatQuantityKg(value: number | string | null, emptyLabel: string): string {\n if (value === null || value === undefined) return emptyLabel\n if (typeof value === 'string' && !value.trim()) return emptyLabel\n return String(value)\n}\n\nexport default function EudrStatementsPage() {\n const translate = useT()\n const locale = useLocale()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<StatementRow[]>([])\n const [page, setPage] = React.useState(1)\n const [pageSize, setPageSize] = React.useState(20)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [sorting, setSorting] = React.useState<SortingState>([])\n const [filters, setFilters] = React.useState<FilterValues>({})\n const [loading, setLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const mutationContextId = 'eudr-statements-list:delete'\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: translate('ui.forms.flash.saveBlocked'),\n })\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', String(pageSize))\n if (search.trim()) params.set('search', search.trim())\n if (typeof filters.commodity === 'string' && filters.commodity.trim()) {\n params.set('commodity', filters.commodity.trim())\n }\n if (typeof filters.status === 'string' && filters.status.trim()) {\n params.set('status', filters.status.trim())\n }\n const firstSort = sorting[0]\n if (firstSort) {\n params.set('sortField', firstSort.id)\n params.set('sortDir', firstSort.desc ? 'desc' : 'asc')\n }\n return params.toString()\n }, [filters.commodity, filters.status, page, pageSize, search, sorting])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadRows() {\n setLoading(true)\n try {\n const fallback: StatementsResponse = { items: [], total: 0, totalPages: 1 }\n const call = await apiCall<StatementsResponse>(\n `/api/eudr/statements?${queryParams}`,\n undefined,\n { fallback },\n )\n if (!call.ok) {\n flash(translate('eudr.statements.list.loadError'), 'error')\n return\n }\n const payload = call.result ?? fallback\n if (cancelled) return\n setRows(Array.isArray(payload.items) ? payload.items : [])\n setTotal(typeof payload.total === 'number' ? payload.total : 0)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)\n setTotalIsCapped(payload?.totalIsCapped === true)\n } catch {\n if (!cancelled) flash(translate('eudr.statements.list.loadError'), 'error')\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n loadRows()\n return () => {\n cancelled = true\n }\n }, [queryParams, reloadToken, scopeVersion, translate])\n\n const refreshRows = React.useCallback(() => {\n setReloadToken((currentToken) => currentToken + 1)\n }, [])\n\n const handleDelete = React.useCallback(async (row: StatementRow) => {\n const confirmed = await confirm({\n title: translate('eudr.statements.list.confirmDelete', { title: row.title }),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n try {\n await runMutation({\n operation: async () => {\n const call = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(row.updatedAt),\n () => apiCall(\n `/api/eudr/statements?id=${encodeURIComponent(row.id)}`,\n { method: 'DELETE' },\n ),\n )\n if (!call.ok) {\n throw Object.assign(new Error('[internal] eudr statement delete failed'), {\n status: call.status,\n ...((call.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return call\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'eudr.due_diligence_statement',\n resourceId: row.id,\n retryLastMutation,\n },\n mutationPayload: { id: row.id },\n })\n flash(translate('eudr.statements.list.deleteSuccess'), 'success')\n refreshRows()\n } catch (error) {\n if (surfaceRecordConflict(error, translate, { onRefresh: refreshRows })) return\n flash(\n translateEudrErrorMessage(error, translate, translate('eudr.statements.list.deleteError')),\n 'error',\n )\n refreshRows()\n }\n }, [confirm, mutationContextId, refreshRows, retryLastMutation, runMutation, translate])\n\n const columns = React.useMemo<ColumnDef<StatementRow>[]>(() => [\n {\n accessorKey: 'title',\n header: translate('eudr.statements.list.columns.title'),\n cell: ({ row }) => (\n <Link href={`/backend/eudr/statements/${row.original.id}`} className=\"font-medium hover:underline\">\n {row.original.title}\n </Link>\n ),\n meta: { maxWidth: '260px', truncate: true },\n },\n {\n accessorKey: 'commodity',\n header: translate('eudr.statements.list.columns.commodity'),\n cell: ({ row }) => translate(`eudr.commodity.${row.original.commodity}`),\n },\n {\n accessorKey: 'status',\n header: translate('eudr.statements.list.columns.status'),\n cell: ({ row }) => (\n <StatusBadge variant={statusBadgeVariant(row.original.status)} dot>\n {translate(`eudr.statementStatus.${row.original.status}`)}\n </StatusBadge>\n ),\n },\n {\n accessorKey: 'activityType',\n header: translate('eudr.statements.list.columns.activityType'),\n cell: ({ row }) => row.original.activityType\n ? translate(`eudr.activityType.${row.original.activityType}`)\n : translate('eudr.common.empty'),\n },\n {\n id: 'latestRiskConclusion',\n header: translate('eudr.statements.list.columns.latestRiskConclusion'),\n cell: ({ row }) => row.original.latestRisk ? (\n <StatusBadge variant={riskConclusionBadgeVariant(row.original.latestRisk.conclusion)}>\n {translate(`eudr.conclusion.${row.original.latestRisk.conclusion}`)}\n </StatusBadge>\n ) : translate('eudr.common.empty'),\n },\n {\n id: 'latestRiskTier',\n header: translate('eudr.statements.list.columns.latestRiskTier'),\n cell: ({ row }) => row.original.latestRisk ? (\n <StatusBadge variant={riskTierBadgeVariant(row.original.latestRisk.overallTier)}>\n {translate(`eudr.riskTier.${row.original.latestRisk.overallTier}`)}\n </StatusBadge>\n ) : translate('eudr.common.empty'),\n },\n {\n accessorKey: 'referenceNumber',\n header: translate('eudr.statements.list.columns.referenceNumber'),\n cell: ({ row }) => row.original.referenceNumber || translate('eudr.common.empty'),\n },\n {\n accessorKey: 'quantityKg',\n header: translate('eudr.statements.list.columns.quantityKg'),\n cell: ({ row }) => formatQuantityKg(row.original.quantityKg, translate('eudr.common.empty')),\n },\n {\n accessorKey: 'updatedAt',\n header: translate('eudr.statements.list.columns.updatedAt'),\n cell: ({ row }) => formatDateTime(row.original.updatedAt, translate('eudr.common.empty'), locale),\n },\n ], [locale, translate])\n\n const filterDefs = React.useMemo<FilterDef[]>(() => [\n {\n id: 'commodity',\n label: translate('eudr.statements.list.filters.commodity'),\n type: 'select',\n options: [\n { value: '', label: translate('eudr.statements.list.filters.allCommodities') },\n ...commodityOptions(translate),\n ],\n },\n {\n id: 'status',\n label: translate('eudr.statements.list.filters.status'),\n type: 'select',\n options: [\n { value: '', label: translate('eudr.statements.list.filters.allStatuses') },\n ...statementStatusOptions(translate),\n ],\n },\n ], [locale, translate])\n\n return (\n <Page>\n <PageBody>\n <DataTable<StatementRow>\n title={translate('eudr.statements.list.title')}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(nextSearch) => {\n setSearch(nextSearch)\n setPage(1)\n }}\n searchPlaceholder={translate('eudr.statements.list.searchPlaceholder')}\n filters={filterDefs}\n filterValues={filters}\n onFiltersApply={(nextFilters) => {\n setFilters(nextFilters)\n setPage(1)\n }}\n onFiltersClear={() => {\n setFilters({})\n setPage(1)\n }}\n actions={(\n <Button asChild>\n <Link href=\"/backend/eudr/statements/create\">\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {translate('eudr.statements.list.actions.create')}\n </Link>\n </Button>\n )}\n rowActions={(row) => {\n const items: RowActionItem[] = [\n {\n id: 'edit',\n label: translate('eudr.statements.list.actions.edit'),\n href: `/backend/eudr/statements/${row.id}`,\n },\n {\n id: 'duplicate',\n label: translate('eudr.statements.duplicateAction'),\n href: `/backend/eudr/statements/create?duplicateFrom=${encodeURIComponent(row.id)}`,\n },\n ]\n if (canDeleteStatement(row.status)) {\n items.push({\n id: 'delete',\n label: translate('eudr.statements.list.actions.delete'),\n destructive: true,\n onSelect: () => {\n void handleDelete(row)\n },\n })\n }\n return <RowActions items={items} />\n }}\n onRowClick={(row) => router.push(`/backend/eudr/statements/${row.id}`)}\n rowClickActionIds={['edit']}\n emptyState={(\n <ListEmptyState\n entityName={translate('eudr.statements.list.entityName')}\n createHref=\"/backend/eudr/statements/create\"\n createLabel={translate('eudr.statements.list.actions.create')}\n />\n )}\n sortable\n manualSorting\n sorting={sorting}\n onSortingChange={(nextSorting) => {\n setSorting(nextSorting)\n setPage(1)\n }}\n pagination={{\n page,\n pageSize,\n total,\n totalPages,\n totalIsCapped,\n onPageChange: setPage,\n pageSizeOptions: [20, 50, 100],\n onPageSizeChange: (nextPageSize) => {\n setPageSize(nextPageSize)\n setPage(1)\n },\n }}\n isLoading={loading}\n perspective={{ tableId: 'eudr.statements.list' }}\n stickyActionsColumn\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { ListEmptyState } from '@open-mercato/ui/backend/filters/ListEmptyState'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport { Plus } from 'lucide-react'\nimport type { SortingState } from '@tanstack/react-table'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { EudrActivityType, EudrCommodity, EudrRiskConclusion, EudrRiskTier, EudrStatementStatus } from '../../../data/validators'\nimport { commodityOptions, statementStatusOptions, statusBadgeVariant, translateEudrErrorMessage } from '../../../components/formConfig'\nimport { canDeleteStatement } from '../../../lib/statement-lifecycle'\nimport {\n riskConclusionBadgeVariant,\n riskTierBadgeVariant,\n} from '../../../components/StatementRiskSection'\n\ntype StatementRow = {\n id: string\n title: string\n commodity: EudrCommodity\n referenceNumber: string | null\n verificationNumber: string | null\n status: EudrStatementStatus\n activityType: EudrActivityType | null\n quantityKg: number | string | null\n orderId: string | null\n notes: string | null\n latestRisk: {\n conclusion: EudrRiskConclusion\n overallTier: EudrRiskTier\n reviewDueAt: string | null\n } | null\n createdAt: string\n updatedAt: string\n}\n\ntype StatementsResponse = {\n items: StatementRow[]\n total: number\n totalPages: number\n totalIsCapped?: boolean\n}\n\nfunction formatDateTime(value: string | null | undefined, emptyLabel: string, locale: string): string {\n if (!value) return emptyLabel\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return emptyLabel\n return date.toLocaleString(locale || undefined)\n}\n\nfunction formatQuantityKg(value: number | string | null, emptyLabel: string): string {\n if (value === null || value === undefined) return emptyLabel\n if (typeof value === 'string' && !value.trim()) return emptyLabel\n return String(value)\n}\n\nexport default function EudrStatementsPage() {\n const translate = useT()\n const locale = useLocale()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<StatementRow[]>([])\n const [page, setPage] = React.useState(1)\n const [pageSize, setPageSize] = React.useState(20)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [sorting, setSorting] = React.useState<SortingState>([])\n const [filters, setFilters] = React.useState<FilterValues>({})\n const [loading, setLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const mutationContextId = 'eudr-statements-list:delete'\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: translate('ui.forms.flash.saveBlocked'),\n })\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', String(pageSize))\n if (search.trim()) params.set('search', search.trim())\n if (typeof filters.commodity === 'string' && filters.commodity.trim()) {\n params.set('commodity', filters.commodity.trim())\n }\n if (typeof filters.status === 'string' && filters.status.trim()) {\n params.set('status', filters.status.trim())\n }\n const firstSort = sorting[0]\n if (firstSort) {\n params.set('sortField', firstSort.id)\n params.set('sortDir', firstSort.desc ? 'desc' : 'asc')\n }\n return params.toString()\n }, [filters.commodity, filters.status, page, pageSize, search, sorting])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadRows() {\n setLoading(true)\n try {\n const fallback: StatementsResponse = { items: [], total: 0, totalPages: 1 }\n const call = await apiCall<StatementsResponse>(\n `/api/eudr/statements?${queryParams}`,\n undefined,\n { fallback },\n )\n if (!call.ok) {\n flash(translate('eudr.statements.list.loadError'), 'error')\n return\n }\n const payload = call.result ?? fallback\n if (cancelled) return\n setRows(Array.isArray(payload.items) ? payload.items : [])\n setTotal(typeof payload.total === 'number' ? payload.total : 0)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)\n setTotalIsCapped(payload?.totalIsCapped === true)\n } catch {\n if (!cancelled) flash(translate('eudr.statements.list.loadError'), 'error')\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n loadRows()\n return () => {\n cancelled = true\n }\n }, [queryParams, reloadToken, scopeVersion, translate])\n\n const refreshRows = React.useCallback(() => {\n setReloadToken((currentToken) => currentToken + 1)\n }, [])\n\n const handleDelete = React.useCallback(async (row: StatementRow) => {\n const confirmed = await confirm({\n title: translate('eudr.statements.list.confirmDelete', { title: row.title }),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n try {\n await runMutation({\n operation: async () => {\n const call = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(row.updatedAt),\n () => apiCall(\n `/api/eudr/statements?id=${encodeURIComponent(row.id)}`,\n { method: 'DELETE' },\n ),\n )\n if (!call.ok) {\n throw Object.assign(new Error('[internal] eudr statement delete failed'), {\n status: call.status,\n ...((call.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return call\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'eudr.due_diligence_statement',\n resourceId: row.id,\n retryLastMutation,\n },\n mutationPayload: { id: row.id },\n })\n flash(translate('eudr.statements.list.deleteSuccess'), 'success')\n refreshRows()\n } catch (error) {\n if (surfaceRecordConflict(error, translate, { onRefresh: refreshRows })) return\n flash(\n translateEudrErrorMessage(error, translate, translate('eudr.statements.list.deleteError')),\n 'error',\n )\n refreshRows()\n }\n }, [confirm, mutationContextId, refreshRows, retryLastMutation, runMutation, translate])\n\n const columns = React.useMemo<ColumnDef<StatementRow>[]>(() => [\n {\n accessorKey: 'title',\n header: translate('eudr.statements.list.columns.title'),\n cell: ({ row }) => (\n <Link href={`/backend/eudr/statements/${row.original.id}`} className=\"font-medium hover:underline\">\n {row.original.title}\n </Link>\n ),\n meta: { maxWidth: '260px', truncate: true },\n },\n {\n accessorKey: 'commodity',\n header: translate('eudr.statements.list.columns.commodity'),\n cell: ({ row }) => translate(`eudr.commodity.${row.original.commodity}`),\n },\n {\n accessorKey: 'status',\n header: translate('eudr.statements.list.columns.status'),\n cell: ({ row }) => (\n <StatusBadge variant={statusBadgeVariant(row.original.status)} dot>\n {translate(`eudr.statementStatus.${row.original.status}`)}\n </StatusBadge>\n ),\n },\n {\n accessorKey: 'activityType',\n header: translate('eudr.statements.list.columns.activityType'),\n cell: ({ row }) => row.original.activityType\n ? translate(`eudr.activityType.${row.original.activityType}`)\n : translate('eudr.common.empty'),\n },\n {\n id: 'latestRiskConclusion',\n header: translate('eudr.statements.list.columns.latestRiskConclusion'),\n cell: ({ row }) => row.original.latestRisk ? (\n <StatusBadge variant={riskConclusionBadgeVariant(row.original.latestRisk.conclusion)}>\n {translate(`eudr.conclusion.${row.original.latestRisk.conclusion}`)}\n </StatusBadge>\n ) : translate('eudr.common.empty'),\n },\n {\n id: 'latestRiskTier',\n header: translate('eudr.statements.list.columns.latestRiskTier'),\n cell: ({ row }) => row.original.latestRisk ? (\n <StatusBadge variant={riskTierBadgeVariant(row.original.latestRisk.overallTier)}>\n {translate(`eudr.riskTier.${row.original.latestRisk.overallTier}`)}\n </StatusBadge>\n ) : translate('eudr.common.empty'),\n },\n {\n accessorKey: 'referenceNumber',\n header: translate('eudr.statements.list.columns.referenceNumber'),\n cell: ({ row }) => row.original.referenceNumber || translate('eudr.common.empty'),\n },\n {\n accessorKey: 'quantityKg',\n header: translate('eudr.statements.list.columns.quantityKg'),\n cell: ({ row }) => formatQuantityKg(row.original.quantityKg, translate('eudr.common.empty')),\n },\n {\n accessorKey: 'updatedAt',\n header: translate('eudr.statements.list.columns.updatedAt'),\n cell: ({ row }) => formatDateTime(row.original.updatedAt, translate('eudr.common.empty'), locale),\n },\n ], [locale, translate])\n\n const filterDefs = React.useMemo<FilterDef[]>(() => [\n {\n id: 'commodity',\n label: translate('eudr.statements.list.filters.commodity'),\n type: 'select',\n options: [\n { value: '', label: translate('eudr.statements.list.filters.allCommodities') },\n ...commodityOptions(translate),\n ],\n },\n {\n id: 'status',\n label: translate('eudr.statements.list.filters.status'),\n type: 'select',\n options: [\n { value: '', label: translate('eudr.statements.list.filters.allStatuses') },\n ...statementStatusOptions(translate),\n ],\n },\n ], [locale, translate])\n\n return (\n <Page>\n <PageBody>\n <DataTable<StatementRow>\n title={translate('eudr.statements.list.title')}\n titleHeadingLevel={1}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(nextSearch) => {\n setSearch(nextSearch)\n setPage(1)\n }}\n searchPlaceholder={translate('eudr.statements.list.searchPlaceholder')}\n filters={filterDefs}\n filterValues={filters}\n onFiltersApply={(nextFilters) => {\n setFilters(nextFilters)\n setPage(1)\n }}\n onFiltersClear={() => {\n setFilters({})\n setPage(1)\n }}\n actions={(\n <Button asChild>\n <Link href=\"/backend/eudr/statements/create\">\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {translate('eudr.statements.list.actions.create')}\n </Link>\n </Button>\n )}\n rowActions={(row) => {\n const items: RowActionItem[] = [\n {\n id: 'edit',\n label: translate('eudr.statements.list.actions.edit'),\n href: `/backend/eudr/statements/${row.id}`,\n },\n {\n id: 'duplicate',\n label: translate('eudr.statements.duplicateAction'),\n href: `/backend/eudr/statements/create?duplicateFrom=${encodeURIComponent(row.id)}`,\n },\n ]\n if (canDeleteStatement(row.status)) {\n items.push({\n id: 'delete',\n label: translate('eudr.statements.list.actions.delete'),\n destructive: true,\n onSelect: () => {\n void handleDelete(row)\n },\n })\n }\n return <RowActions items={items} />\n }}\n onRowClick={(row) => router.push(`/backend/eudr/statements/${row.id}`)}\n rowClickActionIds={['edit']}\n emptyState={(\n <ListEmptyState\n entityName={translate('eudr.statements.list.entityName')}\n createHref=\"/backend/eudr/statements/create\"\n createLabel={translate('eudr.statements.list.actions.create')}\n />\n )}\n sortable\n manualSorting\n sorting={sorting}\n onSortingChange={(nextSorting) => {\n setSorting(nextSorting)\n setPage(1)\n }}\n pagination={{\n page,\n pageSize,\n total,\n totalPages,\n totalIsCapped,\n onPageChange: setPage,\n pageSizeOptions: [20, 50, 100],\n onPageSizeChange: (nextPageSize) => {\n setPageSize(nextPageSize)\n setPage(1)\n },\n }}\n isLoading={loading}\n perspective={{ tableId: 'eudr.statements.list' }}\n stickyActionsColumn\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
5
+ "mappings": ";AA6MQ,cA6GM,YA7GN;AA3MR,YAAY,WAAW;AACvB,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAC1B,SAAS,MAAM,gBAAgB;AAC/B,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,kBAAsC;AAE/C,SAAS,SAAS,mCAAmC;AACrD,SAAS,iCAAiC;AAC1C,SAAS,0BAA0B;AACnC,SAAS,aAAa;AACtB,SAAS,wBAAwB;AACjC,SAAS,6BAA6B;AACtC,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAS,YAAY;AAGrB,SAAS,mCAAmC;AAC5C,SAAS,WAAW,YAAY;AAEhC,SAAS,kBAAkB,wBAAwB,oBAAoB,iCAAiC;AACxG,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AA6BP,SAAS,eAAe,OAAkC,YAAoB,QAAwB;AACpG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AACzC,SAAO,KAAK,eAAe,UAAU,MAAS;AAChD;AAEA,SAAS,iBAAiB,OAA+B,YAA4B;AACnF,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,EAAG,QAAO;AACvD,SAAO,OAAO,KAAK;AACrB;AAEe,SAAR,qBAAsC;AAC3C,QAAM,YAAY,KAAK;AACvB,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,UAAU;AACzB,QAAM,eAAe,4BAA4B;AACjD,QAAM,EAAE,SAAS,qBAAqB,IAAI,iBAAiB;AAC3D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAyB,CAAC,CAAC;AACzD,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC;AACxC,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAS,EAAE;AACjD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,CAAC;AAC1C,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAS,KAAK;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,CAAC;AAC7D,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,CAAC;AAC7D,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,IAAI;AACjD,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,CAAC;AACtD,QAAM,oBAAoB;AAC1B,QAAM,EAAE,aAAa,kBAAkB,IAAI,mBAKxC;AAAA,IACD,WAAW;AAAA,IACX,gBAAgB,UAAU,4BAA4B;AAAA,EACxD,CAAC;AAED,QAAM,cAAc,MAAM,QAAQ,MAAM;AACtC,UAAM,SAAS,IAAI,gBAAgB;AACnC,WAAO,IAAI,QAAQ,OAAO,IAAI,CAAC;AAC/B,WAAO,IAAI,YAAY,OAAO,QAAQ,CAAC;AACvC,QAAI,OAAO,KAAK,EAAG,QAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AACrD,QAAI,OAAO,QAAQ,cAAc,YAAY,QAAQ,UAAU,KAAK,GAAG;AACrE,aAAO,IAAI,aAAa,QAAQ,UAAU,KAAK,CAAC;AAAA,IAClD;AACA,QAAI,OAAO,QAAQ,WAAW,YAAY,QAAQ,OAAO,KAAK,GAAG;AAC/D,aAAO,IAAI,UAAU,QAAQ,OAAO,KAAK,CAAC;AAAA,IAC5C;AACA,UAAM,YAAY,QAAQ,CAAC;AAC3B,QAAI,WAAW;AACb,aAAO,IAAI,aAAa,UAAU,EAAE;AACpC,aAAO,IAAI,WAAW,UAAU,OAAO,SAAS,KAAK;AAAA,IACvD;AACA,WAAO,OAAO,SAAS;AAAA,EACzB,GAAG,CAAC,QAAQ,WAAW,QAAQ,QAAQ,MAAM,UAAU,QAAQ,OAAO,CAAC;AAEvE,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,WAAW;AACxB,iBAAW,IAAI;AACf,UAAI;AACF,cAAM,WAA+B,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,YAAY,EAAE;AAC1E,cAAM,OAAO,MAAM;AAAA,UACjB,wBAAwB,WAAW;AAAA,UACnC;AAAA,UACA,EAAE,SAAS;AAAA,QACb;AACA,YAAI,CAAC,KAAK,IAAI;AACZ,gBAAM,UAAU,gCAAgC,GAAG,OAAO;AAC1D;AAAA,QACF;AACA,cAAM,UAAU,KAAK,UAAU;AAC/B,YAAI,UAAW;AACf,gBAAQ,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC,CAAC;AACzD,iBAAS,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,CAAC;AAC9D,sBAAc,OAAO,QAAQ,eAAe,WAAW,QAAQ,aAAa,CAAC;AAC7E,yBAAiB,SAAS,kBAAkB,IAAI;AAAA,MAClD,QAAQ;AACN,YAAI,CAAC,UAAW,OAAM,UAAU,gCAAgC,GAAG,OAAO;AAAA,MAC5E,UAAE;AACA,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC;AAAA,IACF;AACA,aAAS;AACT,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,aAAa,aAAa,cAAc,SAAS,CAAC;AAEtD,QAAM,cAAc,MAAM,YAAY,MAAM;AAC1C,mBAAe,CAAC,iBAAiB,eAAe,CAAC;AAAA,EACnD,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,MAAM,YAAY,OAAO,QAAsB;AAClE,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B,OAAO,UAAU,sCAAsC,EAAE,OAAO,IAAI,MAAM,CAAC;AAAA,MAC3E,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAW;AAEhB,QAAI;AACF,YAAM,YAAY;AAAA,QAChB,WAAW,YAAY;AACrB,gBAAM,OAAO,MAAM;AAAA,YACjB,0BAA0B,IAAI,SAAS;AAAA,YACvC,MAAM;AAAA,cACJ,2BAA2B,mBAAmB,IAAI,EAAE,CAAC;AAAA,cACrD,EAAE,QAAQ,SAAS;AAAA,YACrB;AAAA,UACF;AACA,cAAI,CAAC,KAAK,IAAI;AACZ,kBAAM,OAAO,OAAO,IAAI,MAAM,yCAAyC,GAAG;AAAA,cACxE,QAAQ,KAAK;AAAA,cACb,GAAK,KAAK,UAA6C,CAAC;AAAA,YAC1D,CAAC;AAAA,UACH;AACA,iBAAO;AAAA,QACT;AAAA,QACA,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,cAAc;AAAA,UACd,YAAY,IAAI;AAAA,UAChB;AAAA,QACF;AAAA,QACA,iBAAiB,EAAE,IAAI,IAAI,GAAG;AAAA,MAChC,CAAC;AACD,YAAM,UAAU,oCAAoC,GAAG,SAAS;AAChE,kBAAY;AAAA,IACd,SAAS,OAAO;AACd,UAAI,sBAAsB,OAAO,WAAW,EAAE,WAAW,YAAY,CAAC,EAAG;AACzE;AAAA,QACE,0BAA0B,OAAO,WAAW,UAAU,kCAAkC,CAAC;AAAA,QACzF;AAAA,MACF;AACA,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,SAAS,mBAAmB,aAAa,mBAAmB,aAAa,SAAS,CAAC;AAEvF,QAAM,UAAU,MAAM,QAAmC,MAAM;AAAA,IAC7D;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,oCAAoC;AAAA,MACtD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,QAAK,MAAM,4BAA4B,IAAI,SAAS,EAAE,IAAI,WAAU,+BAClE,cAAI,SAAS,OAChB;AAAA,MAEF,MAAM,EAAE,UAAU,SAAS,UAAU,KAAK;AAAA,IAC5C;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,wCAAwC;AAAA,MAC1D,MAAM,CAAC,EAAE,IAAI,MAAM,UAAU,kBAAkB,IAAI,SAAS,SAAS,EAAE;AAAA,IACzE;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,qCAAqC;AAAA,MACvD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,eAAY,SAAS,mBAAmB,IAAI,SAAS,MAAM,GAAG,KAAG,MAC/D,oBAAU,wBAAwB,IAAI,SAAS,MAAM,EAAE,GAC1D;AAAA,IAEJ;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,2CAA2C;AAAA,MAC7D,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,eAC5B,UAAU,qBAAqB,IAAI,SAAS,YAAY,EAAE,IAC1D,UAAU,mBAAmB;AAAA,IACnC;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,QAAQ,UAAU,mDAAmD;AAAA,MACrE,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,aAC9B,oBAAC,eAAY,SAAS,2BAA2B,IAAI,SAAS,WAAW,UAAU,GAChF,oBAAU,mBAAmB,IAAI,SAAS,WAAW,UAAU,EAAE,GACpE,IACE,UAAU,mBAAmB;AAAA,IACnC;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,QAAQ,UAAU,6CAA6C;AAAA,MAC/D,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,aAC9B,oBAAC,eAAY,SAAS,qBAAqB,IAAI,SAAS,WAAW,WAAW,GAC3E,oBAAU,iBAAiB,IAAI,SAAS,WAAW,WAAW,EAAE,GACnE,IACE,UAAU,mBAAmB;AAAA,IACnC;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,8CAA8C;AAAA,MAChE,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,mBAAmB,UAAU,mBAAmB;AAAA,IAClF;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,yCAAyC;AAAA,MAC3D,MAAM,CAAC,EAAE,IAAI,MAAM,iBAAiB,IAAI,SAAS,YAAY,UAAU,mBAAmB,CAAC;AAAA,IAC7F;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,wCAAwC;AAAA,MAC1D,MAAM,CAAC,EAAE,IAAI,MAAM,eAAe,IAAI,SAAS,WAAW,UAAU,mBAAmB,GAAG,MAAM;AAAA,IAClG;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,QAAM,aAAa,MAAM,QAAqB,MAAM;AAAA,IAClD;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,wCAAwC;AAAA,MACzD,MAAM;AAAA,MACN,SAAS;AAAA,QACP,EAAE,OAAO,IAAI,OAAO,UAAU,6CAA6C,EAAE;AAAA,QAC7E,GAAG,iBAAiB,SAAS;AAAA,MAC/B;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,qCAAqC;AAAA,MACtD,MAAM;AAAA,MACN,SAAS;AAAA,QACP,EAAE,OAAO,IAAI,OAAO,UAAU,0CAA0C,EAAE;AAAA,QAC1E,GAAG,uBAAuB,SAAS;AAAA,MACrC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,SACE,qBAAC,QACC;AAAA,wBAAC,YACC;AAAA,MAAC;AAAA;AAAA,QACD,OAAO,UAAU,4BAA4B;AAAA,QAC7C,mBAAmB;AAAA,QACjB;AAAA,QACA,MAAM;AAAA,QACN,aAAa;AAAA,QACb,gBAAgB,CAAC,eAAe;AAC9B,oBAAU,UAAU;AACpB,kBAAQ,CAAC;AAAA,QACX;AAAA,QACA,mBAAmB,UAAU,wCAAwC;AAAA,QACrE,SAAS;AAAA,QACT,cAAc;AAAA,QACd,gBAAgB,CAAC,gBAAgB;AAC/B,qBAAW,WAAW;AACtB,kBAAQ,CAAC;AAAA,QACX;AAAA,QACA,gBAAgB,MAAM;AACpB,qBAAW,CAAC,CAAC;AACb,kBAAQ,CAAC;AAAA,QACX;AAAA,QACA,SACE,oBAAC,UAAO,SAAO,MACb,+BAAC,QAAK,MAAK,mCACT;AAAA,8BAAC,QAAK,WAAU,gBAAe,eAAW,MAAC;AAAA,UAC1C,UAAU,qCAAqC;AAAA,WAClD,GACF;AAAA,QAEF,YAAY,CAAC,QAAQ;AACnB,gBAAM,QAAyB;AAAA,YAC7B;AAAA,cACE,IAAI;AAAA,cACJ,OAAO,UAAU,mCAAmC;AAAA,cACpD,MAAM,4BAA4B,IAAI,EAAE;AAAA,YAC1C;AAAA,YACA;AAAA,cACE,IAAI;AAAA,cACJ,OAAO,UAAU,iCAAiC;AAAA,cAClD,MAAM,iDAAiD,mBAAmB,IAAI,EAAE,CAAC;AAAA,YACnF;AAAA,UACF;AACA,cAAI,mBAAmB,IAAI,MAAM,GAAG;AAClC,kBAAM,KAAK;AAAA,cACT,IAAI;AAAA,cACJ,OAAO,UAAU,qCAAqC;AAAA,cACtD,aAAa;AAAA,cACb,UAAU,MAAM;AACd,qBAAK,aAAa,GAAG;AAAA,cACvB;AAAA,YACF,CAAC;AAAA,UACH;AACA,iBAAO,oBAAC,cAAW,OAAc;AAAA,QACnC;AAAA,QACA,YAAY,CAAC,QAAQ,OAAO,KAAK,4BAA4B,IAAI,EAAE,EAAE;AAAA,QACrE,mBAAmB,CAAC,MAAM;AAAA,QAC1B,YACE;AAAA,UAAC;AAAA;AAAA,YACC,YAAY,UAAU,iCAAiC;AAAA,YACvD,YAAW;AAAA,YACX,aAAa,UAAU,qCAAqC;AAAA;AAAA,QAC9D;AAAA,QAEF,UAAQ;AAAA,QACR,eAAa;AAAA,QACb;AAAA,QACA,iBAAiB,CAAC,gBAAgB;AAChC,qBAAW,WAAW;AACtB,kBAAQ,CAAC;AAAA,QACX;AAAA,QACA,YAAY;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,cAAc;AAAA,UACd,iBAAiB,CAAC,IAAI,IAAI,GAAG;AAAA,UAC7B,kBAAkB,CAAC,iBAAiB;AAClC,wBAAY,YAAY;AACxB,oBAAQ,CAAC;AAAA,UACX;AAAA,QACF;AAAA,QACA,WAAW;AAAA,QACX,aAAa,EAAE,SAAS,uBAAuB;AAAA,QAC/C,qBAAmB;AAAA;AAAA,IACrB,GACF;AAAA,IACC;AAAA,KACH;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -247,6 +247,7 @@ function MappingSuggestionsDialog({
247
247
  DataTable,
248
248
  {
249
249
  title: t("eudr.suggestions.tableTitle"),
250
+ titleHeadingLevel: 2,
250
251
  columns,
251
252
  data: items,
252
253
  emptyState: /* @__PURE__ */ jsx(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/eudr/components/MappingSuggestionsDialog.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { EmptyState } from '@open-mercato/ui/backend/EmptyState'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport {\n EUDR_COMMODITIES,\n type EudrCommodity,\n} from '../data/validators'\n\ntype MappingSuggestion = {\n productId: string\n name: string\n sku: string | null\n hsCode: string\n suggestedCommodity: EudrCommodity\n}\n\ntype SuggestionsResponse = {\n items: MappingSuggestion[]\n}\n\ntype ApplyResponse = {\n created: number\n failed: Array<{ productId: string; errorKey: string }>\n}\n\ntype ApplyItem = {\n productId: string\n commodity: EudrCommodity\n hsCode: string\n}\n\ntype MappingSuggestionsDialogProps = {\n open: boolean\n onOpenChange: (open: boolean) => void\n onApplied?: () => void\n}\n\nconst commoditySet = new Set<string>(EUDR_COMMODITIES)\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isEudrCommodity(value: unknown): value is EudrCommodity {\n return typeof value === 'string' && commoditySet.has(value)\n}\n\nfunction normalizeSuggestion(value: unknown): MappingSuggestion | null {\n if (!isRecord(value)) return null\n const { productId, name, sku, hsCode, suggestedCommodity } = value\n if (\n typeof productId !== 'string'\n || typeof name !== 'string'\n || typeof hsCode !== 'string'\n || !isEudrCommodity(suggestedCommodity)\n ) {\n return null\n }\n return {\n productId,\n name,\n sku: typeof sku === 'string' ? sku : null,\n hsCode,\n suggestedCommodity,\n }\n}\n\nfunction normalizeSuggestionsResponse(value: SuggestionsResponse | null): MappingSuggestion[] {\n const rawItems = Array.isArray((value as { items?: unknown[] } | null)?.items)\n ? (value as { items: unknown[] }).items\n : []\n return rawItems\n .map(normalizeSuggestion)\n .filter((item): item is MappingSuggestion => item !== null)\n}\n\nfunction formatProductLabel(item: MappingSuggestion): string {\n return item.sku ? `${item.name} (${item.sku})` : item.name\n}\n\nexport function MappingSuggestionsDialog({\n open,\n onOpenChange,\n onApplied,\n}: MappingSuggestionsDialogProps) {\n const t = useT()\n const [items, setItems] = React.useState<MappingSuggestion[]>([])\n const [selectedIds, setSelectedIds] = React.useState<Set<string>>(() => new Set())\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [applying, setApplying] = React.useState(false)\n const [failures, setFailures] = React.useState<ApplyResponse['failed']>([])\n const appliedDuringSessionRef = React.useRef(false)\n const mutationContextId = 'eudr-product-mapping-suggestions:apply'\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked'),\n })\n\n const closeDialog = React.useCallback((nextOpen: boolean) => {\n if (!nextOpen && appliedDuringSessionRef.current) {\n onApplied?.()\n appliedDuringSessionRef.current = false\n }\n onOpenChange(nextOpen)\n }, [onApplied, onOpenChange])\n\n React.useEffect(() => {\n if (!open) return\n appliedDuringSessionRef.current = false\n setFailures([])\n setSelectedIds(new Set<string>())\n\n let cancelled = false\n async function loadSuggestions() {\n setLoading(true)\n setError(null)\n try {\n const fallback: SuggestionsResponse = { items: [] }\n const call = await apiCall<SuggestionsResponse>(\n '/api/eudr/product-mappings/suggestions',\n undefined,\n { fallback },\n )\n if (!call.ok) {\n setError(t('eudr.suggestions.loadError'))\n return\n }\n const nextItems = normalizeSuggestionsResponse(call.result ?? fallback)\n if (cancelled) return\n setItems(nextItems)\n setSelectedIds(new Set(nextItems.map((item) => item.productId)))\n } catch {\n if (!cancelled) setError(t('eudr.suggestions.loadError'))\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n\n void loadSuggestions()\n return () => {\n cancelled = true\n }\n }, [open, t])\n\n const selectedItems = React.useMemo(() => {\n return items.filter((item) => selectedIds.has(item.productId))\n }, [items, selectedIds])\n\n const selectedCount = selectedItems.length\n const allSelected = items.length > 0 && selectedCount === items.length\n const partiallySelected = selectedCount > 0 && selectedCount < items.length\n const canApply = selectedCount > 0 && !applying && !loading\n\n const toggleAll = React.useCallback((checked: boolean | 'indeterminate') => {\n if (checked) {\n setSelectedIds(new Set(items.map((item) => item.productId)))\n } else {\n setSelectedIds(new Set<string>())\n }\n }, [items])\n\n const toggleOne = React.useCallback((productId: string, checked: boolean | 'indeterminate') => {\n setSelectedIds((current) => {\n const next = new Set(current)\n if (checked) next.add(productId)\n else next.delete(productId)\n return next\n })\n }, [])\n\n const columns = React.useMemo<ColumnDef<MappingSuggestion>[]>(() => [\n {\n id: 'select',\n header: () => (\n <Checkbox\n aria-label={t('eudr.suggestions.selectAll')}\n checked={allSelected ? true : partiallySelected ? 'indeterminate' : false}\n onCheckedChange={toggleAll}\n />\n ),\n cell: ({ row }) => (\n <Checkbox\n aria-label={t('eudr.suggestions.selectRow', { product: formatProductLabel(row.original) })}\n checked={selectedIds.has(row.original.productId)}\n onCheckedChange={(checked) => toggleOne(row.original.productId, checked)}\n />\n ),\n enableSorting: false,\n size: 48,\n },\n {\n accessorKey: 'name',\n header: t('eudr.suggestions.columns.product'),\n cell: ({ row }) => (\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\">{row.original.name}</p>\n {row.original.sku ? (\n <p className=\"truncate text-xs text-muted-foreground\">{row.original.sku}</p>\n ) : null}\n </div>\n ),\n meta: { maxWidth: '260px', truncate: true },\n },\n {\n accessorKey: 'hsCode',\n header: t('eudr.suggestions.columns.hsCode'),\n cell: ({ row }) => <span className=\"font-mono text-xs\">{row.original.hsCode}</span>,\n },\n {\n accessorKey: 'suggestedCommodity',\n header: t('eudr.suggestions.columns.suggestedCommodity'),\n cell: ({ row }) => (\n <Tag variant=\"success\">\n {t(`eudr.commodity.${row.original.suggestedCommodity}`)}\n </Tag>\n ),\n },\n ], [allSelected, partiallySelected, selectedIds, t, toggleAll, toggleOne])\n\n const handleApply = React.useCallback(async () => {\n if (!canApply) return\n setApplying(true)\n setFailures([])\n try {\n const payloadItems: ApplyItem[] = selectedItems.map((item) => ({\n productId: item.productId,\n commodity: item.suggestedCommodity,\n hsCode: item.hsCode,\n }))\n const call = await runMutation({\n operation: () => apiCallOrThrow<ApplyResponse>(\n '/api/eudr/product-mappings/suggestions/apply',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ items: payloadItems }),\n },\n { errorMessage: t('eudr.suggestions.applyError') },\n ),\n context: {\n formId: mutationContextId,\n resourceKind: 'eudr.product_mapping',\n resourceId: 'bulk-suggestions',\n retryLastMutation,\n },\n mutationPayload: { items: payloadItems },\n })\n const result = call.result ?? { created: 0, failed: [] }\n appliedDuringSessionRef.current = true\n flash(t('eudr.suggestions.applySuccess', { count: result.created }), result.created > 0 ? 'success' : 'warning')\n const failures = Array.isArray(result.failed) ? result.failed : []\n setFailures(failures)\n if (!failures.length) {\n closeDialog(false)\n } else {\n setSelectedIds(new Set(failures.map((failure) => failure.productId)))\n }\n } catch {\n flash(t('eudr.suggestions.applyError'), 'error')\n } finally {\n setApplying(false)\n }\n }, [canApply, closeDialog, mutationContextId, retryLastMutation, runMutation, selectedItems, t])\n\n return (\n <Dialog open={open} onOpenChange={closeDialog}>\n <DialogContent\n size=\"xl\"\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n closeDialog(false)\n return\n }\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void handleApply()\n }\n }}\n >\n <DialogHeader>\n <DialogTitle>{t('eudr.suggestions.title')}</DialogTitle>\n </DialogHeader>\n\n <div className=\"min-h-64\">\n {error ? (\n <ErrorMessage label={error} />\n ) : loading ? (\n <LoadingMessage label={t('eudr.suggestions.loading')} />\n ) : items.length === 0 ? (\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={t('eudr.suggestions.empty')}\n description={t('eudr.suggestions.emptyHint')}\n />\n ) : (\n <div className=\"space-y-3\">\n <DataTable<MappingSuggestion>\n title={t('eudr.suggestions.tableTitle')}\n columns={columns}\n data={items}\n emptyState={(\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={t('eudr.suggestions.empty')}\n description={t('eudr.suggestions.emptyHint')}\n />\n )}\n perspective={{ tableId: 'eudr.product_mapping_suggestions.dialog' }}\n disableRowClick\n />\n {failures.length > 0 ? (\n <div className=\"rounded-md border border-status-error-border bg-status-error-bg p-3 text-sm text-status-error-text\">\n <p className=\"font-medium\">{t('eudr.suggestions.failuresTitle')}</p>\n <ul className=\"mt-2 space-y-1\">\n {failures.map((failure) => {\n const item = items.find((candidate) => candidate.productId === failure.productId)\n return (\n <li key={failure.productId}>\n <span className=\"font-medium\">\n {item ? formatProductLabel(item) : t('eudr.common.recordUnavailable')}\n </span>\n {': '}\n <span>{t(failure.errorKey)}</span>\n </li>\n )\n })}\n </ul>\n </div>\n ) : null}\n </div>\n )}\n </div>\n\n <DialogFooter>\n <span className=\"mr-auto text-sm text-muted-foreground\">\n {t('eudr.suggestions.selectedCount', { count: selectedCount })}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => closeDialog(false)}\n >\n {t('eudr.suggestions.cancel')}\n </Button>\n <Button\n type=\"button\"\n onClick={() => void handleApply()}\n disabled={!canApply}\n >\n {applying ? t('eudr.suggestions.applying') : t('eudr.suggestions.apply')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nexport default MappingSuggestionsDialog\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { EmptyState } from '@open-mercato/ui/backend/EmptyState'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport {\n EUDR_COMMODITIES,\n type EudrCommodity,\n} from '../data/validators'\n\ntype MappingSuggestion = {\n productId: string\n name: string\n sku: string | null\n hsCode: string\n suggestedCommodity: EudrCommodity\n}\n\ntype SuggestionsResponse = {\n items: MappingSuggestion[]\n}\n\ntype ApplyResponse = {\n created: number\n failed: Array<{ productId: string; errorKey: string }>\n}\n\ntype ApplyItem = {\n productId: string\n commodity: EudrCommodity\n hsCode: string\n}\n\ntype MappingSuggestionsDialogProps = {\n open: boolean\n onOpenChange: (open: boolean) => void\n onApplied?: () => void\n}\n\nconst commoditySet = new Set<string>(EUDR_COMMODITIES)\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isEudrCommodity(value: unknown): value is EudrCommodity {\n return typeof value === 'string' && commoditySet.has(value)\n}\n\nfunction normalizeSuggestion(value: unknown): MappingSuggestion | null {\n if (!isRecord(value)) return null\n const { productId, name, sku, hsCode, suggestedCommodity } = value\n if (\n typeof productId !== 'string'\n || typeof name !== 'string'\n || typeof hsCode !== 'string'\n || !isEudrCommodity(suggestedCommodity)\n ) {\n return null\n }\n return {\n productId,\n name,\n sku: typeof sku === 'string' ? sku : null,\n hsCode,\n suggestedCommodity,\n }\n}\n\nfunction normalizeSuggestionsResponse(value: SuggestionsResponse | null): MappingSuggestion[] {\n const rawItems = Array.isArray((value as { items?: unknown[] } | null)?.items)\n ? (value as { items: unknown[] }).items\n : []\n return rawItems\n .map(normalizeSuggestion)\n .filter((item): item is MappingSuggestion => item !== null)\n}\n\nfunction formatProductLabel(item: MappingSuggestion): string {\n return item.sku ? `${item.name} (${item.sku})` : item.name\n}\n\nexport function MappingSuggestionsDialog({\n open,\n onOpenChange,\n onApplied,\n}: MappingSuggestionsDialogProps) {\n const t = useT()\n const [items, setItems] = React.useState<MappingSuggestion[]>([])\n const [selectedIds, setSelectedIds] = React.useState<Set<string>>(() => new Set())\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [applying, setApplying] = React.useState(false)\n const [failures, setFailures] = React.useState<ApplyResponse['failed']>([])\n const appliedDuringSessionRef = React.useRef(false)\n const mutationContextId = 'eudr-product-mapping-suggestions:apply'\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked'),\n })\n\n const closeDialog = React.useCallback((nextOpen: boolean) => {\n if (!nextOpen && appliedDuringSessionRef.current) {\n onApplied?.()\n appliedDuringSessionRef.current = false\n }\n onOpenChange(nextOpen)\n }, [onApplied, onOpenChange])\n\n React.useEffect(() => {\n if (!open) return\n appliedDuringSessionRef.current = false\n setFailures([])\n setSelectedIds(new Set<string>())\n\n let cancelled = false\n async function loadSuggestions() {\n setLoading(true)\n setError(null)\n try {\n const fallback: SuggestionsResponse = { items: [] }\n const call = await apiCall<SuggestionsResponse>(\n '/api/eudr/product-mappings/suggestions',\n undefined,\n { fallback },\n )\n if (!call.ok) {\n setError(t('eudr.suggestions.loadError'))\n return\n }\n const nextItems = normalizeSuggestionsResponse(call.result ?? fallback)\n if (cancelled) return\n setItems(nextItems)\n setSelectedIds(new Set(nextItems.map((item) => item.productId)))\n } catch {\n if (!cancelled) setError(t('eudr.suggestions.loadError'))\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n\n void loadSuggestions()\n return () => {\n cancelled = true\n }\n }, [open, t])\n\n const selectedItems = React.useMemo(() => {\n return items.filter((item) => selectedIds.has(item.productId))\n }, [items, selectedIds])\n\n const selectedCount = selectedItems.length\n const allSelected = items.length > 0 && selectedCount === items.length\n const partiallySelected = selectedCount > 0 && selectedCount < items.length\n const canApply = selectedCount > 0 && !applying && !loading\n\n const toggleAll = React.useCallback((checked: boolean | 'indeterminate') => {\n if (checked) {\n setSelectedIds(new Set(items.map((item) => item.productId)))\n } else {\n setSelectedIds(new Set<string>())\n }\n }, [items])\n\n const toggleOne = React.useCallback((productId: string, checked: boolean | 'indeterminate') => {\n setSelectedIds((current) => {\n const next = new Set(current)\n if (checked) next.add(productId)\n else next.delete(productId)\n return next\n })\n }, [])\n\n const columns = React.useMemo<ColumnDef<MappingSuggestion>[]>(() => [\n {\n id: 'select',\n header: () => (\n <Checkbox\n aria-label={t('eudr.suggestions.selectAll')}\n checked={allSelected ? true : partiallySelected ? 'indeterminate' : false}\n onCheckedChange={toggleAll}\n />\n ),\n cell: ({ row }) => (\n <Checkbox\n aria-label={t('eudr.suggestions.selectRow', { product: formatProductLabel(row.original) })}\n checked={selectedIds.has(row.original.productId)}\n onCheckedChange={(checked) => toggleOne(row.original.productId, checked)}\n />\n ),\n enableSorting: false,\n size: 48,\n },\n {\n accessorKey: 'name',\n header: t('eudr.suggestions.columns.product'),\n cell: ({ row }) => (\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\">{row.original.name}</p>\n {row.original.sku ? (\n <p className=\"truncate text-xs text-muted-foreground\">{row.original.sku}</p>\n ) : null}\n </div>\n ),\n meta: { maxWidth: '260px', truncate: true },\n },\n {\n accessorKey: 'hsCode',\n header: t('eudr.suggestions.columns.hsCode'),\n cell: ({ row }) => <span className=\"font-mono text-xs\">{row.original.hsCode}</span>,\n },\n {\n accessorKey: 'suggestedCommodity',\n header: t('eudr.suggestions.columns.suggestedCommodity'),\n cell: ({ row }) => (\n <Tag variant=\"success\">\n {t(`eudr.commodity.${row.original.suggestedCommodity}`)}\n </Tag>\n ),\n },\n ], [allSelected, partiallySelected, selectedIds, t, toggleAll, toggleOne])\n\n const handleApply = React.useCallback(async () => {\n if (!canApply) return\n setApplying(true)\n setFailures([])\n try {\n const payloadItems: ApplyItem[] = selectedItems.map((item) => ({\n productId: item.productId,\n commodity: item.suggestedCommodity,\n hsCode: item.hsCode,\n }))\n const call = await runMutation({\n operation: () => apiCallOrThrow<ApplyResponse>(\n '/api/eudr/product-mappings/suggestions/apply',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ items: payloadItems }),\n },\n { errorMessage: t('eudr.suggestions.applyError') },\n ),\n context: {\n formId: mutationContextId,\n resourceKind: 'eudr.product_mapping',\n resourceId: 'bulk-suggestions',\n retryLastMutation,\n },\n mutationPayload: { items: payloadItems },\n })\n const result = call.result ?? { created: 0, failed: [] }\n appliedDuringSessionRef.current = true\n flash(t('eudr.suggestions.applySuccess', { count: result.created }), result.created > 0 ? 'success' : 'warning')\n const failures = Array.isArray(result.failed) ? result.failed : []\n setFailures(failures)\n if (!failures.length) {\n closeDialog(false)\n } else {\n setSelectedIds(new Set(failures.map((failure) => failure.productId)))\n }\n } catch {\n flash(t('eudr.suggestions.applyError'), 'error')\n } finally {\n setApplying(false)\n }\n }, [canApply, closeDialog, mutationContextId, retryLastMutation, runMutation, selectedItems, t])\n\n return (\n <Dialog open={open} onOpenChange={closeDialog}>\n <DialogContent\n size=\"xl\"\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n closeDialog(false)\n return\n }\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void handleApply()\n }\n }}\n >\n <DialogHeader>\n <DialogTitle>{t('eudr.suggestions.title')}</DialogTitle>\n </DialogHeader>\n\n <div className=\"min-h-64\">\n {error ? (\n <ErrorMessage label={error} />\n ) : loading ? (\n <LoadingMessage label={t('eudr.suggestions.loading')} />\n ) : items.length === 0 ? (\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={t('eudr.suggestions.empty')}\n description={t('eudr.suggestions.emptyHint')}\n />\n ) : (\n <div className=\"space-y-3\">\n <DataTable<MappingSuggestion>\n title={t('eudr.suggestions.tableTitle')}\n titleHeadingLevel={2}\n columns={columns}\n data={items}\n emptyState={(\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={t('eudr.suggestions.empty')}\n description={t('eudr.suggestions.emptyHint')}\n />\n )}\n perspective={{ tableId: 'eudr.product_mapping_suggestions.dialog' }}\n disableRowClick\n />\n {failures.length > 0 ? (\n <div className=\"rounded-md border border-status-error-border bg-status-error-bg p-3 text-sm text-status-error-text\">\n <p className=\"font-medium\">{t('eudr.suggestions.failuresTitle')}</p>\n <ul className=\"mt-2 space-y-1\">\n {failures.map((failure) => {\n const item = items.find((candidate) => candidate.productId === failure.productId)\n return (\n <li key={failure.productId}>\n <span className=\"font-medium\">\n {item ? formatProductLabel(item) : t('eudr.common.recordUnavailable')}\n </span>\n {': '}\n <span>{t(failure.errorKey)}</span>\n </li>\n )\n })}\n </ul>\n </div>\n ) : null}\n </div>\n )}\n </div>\n\n <DialogFooter>\n <span className=\"mr-auto text-sm text-muted-foreground\">\n {t('eudr.suggestions.selectedCount', { count: selectedCount })}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => closeDialog(false)}\n >\n {t('eudr.suggestions.cancel')}\n </Button>\n <Button\n type=\"button\"\n onClick={() => void handleApply()}\n disabled={!canApply}\n >\n {applying ? t('eudr.suggestions.applying') : t('eudr.suggestions.apply')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nexport default MappingSuggestionsDialog\n"],
5
+ "mappings": ";AAsMQ,cAoBA,YApBA;AApMR,YAAY,WAAW;AAEvB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AACtB,SAAS,0BAA0B;AACnC,SAAS,cAAc,sBAAsB;AAC7C,SAAS,SAAS,sBAAsB;AACxC,SAAS,cAAc;AACvB,SAAS,gBAAgB;AACzB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW;AACpB;AAAA,EACE;AAAA,OAEK;AA+BP,MAAM,eAAe,IAAI,IAAY,gBAAgB;AAErD,SAAS,SAAS,OAAkD;AAClE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,gBAAgB,OAAwC;AAC/D,SAAO,OAAO,UAAU,YAAY,aAAa,IAAI,KAAK;AAC5D;AAEA,SAAS,oBAAoB,OAA0C;AACrE,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,QAAM,EAAE,WAAW,MAAM,KAAK,QAAQ,mBAAmB,IAAI;AAC7D,MACE,OAAO,cAAc,YAClB,OAAO,SAAS,YAChB,OAAO,WAAW,YAClB,CAAC,gBAAgB,kBAAkB,GACtC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,KAAK,OAAO,QAAQ,WAAW,MAAM;AAAA,IACrC;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,6BAA6B,OAAwD;AAC5F,QAAM,WAAW,MAAM,QAAS,OAAwC,KAAK,IACxE,MAA+B,QAChC,CAAC;AACL,SAAO,SACJ,IAAI,mBAAmB,EACvB,OAAO,CAAC,SAAoC,SAAS,IAAI;AAC9D;AAEA,SAAS,mBAAmB,MAAiC;AAC3D,SAAO,KAAK,MAAM,GAAG,KAAK,IAAI,KAAK,KAAK,GAAG,MAAM,KAAK;AACxD;AAEO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AACF,GAAkC;AAChC,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAA8B,CAAC,CAAC;AAChE,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAsB,MAAM,oBAAI,IAAI,CAAC;AACjF,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAC5D,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAS,KAAK;AACpD,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAkC,CAAC,CAAC;AAC1E,QAAM,0BAA0B,MAAM,OAAO,KAAK;AAClD,QAAM,oBAAoB;AAC1B,QAAM,EAAE,aAAa,kBAAkB,IAAI,mBAKxC;AAAA,IACD,WAAW;AAAA,IACX,gBAAgB,EAAE,4BAA4B;AAAA,EAChD,CAAC;AAED,QAAM,cAAc,MAAM,YAAY,CAAC,aAAsB;AAC3D,QAAI,CAAC,YAAY,wBAAwB,SAAS;AAChD,kBAAY;AACZ,8BAAwB,UAAU;AAAA,IACpC;AACA,iBAAa,QAAQ;AAAA,EACvB,GAAG,CAAC,WAAW,YAAY,CAAC;AAE5B,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,KAAM;AACX,4BAAwB,UAAU;AAClC,gBAAY,CAAC,CAAC;AACd,mBAAe,oBAAI,IAAY,CAAC;AAEhC,QAAI,YAAY;AAChB,mBAAe,kBAAkB;AAC/B,iBAAW,IAAI;AACf,eAAS,IAAI;AACb,UAAI;AACF,cAAM,WAAgC,EAAE,OAAO,CAAC,EAAE;AAClD,cAAM,OAAO,MAAM;AAAA,UACjB;AAAA,UACA;AAAA,UACA,EAAE,SAAS;AAAA,QACb;AACA,YAAI,CAAC,KAAK,IAAI;AACZ,mBAAS,EAAE,4BAA4B,CAAC;AACxC;AAAA,QACF;AACA,cAAM,YAAY,6BAA6B,KAAK,UAAU,QAAQ;AACtE,YAAI,UAAW;AACf,iBAAS,SAAS;AAClB,uBAAe,IAAI,IAAI,UAAU,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;AAAA,MACjE,QAAQ;AACN,YAAI,CAAC,UAAW,UAAS,EAAE,4BAA4B,CAAC;AAAA,MAC1D,UAAE;AACA,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC;AAAA,IACF;AAEA,SAAK,gBAAgB;AACrB,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,MAAM,CAAC,CAAC;AAEZ,QAAM,gBAAgB,MAAM,QAAQ,MAAM;AACxC,WAAO,MAAM,OAAO,CAAC,SAAS,YAAY,IAAI,KAAK,SAAS,CAAC;AAAA,EAC/D,GAAG,CAAC,OAAO,WAAW,CAAC;AAEvB,QAAM,gBAAgB,cAAc;AACpC,QAAM,cAAc,MAAM,SAAS,KAAK,kBAAkB,MAAM;AAChE,QAAM,oBAAoB,gBAAgB,KAAK,gBAAgB,MAAM;AACrE,QAAM,WAAW,gBAAgB,KAAK,CAAC,YAAY,CAAC;AAEpD,QAAM,YAAY,MAAM,YAAY,CAAC,YAAuC;AAC1E,QAAI,SAAS;AACX,qBAAe,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;AAAA,IAC7D,OAAO;AACL,qBAAe,oBAAI,IAAY,CAAC;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,YAAY,MAAM,YAAY,CAAC,WAAmB,YAAuC;AAC7F,mBAAe,CAAC,YAAY;AAC1B,YAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,UAAI,QAAS,MAAK,IAAI,SAAS;AAAA,UAC1B,MAAK,OAAO,SAAS;AAC1B,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,MAAM,QAAwC,MAAM;AAAA,IAClE;AAAA,MACE,IAAI;AAAA,MACJ,QAAQ,MACN;AAAA,QAAC;AAAA;AAAA,UACC,cAAY,EAAE,4BAA4B;AAAA,UAC1C,SAAS,cAAc,OAAO,oBAAoB,kBAAkB;AAAA,UACpE,iBAAiB;AAAA;AAAA,MACnB;AAAA,MAEF,MAAM,CAAC,EAAE,IAAI,MACX;AAAA,QAAC;AAAA;AAAA,UACC,cAAY,EAAE,8BAA8B,EAAE,SAAS,mBAAmB,IAAI,QAAQ,EAAE,CAAC;AAAA,UACzF,SAAS,YAAY,IAAI,IAAI,SAAS,SAAS;AAAA,UAC/C,iBAAiB,CAAC,YAAY,UAAU,IAAI,SAAS,WAAW,OAAO;AAAA;AAAA,MACzE;AAAA,MAEF,eAAe;AAAA,MACf,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,kCAAkC;AAAA,MAC5C,MAAM,CAAC,EAAE,IAAI,MACX,qBAAC,SAAI,WAAU,WACb;AAAA,4BAAC,OAAE,WAAU,wBAAwB,cAAI,SAAS,MAAK;AAAA,QACtD,IAAI,SAAS,MACZ,oBAAC,OAAE,WAAU,0CAA0C,cAAI,SAAS,KAAI,IACtE;AAAA,SACN;AAAA,MAEF,MAAM,EAAE,UAAU,SAAS,UAAU,KAAK;AAAA,IAC5C;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,iCAAiC;AAAA,MAC3C,MAAM,CAAC,EAAE,IAAI,MAAM,oBAAC,UAAK,WAAU,qBAAqB,cAAI,SAAS,QAAO;AAAA,IAC9E;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,6CAA6C;AAAA,MACvD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,OAAI,SAAQ,WACV,YAAE,kBAAkB,IAAI,SAAS,kBAAkB,EAAE,GACxD;AAAA,IAEJ;AAAA,EACF,GAAG,CAAC,aAAa,mBAAmB,aAAa,GAAG,WAAW,SAAS,CAAC;AAEzE,QAAM,cAAc,MAAM,YAAY,YAAY;AAChD,QAAI,CAAC,SAAU;AACf,gBAAY,IAAI;AAChB,gBAAY,CAAC,CAAC;AACd,QAAI;AACF,YAAM,eAA4B,cAAc,IAAI,CAAC,UAAU;AAAA,QAC7D,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,QAAQ,KAAK;AAAA,MACf,EAAE;AACF,YAAM,OAAO,MAAM,YAAY;AAAA,QAC7B,WAAW,MAAM;AAAA,UACf;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,YAC9C,MAAM,KAAK,UAAU,EAAE,OAAO,aAAa,CAAC;AAAA,UAC9C;AAAA,UACA,EAAE,cAAc,EAAE,6BAA6B,EAAE;AAAA,QACnD;AAAA,QACA,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,cAAc;AAAA,UACd,YAAY;AAAA,UACZ;AAAA,QACF;AAAA,QACA,iBAAiB,EAAE,OAAO,aAAa;AAAA,MACzC,CAAC;AACD,YAAM,SAAS,KAAK,UAAU,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE;AACvD,8BAAwB,UAAU;AAClC,YAAM,EAAE,iCAAiC,EAAE,OAAO,OAAO,QAAQ,CAAC,GAAG,OAAO,UAAU,IAAI,YAAY,SAAS;AAC/G,YAAMA,YAAW,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,SAAS,CAAC;AACjE,kBAAYA,SAAQ;AACpB,UAAI,CAACA,UAAS,QAAQ;AACpB,oBAAY,KAAK;AAAA,MACnB,OAAO;AACL,uBAAe,IAAI,IAAIA,UAAS,IAAI,CAAC,YAAY,QAAQ,SAAS,CAAC,CAAC;AAAA,MACtE;AAAA,IACF,QAAQ;AACN,YAAM,EAAE,6BAA6B,GAAG,OAAO;AAAA,IACjD,UAAE;AACA,kBAAY,KAAK;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,UAAU,aAAa,mBAAmB,mBAAmB,aAAa,eAAe,CAAC,CAAC;AAE/F,SACE,oBAAC,UAAO,MAAY,cAAc,aAChC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW,CAAC,UAAU;AACpB,YAAI,MAAM,QAAQ,UAAU;AAC1B,gBAAM,eAAe;AACrB,sBAAY,KAAK;AACjB;AAAA,QACF;AACA,aAAK,MAAM,WAAW,MAAM,YAAY,MAAM,QAAQ,SAAS;AAC7D,gBAAM,eAAe;AACrB,eAAK,YAAY;AAAA,QACnB;AAAA,MACF;AAAA,MAEA;AAAA,4BAAC,gBACC,8BAAC,eAAa,YAAE,wBAAwB,GAAE,GAC5C;AAAA,QAEA,oBAAC,SAAI,WAAU,YACZ,kBACC,oBAAC,gBAAa,OAAO,OAAO,IAC1B,UACF,oBAAC,kBAAe,OAAO,EAAE,0BAA0B,GAAG,IACpD,MAAM,WAAW,IACnB;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,OAAO,EAAE,wBAAwB;AAAA,YACjC,aAAa,EAAE,4BAA4B;AAAA;AAAA,QAC7C,IAEA,qBAAC,SAAI,WAAU,aACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,EAAE,6BAA6B;AAAA,cACtC,mBAAmB;AAAA,cACnB;AAAA,cACA,MAAM;AAAA,cACN,YACE;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAQ;AAAA,kBACR,OAAO,EAAE,wBAAwB;AAAA,kBACjC,aAAa,EAAE,4BAA4B;AAAA;AAAA,cAC7C;AAAA,cAEF,aAAa,EAAE,SAAS,0CAA0C;AAAA,cAClE,iBAAe;AAAA;AAAA,UACjB;AAAA,UACC,SAAS,SAAS,IACjB,qBAAC,SAAI,WAAU,sGACb;AAAA,gCAAC,OAAE,WAAU,eAAe,YAAE,gCAAgC,GAAE;AAAA,YAChE,oBAAC,QAAG,WAAU,kBACX,mBAAS,IAAI,CAAC,YAAY;AACzB,oBAAM,OAAO,MAAM,KAAK,CAAC,cAAc,UAAU,cAAc,QAAQ,SAAS;AAChF,qBACE,qBAAC,QACC;AAAA,oCAAC,UAAK,WAAU,eACb,iBAAO,mBAAmB,IAAI,IAAI,EAAE,+BAA+B,GACtE;AAAA,gBACC;AAAA,gBACD,oBAAC,UAAM,YAAE,QAAQ,QAAQ,GAAE;AAAA,mBALpB,QAAQ,SAMjB;AAAA,YAEJ,CAAC,GACH;AAAA,aACF,IACE;AAAA,WACN,GAEJ;AAAA,QAEA,qBAAC,gBACC;AAAA,8BAAC,UAAK,WAAU,yCACb,YAAE,kCAAkC,EAAE,OAAO,cAAc,CAAC,GAC/D;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,SAAS,MAAM,YAAY,KAAK;AAAA,cAE/B,YAAE,yBAAyB;AAAA;AAAA,UAC9B;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,MAAM,KAAK,YAAY;AAAA,cAChC,UAAU,CAAC;AAAA,cAEV,qBAAW,EAAE,2BAA2B,IAAI,EAAE,wBAAwB;AAAA;AAAA,UACzE;AAAA,WACF;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;AAEA,IAAO,mCAAQ;",
6
6
  "names": ["failures"]
7
7
  }
@@ -246,6 +246,7 @@ function MitigationActionsSection({
246
246
  DataTable,
247
247
  {
248
248
  title: translate("eudr.mitigationActions.tableTitle"),
249
+ titleHeadingLevel: 2,
249
250
  columns,
250
251
  data: rows,
251
252
  isLoading: loading,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/eudr/components/MitigationActionsSection.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Plus } from 'lucide-react'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrud, deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport {\n EUDR_MITIGATION_STATUSES,\n EUDR_MITIGATION_TYPES,\n type EudrMitigationStatus,\n type EudrMitigationType,\n} from '../data/validators'\n\ntype MitigationActionRow = {\n id: string\n riskAssessmentId: string\n actionType: EudrMitigationType | null\n title: string\n description: string | null\n status: EudrMitigationStatus | null\n dueDate: string | null\n completedAt: string | null\n notes: string | null\n updatedAt: string\n}\n\ntype MitigationActionsResponse = {\n items?: MitigationActionRow[]\n}\n\ntype MitigationActionFormValues = {\n actionType: string\n title: string\n description: string\n status: string\n dueDate: string\n notes: string\n} & Record<string, unknown>\n\ntype MutationContext = {\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n}\n\nexport type MitigationActionsSectionProps = {\n riskAssessmentId: string\n}\n\nfunction optionalText(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length ? trimmed : null\n}\n\nfunction formatDate(value: string | null | undefined, emptyLabel: string, locale: string): string {\n if (!value) return emptyLabel\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return emptyLabel\n return date.toLocaleDateString(locale || undefined)\n}\n\nfunction formatDateInput(value: string | null | undefined): string {\n if (!value) return ''\n return value.slice(0, 10)\n}\n\nfunction isOverdue(row: MitigationActionRow): boolean {\n if (!row.dueDate || row.status === 'completed') return false\n const date = new Date(row.dueDate)\n return !Number.isNaN(date.getTime()) && date.getTime() < Date.now()\n}\n\nfunction statusVariant(status: string | null | undefined): 'neutral' | 'info' | 'success' {\n if (status === 'in_progress') return 'info'\n if (status === 'completed') return 'success'\n return 'neutral'\n}\n\nfunction actionTypeOptions(translate: ReturnType<typeof useT>) {\n return EUDR_MITIGATION_TYPES.map((type) => ({\n value: type,\n label: translate(`eudr.mitigationType.${type}`),\n }))\n}\n\nfunction actionStatusOptions(translate: ReturnType<typeof useT>) {\n return EUDR_MITIGATION_STATUSES.map((status) => ({\n value: status,\n label: translate(`eudr.mitigationStatus.${status}`),\n }))\n}\n\nexport function MitigationActionsSection({\n riskAssessmentId,\n}: MitigationActionsSectionProps) {\n const translate = useT()\n const locale = useLocale()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<MitigationActionRow[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [dialogMode, setDialogMode] = React.useState<'create' | 'edit' | null>(null)\n const [editingRow, setEditingRow] = React.useState<MitigationActionRow | null>(null)\n const [reloadToken, setReloadToken] = React.useState(0)\n const mutationContextId = `eudr-mitigation-actions:${riskAssessmentId}`\n const { runMutation, retryLastMutation } = useGuardedMutation<MutationContext>({\n contextId: mutationContextId,\n blockedMessage: translate('ui.forms.flash.saveBlocked'),\n })\n\n React.useEffect(() => {\n let cancelled = false\n async function loadRows() {\n setLoading(true)\n setError(null)\n try {\n const call = await apiCall<MitigationActionsResponse>(\n `/api/eudr/mitigation-actions?riskAssessmentId=${encodeURIComponent(riskAssessmentId)}&pageSize=100&sortField=dueDate&sortDir=asc`,\n undefined,\n { fallback: { items: [] } },\n )\n if (!call.ok) {\n if (!cancelled) setError(translate('eudr.mitigationActions.loadError'))\n return\n }\n if (!cancelled) setRows(Array.isArray(call.result?.items) ? call.result.items : [])\n } catch {\n if (!cancelled) setError(translate('eudr.mitigationActions.loadError'))\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n loadRows()\n return () => {\n cancelled = true\n }\n }, [reloadToken, riskAssessmentId, translate])\n\n const refreshRows = React.useCallback(() => {\n setReloadToken((currentToken) => currentToken + 1)\n }, [])\n\n const openCreateDialog = React.useCallback(() => {\n setEditingRow(null)\n setDialogMode('create')\n }, [])\n\n const openEditDialog = React.useCallback((row: MitigationActionRow) => {\n setEditingRow(row)\n setDialogMode('edit')\n }, [])\n\n const closeDialog = React.useCallback(() => {\n setDialogMode(null)\n setEditingRow(null)\n }, [])\n\n const handleDelete = React.useCallback(async (row: MitigationActionRow) => {\n const confirmed = await confirm({\n title: translate('eudr.mitigationActions.confirmDelete', { title: row.title }),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n try {\n await runMutation({\n operation: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(row.updatedAt),\n () => deleteCrud('eudr/mitigation-actions', row.id, {\n errorMessage: translate('eudr.mitigationActions.deleteError'),\n }),\n ),\n context: {\n formId: mutationContextId,\n resourceKind: 'eudr.mitigation_action',\n resourceId: row.id,\n retryLastMutation,\n },\n mutationPayload: { id: row.id },\n })\n flash(translate('eudr.mitigationActions.deleteSuccess'), 'success')\n refreshRows()\n } catch (deleteError) {\n if (surfaceRecordConflict(deleteError, translate, { onRefresh: refreshRows })) return\n flash(translate('eudr.mitigationActions.deleteError'), 'error')\n }\n }, [confirm, mutationContextId, refreshRows, retryLastMutation, runMutation, translate])\n\n const fields = React.useMemo<CrudField[]>(() => [\n {\n id: 'actionType',\n label: translate('eudr.mitigationActions.form.actionType'),\n type: 'select',\n options: actionTypeOptions(translate),\n },\n {\n id: 'title',\n label: translate('eudr.mitigationActions.form.title'),\n type: 'text',\n required: true,\n },\n {\n id: 'description',\n label: translate('eudr.mitigationActions.form.description'),\n type: 'textarea',\n },\n {\n id: 'status',\n label: translate('eudr.mitigationActions.form.status'),\n type: 'select',\n options: actionStatusOptions(translate),\n },\n {\n id: 'dueDate',\n label: translate('eudr.mitigationActions.form.dueDate'),\n type: 'date',\n },\n {\n id: 'notes',\n label: translate('eudr.mitigationActions.form.notes'),\n type: 'textarea',\n },\n ], [translate])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => [\n {\n id: 'details',\n title: translate('eudr.mitigationActions.form.details'),\n column: 1,\n fields: ['actionType', 'title', 'description', 'status', 'dueDate', 'notes'],\n },\n ], [translate])\n\n const initialValues = React.useMemo<MitigationActionFormValues>(() => ({\n actionType: editingRow?.actionType ?? 'request_documents',\n title: editingRow?.title ?? '',\n description: editingRow?.description ?? '',\n status: editingRow?.status ?? 'planned',\n dueDate: formatDateInput(editingRow?.dueDate),\n notes: editingRow?.notes ?? '',\n }), [editingRow])\n\n const columns = React.useMemo<ColumnDef<MitigationActionRow>[]>(() => [\n {\n accessorKey: 'title',\n header: translate('eudr.mitigationActions.columns.title'),\n cell: ({ row }) => row.original.title,\n meta: { maxWidth: '260px', truncate: true },\n },\n {\n accessorKey: 'actionType',\n header: translate('eudr.mitigationActions.columns.type'),\n cell: ({ row }) => row.original.actionType\n ? translate(`eudr.mitigationType.${row.original.actionType}`)\n : translate('eudr.common.empty'),\n },\n {\n accessorKey: 'status',\n header: translate('eudr.mitigationActions.columns.status'),\n cell: ({ row }) => (\n <StatusBadge variant={statusVariant(row.original.status)} dot>\n {row.original.status ? translate(`eudr.mitigationStatus.${row.original.status}`) : translate('eudr.common.empty')}\n </StatusBadge>\n ),\n },\n {\n accessorKey: 'dueDate',\n header: translate('eudr.mitigationActions.columns.dueDate'),\n cell: ({ row }) => (\n <span className={isOverdue(row.original) ? 'text-status-warning-text' : undefined}>\n {formatDate(row.original.dueDate, translate('eudr.common.empty'), locale)}\n </span>\n ),\n },\n {\n accessorKey: 'completedAt',\n header: translate('eudr.mitigationActions.columns.completedAt'),\n cell: ({ row }) => formatDate(row.original.completedAt, translate('eudr.common.empty'), locale),\n },\n ], [locale, translate])\n\n return (\n <section className=\"space-y-4 rounded-lg border border-border bg-card p-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold\">{translate('eudr.mitigationActions.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">{translate('eudr.mitigationActions.description')}</p>\n </div>\n <Button type=\"button\" onClick={openCreateDialog}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('eudr.mitigationActions.actions.add')}\n </Button>\n </div>\n\n <DataTable<MitigationActionRow>\n title={translate('eudr.mitigationActions.tableTitle')}\n columns={columns}\n data={rows}\n isLoading={loading}\n error={error}\n rowActions={(row) => (\n <RowActions\n items={[\n {\n id: 'edit',\n label: translate('eudr.mitigationActions.actions.edit'),\n onSelect: () => openEditDialog(row),\n },\n {\n id: 'delete',\n label: translate('eudr.mitigationActions.actions.delete'),\n destructive: true,\n onSelect: () => {\n void handleDelete(row)\n },\n },\n ]}\n />\n )}\n emptyState={(\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={translate('eudr.mitigationActions.empty')}\n />\n )}\n perspective={{ tableId: 'eudr.risk_assessments.detail.mitigation_actions' }}\n disableRowClick\n stickyActionsColumn\n />\n\n <Dialog open={dialogMode !== null} onOpenChange={(open) => {\n if (!open) closeDialog()\n }}>\n <DialogContent size=\"lg\">\n <DialogHeader>\n <DialogTitle>\n {dialogMode === 'edit'\n ? translate('eudr.mitigationActions.editTitle')\n : translate('eudr.mitigationActions.createTitle')}\n </DialogTitle>\n </DialogHeader>\n <CrudForm<MitigationActionFormValues>\n embedded\n title={dialogMode === 'edit'\n ? translate('eudr.mitigationActions.editTitle')\n : translate('eudr.mitigationActions.createTitle')}\n submitLabel={translate('eudr.mitigationActions.form.submit')}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={async (values) => {\n const title = optionalText(values.title)\n if (!title) {\n const message = translate('eudr.mitigationActions.form.titleRequired')\n throw createCrudFormError(message, { title: message })\n }\n const payload = {\n riskAssessmentId,\n actionType: optionalText(values.actionType) ?? 'request_documents',\n title,\n description: optionalText(values.description),\n status: optionalText(values.status) ?? 'planned',\n dueDate: optionalText(values.dueDate),\n notes: optionalText(values.notes),\n }\n if (dialogMode === 'edit' && editingRow) {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(editingRow.updatedAt),\n () => updateCrud('eudr/mitigation-actions', {\n id: editingRow.id,\n ...payload,\n }, {\n errorMessage: translate('eudr.mitigationActions.updateError'),\n }),\n )\n flash(translate('eudr.mitigationActions.updateSuccess'), 'success')\n } else {\n await createCrud('eudr/mitigation-actions', payload, {\n errorMessage: translate('eudr.mitigationActions.createError'),\n })\n flash(translate('eudr.mitigationActions.createSuccess'), 'success')\n }\n closeDialog()\n refreshRows()\n }}\n />\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </section>\n )\n}\n\nexport default MitigationActionsSection\n"],
5
- "mappings": ";AA0RQ,cAwBA,YAxBA;AAxRR,YAAY,WAAW;AACvB,SAAS,YAAY;AACrB,SAAS,WAAW,YAAY;AAChC,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAC3B,SAAS,wBAAwB;AACjC,SAAS,0BAA0B;AACnC,SAAS,aAAa;AACtB,SAAS,SAAS,mCAAmC;AACrD,SAAS,YAAY,YAAY,kBAAkB;AACnD,SAAS,iCAAiC;AAC1C,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AACtC,SAAS,gBAAoD;AAC7D,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAE5B;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAuCP,SAAS,aAAa,OAA+B;AACnD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,UAAU;AACpC;AAEA,SAAS,WAAW,OAAkC,YAAoB,QAAwB;AAChG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AACzC,SAAO,KAAK,mBAAmB,UAAU,MAAS;AACpD;AAEA,SAAS,gBAAgB,OAA0C;AACjE,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,MAAM,MAAM,GAAG,EAAE;AAC1B;AAEA,SAAS,UAAU,KAAmC;AACpD,MAAI,CAAC,IAAI,WAAW,IAAI,WAAW,YAAa,QAAO;AACvD,QAAM,OAAO,IAAI,KAAK,IAAI,OAAO;AACjC,SAAO,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI;AACpE;AAEA,SAAS,cAAc,QAAmE;AACxF,MAAI,WAAW,cAAe,QAAO;AACrC,MAAI,WAAW,YAAa,QAAO;AACnC,SAAO;AACT;AAEA,SAAS,kBAAkB,WAAoC;AAC7D,SAAO,sBAAsB,IAAI,CAAC,UAAU;AAAA,IAC1C,OAAO;AAAA,IACP,OAAO,UAAU,uBAAuB,IAAI,EAAE;AAAA,EAChD,EAAE;AACJ;AAEA,SAAS,oBAAoB,WAAoC;AAC/D,SAAO,yBAAyB,IAAI,CAAC,YAAY;AAAA,IAC/C,OAAO;AAAA,IACP,OAAO,UAAU,yBAAyB,MAAM,EAAE;AAAA,EACpD,EAAE;AACJ;AAEO,SAAS,yBAAyB;AAAA,EACvC;AACF,GAAkC;AAChC,QAAM,YAAY,KAAK;AACvB,QAAM,SAAS,UAAU;AACzB,QAAM,EAAE,SAAS,qBAAqB,IAAI,iBAAiB;AAC3D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAgC,CAAC,CAAC;AAChE,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAC5D,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAmC,IAAI;AACjF,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAqC,IAAI;AACnF,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,CAAC;AACtD,QAAM,oBAAoB,2BAA2B,gBAAgB;AACrE,QAAM,EAAE,aAAa,kBAAkB,IAAI,mBAAoC;AAAA,IAC7E,WAAW;AAAA,IACX,gBAAgB,UAAU,4BAA4B;AAAA,EACxD,CAAC;AAED,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,WAAW;AACxB,iBAAW,IAAI;AACf,eAAS,IAAI;AACb,UAAI;AACF,cAAM,OAAO,MAAM;AAAA,UACjB,iDAAiD,mBAAmB,gBAAgB,CAAC;AAAA,UACrF;AAAA,UACA,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,QAC5B;AACA,YAAI,CAAC,KAAK,IAAI;AACZ,cAAI,CAAC,UAAW,UAAS,UAAU,kCAAkC,CAAC;AACtE;AAAA,QACF;AACA,YAAI,CAAC,UAAW,SAAQ,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,OAAO,QAAQ,CAAC,CAAC;AAAA,MACpF,QAAQ;AACN,YAAI,CAAC,UAAW,UAAS,UAAU,kCAAkC,CAAC;AAAA,MACxE,UAAE;AACA,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC;AAAA,IACF;AACA,aAAS;AACT,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,aAAa,kBAAkB,SAAS,CAAC;AAE7C,QAAM,cAAc,MAAM,YAAY,MAAM;AAC1C,mBAAe,CAAC,iBAAiB,eAAe,CAAC;AAAA,EACnD,GAAG,CAAC,CAAC;AAEL,QAAM,mBAAmB,MAAM,YAAY,MAAM;AAC/C,kBAAc,IAAI;AAClB,kBAAc,QAAQ;AAAA,EACxB,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAiB,MAAM,YAAY,CAAC,QAA6B;AACrE,kBAAc,GAAG;AACjB,kBAAc,MAAM;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,QAAM,cAAc,MAAM,YAAY,MAAM;AAC1C,kBAAc,IAAI;AAClB,kBAAc,IAAI;AAAA,EACpB,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,MAAM,YAAY,OAAO,QAA6B;AACzE,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B,OAAO,UAAU,wCAAwC,EAAE,OAAO,IAAI,MAAM,CAAC;AAAA,MAC7E,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAW;AAEhB,QAAI;AACF,YAAM,YAAY;AAAA,QAChB,WAAW,MAAM;AAAA,UACf,0BAA0B,IAAI,SAAS;AAAA,UACvC,MAAM,WAAW,2BAA2B,IAAI,IAAI;AAAA,YAClD,cAAc,UAAU,oCAAoC;AAAA,UAC9D,CAAC;AAAA,QACH;AAAA,QACA,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,cAAc;AAAA,UACd,YAAY,IAAI;AAAA,UAChB;AAAA,QACF;AAAA,QACA,iBAAiB,EAAE,IAAI,IAAI,GAAG;AAAA,MAChC,CAAC;AACD,YAAM,UAAU,sCAAsC,GAAG,SAAS;AAClE,kBAAY;AAAA,IACd,SAAS,aAAa;AACpB,UAAI,sBAAsB,aAAa,WAAW,EAAE,WAAW,YAAY,CAAC,EAAG;AAC/E,YAAM,UAAU,oCAAoC,GAAG,OAAO;AAAA,IAChE;AAAA,EACF,GAAG,CAAC,SAAS,mBAAmB,aAAa,mBAAmB,aAAa,SAAS,CAAC;AAEvF,QAAM,SAAS,MAAM,QAAqB,MAAM;AAAA,IAC9C;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,wCAAwC;AAAA,MACzD,MAAM;AAAA,MACN,SAAS,kBAAkB,SAAS;AAAA,IACtC;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,mCAAmC;AAAA,MACpD,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,yCAAyC;AAAA,MAC1D,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,oCAAoC;AAAA,MACrD,MAAM;AAAA,MACN,SAAS,oBAAoB,SAAS;AAAA,IACxC;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,qCAAqC;AAAA,MACtD,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,mCAAmC;AAAA,MACpD,MAAM;AAAA,IACR;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,SAAS,MAAM,QAAyB,MAAM;AAAA,IAClD;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,UAAU,qCAAqC;AAAA,MACtD,QAAQ;AAAA,MACR,QAAQ,CAAC,cAAc,SAAS,eAAe,UAAU,WAAW,OAAO;AAAA,IAC7E;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,gBAAgB,MAAM,QAAoC,OAAO;AAAA,IACrE,YAAY,YAAY,cAAc;AAAA,IACtC,OAAO,YAAY,SAAS;AAAA,IAC5B,aAAa,YAAY,eAAe;AAAA,IACxC,QAAQ,YAAY,UAAU;AAAA,IAC9B,SAAS,gBAAgB,YAAY,OAAO;AAAA,IAC5C,OAAO,YAAY,SAAS;AAAA,EAC9B,IAAI,CAAC,UAAU,CAAC;AAEhB,QAAM,UAAU,MAAM,QAA0C,MAAM;AAAA,IACpE;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,sCAAsC;AAAA,MACxD,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS;AAAA,MAChC,MAAM,EAAE,UAAU,SAAS,UAAU,KAAK;AAAA,IAC5C;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,qCAAqC;AAAA,MACvD,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,aAC5B,UAAU,uBAAuB,IAAI,SAAS,UAAU,EAAE,IAC1D,UAAU,mBAAmB;AAAA,IACnC;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,uCAAuC;AAAA,MACzD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,eAAY,SAAS,cAAc,IAAI,SAAS,MAAM,GAAG,KAAG,MAC1D,cAAI,SAAS,SAAS,UAAU,yBAAyB,IAAI,SAAS,MAAM,EAAE,IAAI,UAAU,mBAAmB,GAClH;AAAA,IAEJ;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,wCAAwC;AAAA,MAC1D,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAW,UAAU,IAAI,QAAQ,IAAI,6BAA6B,QACrE,qBAAW,IAAI,SAAS,SAAS,UAAU,mBAAmB,GAAG,MAAM,GAC1E;AAAA,IAEJ;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,UAAU,4CAA4C;AAAA,MAC9D,MAAM,CAAC,EAAE,IAAI,MAAM,WAAW,IAAI,SAAS,aAAa,UAAU,mBAAmB,GAAG,MAAM;AAAA,IAChG;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,SACE,qBAAC,aAAQ,WAAU,yDACjB;AAAA,yBAAC,SAAI,WAAU,qEACb;AAAA,2BAAC,SAAI,WAAU,aACb;AAAA,4BAAC,QAAG,WAAU,yBAAyB,oBAAU,8BAA8B,GAAE;AAAA,QACjF,oBAAC,OAAE,WAAU,iCAAiC,oBAAU,oCAAoC,GAAE;AAAA,SAChG;AAAA,MACA,qBAAC,UAAO,MAAK,UAAS,SAAS,kBAC7B;AAAA,4BAAC,QAAK,WAAU,UAAS,eAAY,QAAO;AAAA,QAC3C,UAAU,oCAAoC;AAAA,SACjD;AAAA,OACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,UAAU,mCAAmC;AAAA,QACpD;AAAA,QACA,MAAM;AAAA,QACN,WAAW;AAAA,QACX;AAAA,QACA,YAAY,CAAC,QACX;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL;AAAA,gBACE,IAAI;AAAA,gBACJ,OAAO,UAAU,qCAAqC;AAAA,gBACtD,UAAU,MAAM,eAAe,GAAG;AAAA,cACpC;AAAA,cACA;AAAA,gBACE,IAAI;AAAA,gBACJ,OAAO,UAAU,uCAAuC;AAAA,gBACxD,aAAa;AAAA,gBACb,UAAU,MAAM;AACd,uBAAK,aAAa,GAAG;AAAA,gBACvB;AAAA,cACF;AAAA,YACF;AAAA;AAAA,QACF;AAAA,QAEF,YACE;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,OAAO,UAAU,8BAA8B;AAAA;AAAA,QACjD;AAAA,QAEF,aAAa,EAAE,SAAS,kDAAkD;AAAA,QAC1E,iBAAe;AAAA,QACf,qBAAmB;AAAA;AAAA,IACrB;AAAA,IAEA,oBAAC,UAAO,MAAM,eAAe,MAAM,cAAc,CAAC,SAAS;AACzD,UAAI,CAAC,KAAM,aAAY;AAAA,IACzB,GACE,+BAAC,iBAAc,MAAK,MAClB;AAAA,0BAAC,gBACC,8BAAC,eACE,yBAAe,SACZ,UAAU,kCAAkC,IAC5C,UAAU,oCAAoC,GACpD,GACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,UAAQ;AAAA,UACR,OAAO,eAAe,SAClB,UAAU,kCAAkC,IAC5C,UAAU,oCAAoC;AAAA,UAClD,aAAa,UAAU,oCAAoC;AAAA,UAC3D;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,OAAO,WAAW;AAC1B,kBAAM,QAAQ,aAAa,OAAO,KAAK;AACvC,gBAAI,CAAC,OAAO;AACV,oBAAM,UAAU,UAAU,2CAA2C;AACrE,oBAAM,oBAAoB,SAAS,EAAE,OAAO,QAAQ,CAAC;AAAA,YACvD;AACA,kBAAM,UAAU;AAAA,cACd;AAAA,cACA,YAAY,aAAa,OAAO,UAAU,KAAK;AAAA,cAC/C;AAAA,cACA,aAAa,aAAa,OAAO,WAAW;AAAA,cAC5C,QAAQ,aAAa,OAAO,MAAM,KAAK;AAAA,cACvC,SAAS,aAAa,OAAO,OAAO;AAAA,cACpC,OAAO,aAAa,OAAO,KAAK;AAAA,YAClC;AACA,gBAAI,eAAe,UAAU,YAAY;AACvC,oBAAM;AAAA,gBACJ,0BAA0B,WAAW,SAAS;AAAA,gBAC9C,MAAM,WAAW,2BAA2B;AAAA,kBAC1C,IAAI,WAAW;AAAA,kBACf,GAAG;AAAA,gBACL,GAAG;AAAA,kBACD,cAAc,UAAU,oCAAoC;AAAA,gBAC9D,CAAC;AAAA,cACH;AACA,oBAAM,UAAU,sCAAsC,GAAG,SAAS;AAAA,YACpE,OAAO;AACL,oBAAM,WAAW,2BAA2B,SAAS;AAAA,gBACnD,cAAc,UAAU,oCAAoC;AAAA,cAC9D,CAAC;AACD,oBAAM,UAAU,sCAAsC,GAAG,SAAS;AAAA,YACpE;AACA,wBAAY;AACZ,wBAAY;AAAA,UACd;AAAA;AAAA,MACF;AAAA,OACF,GACF;AAAA,IACC;AAAA,KACH;AAEJ;AAEA,IAAO,mCAAQ;",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Plus } from 'lucide-react'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrud, deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport {\n EUDR_MITIGATION_STATUSES,\n EUDR_MITIGATION_TYPES,\n type EudrMitigationStatus,\n type EudrMitigationType,\n} from '../data/validators'\n\ntype MitigationActionRow = {\n id: string\n riskAssessmentId: string\n actionType: EudrMitigationType | null\n title: string\n description: string | null\n status: EudrMitigationStatus | null\n dueDate: string | null\n completedAt: string | null\n notes: string | null\n updatedAt: string\n}\n\ntype MitigationActionsResponse = {\n items?: MitigationActionRow[]\n}\n\ntype MitigationActionFormValues = {\n actionType: string\n title: string\n description: string\n status: string\n dueDate: string\n notes: string\n} & Record<string, unknown>\n\ntype MutationContext = {\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n}\n\nexport type MitigationActionsSectionProps = {\n riskAssessmentId: string\n}\n\nfunction optionalText(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length ? trimmed : null\n}\n\nfunction formatDate(value: string | null | undefined, emptyLabel: string, locale: string): string {\n if (!value) return emptyLabel\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return emptyLabel\n return date.toLocaleDateString(locale || undefined)\n}\n\nfunction formatDateInput(value: string | null | undefined): string {\n if (!value) return ''\n return value.slice(0, 10)\n}\n\nfunction isOverdue(row: MitigationActionRow): boolean {\n if (!row.dueDate || row.status === 'completed') return false\n const date = new Date(row.dueDate)\n return !Number.isNaN(date.getTime()) && date.getTime() < Date.now()\n}\n\nfunction statusVariant(status: string | null | undefined): 'neutral' | 'info' | 'success' {\n if (status === 'in_progress') return 'info'\n if (status === 'completed') return 'success'\n return 'neutral'\n}\n\nfunction actionTypeOptions(translate: ReturnType<typeof useT>) {\n return EUDR_MITIGATION_TYPES.map((type) => ({\n value: type,\n label: translate(`eudr.mitigationType.${type}`),\n }))\n}\n\nfunction actionStatusOptions(translate: ReturnType<typeof useT>) {\n return EUDR_MITIGATION_STATUSES.map((status) => ({\n value: status,\n label: translate(`eudr.mitigationStatus.${status}`),\n }))\n}\n\nexport function MitigationActionsSection({\n riskAssessmentId,\n}: MitigationActionsSectionProps) {\n const translate = useT()\n const locale = useLocale()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<MitigationActionRow[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [dialogMode, setDialogMode] = React.useState<'create' | 'edit' | null>(null)\n const [editingRow, setEditingRow] = React.useState<MitigationActionRow | null>(null)\n const [reloadToken, setReloadToken] = React.useState(0)\n const mutationContextId = `eudr-mitigation-actions:${riskAssessmentId}`\n const { runMutation, retryLastMutation } = useGuardedMutation<MutationContext>({\n contextId: mutationContextId,\n blockedMessage: translate('ui.forms.flash.saveBlocked'),\n })\n\n React.useEffect(() => {\n let cancelled = false\n async function loadRows() {\n setLoading(true)\n setError(null)\n try {\n const call = await apiCall<MitigationActionsResponse>(\n `/api/eudr/mitigation-actions?riskAssessmentId=${encodeURIComponent(riskAssessmentId)}&pageSize=100&sortField=dueDate&sortDir=asc`,\n undefined,\n { fallback: { items: [] } },\n )\n if (!call.ok) {\n if (!cancelled) setError(translate('eudr.mitigationActions.loadError'))\n return\n }\n if (!cancelled) setRows(Array.isArray(call.result?.items) ? call.result.items : [])\n } catch {\n if (!cancelled) setError(translate('eudr.mitigationActions.loadError'))\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n loadRows()\n return () => {\n cancelled = true\n }\n }, [reloadToken, riskAssessmentId, translate])\n\n const refreshRows = React.useCallback(() => {\n setReloadToken((currentToken) => currentToken + 1)\n }, [])\n\n const openCreateDialog = React.useCallback(() => {\n setEditingRow(null)\n setDialogMode('create')\n }, [])\n\n const openEditDialog = React.useCallback((row: MitigationActionRow) => {\n setEditingRow(row)\n setDialogMode('edit')\n }, [])\n\n const closeDialog = React.useCallback(() => {\n setDialogMode(null)\n setEditingRow(null)\n }, [])\n\n const handleDelete = React.useCallback(async (row: MitigationActionRow) => {\n const confirmed = await confirm({\n title: translate('eudr.mitigationActions.confirmDelete', { title: row.title }),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n try {\n await runMutation({\n operation: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(row.updatedAt),\n () => deleteCrud('eudr/mitigation-actions', row.id, {\n errorMessage: translate('eudr.mitigationActions.deleteError'),\n }),\n ),\n context: {\n formId: mutationContextId,\n resourceKind: 'eudr.mitigation_action',\n resourceId: row.id,\n retryLastMutation,\n },\n mutationPayload: { id: row.id },\n })\n flash(translate('eudr.mitigationActions.deleteSuccess'), 'success')\n refreshRows()\n } catch (deleteError) {\n if (surfaceRecordConflict(deleteError, translate, { onRefresh: refreshRows })) return\n flash(translate('eudr.mitigationActions.deleteError'), 'error')\n }\n }, [confirm, mutationContextId, refreshRows, retryLastMutation, runMutation, translate])\n\n const fields = React.useMemo<CrudField[]>(() => [\n {\n id: 'actionType',\n label: translate('eudr.mitigationActions.form.actionType'),\n type: 'select',\n options: actionTypeOptions(translate),\n },\n {\n id: 'title',\n label: translate('eudr.mitigationActions.form.title'),\n type: 'text',\n required: true,\n },\n {\n id: 'description',\n label: translate('eudr.mitigationActions.form.description'),\n type: 'textarea',\n },\n {\n id: 'status',\n label: translate('eudr.mitigationActions.form.status'),\n type: 'select',\n options: actionStatusOptions(translate),\n },\n {\n id: 'dueDate',\n label: translate('eudr.mitigationActions.form.dueDate'),\n type: 'date',\n },\n {\n id: 'notes',\n label: translate('eudr.mitigationActions.form.notes'),\n type: 'textarea',\n },\n ], [translate])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => [\n {\n id: 'details',\n title: translate('eudr.mitigationActions.form.details'),\n column: 1,\n fields: ['actionType', 'title', 'description', 'status', 'dueDate', 'notes'],\n },\n ], [translate])\n\n const initialValues = React.useMemo<MitigationActionFormValues>(() => ({\n actionType: editingRow?.actionType ?? 'request_documents',\n title: editingRow?.title ?? '',\n description: editingRow?.description ?? '',\n status: editingRow?.status ?? 'planned',\n dueDate: formatDateInput(editingRow?.dueDate),\n notes: editingRow?.notes ?? '',\n }), [editingRow])\n\n const columns = React.useMemo<ColumnDef<MitigationActionRow>[]>(() => [\n {\n accessorKey: 'title',\n header: translate('eudr.mitigationActions.columns.title'),\n cell: ({ row }) => row.original.title,\n meta: { maxWidth: '260px', truncate: true },\n },\n {\n accessorKey: 'actionType',\n header: translate('eudr.mitigationActions.columns.type'),\n cell: ({ row }) => row.original.actionType\n ? translate(`eudr.mitigationType.${row.original.actionType}`)\n : translate('eudr.common.empty'),\n },\n {\n accessorKey: 'status',\n header: translate('eudr.mitigationActions.columns.status'),\n cell: ({ row }) => (\n <StatusBadge variant={statusVariant(row.original.status)} dot>\n {row.original.status ? translate(`eudr.mitigationStatus.${row.original.status}`) : translate('eudr.common.empty')}\n </StatusBadge>\n ),\n },\n {\n accessorKey: 'dueDate',\n header: translate('eudr.mitigationActions.columns.dueDate'),\n cell: ({ row }) => (\n <span className={isOverdue(row.original) ? 'text-status-warning-text' : undefined}>\n {formatDate(row.original.dueDate, translate('eudr.common.empty'), locale)}\n </span>\n ),\n },\n {\n accessorKey: 'completedAt',\n header: translate('eudr.mitigationActions.columns.completedAt'),\n cell: ({ row }) => formatDate(row.original.completedAt, translate('eudr.common.empty'), locale),\n },\n ], [locale, translate])\n\n return (\n <section className=\"space-y-4 rounded-lg border border-border bg-card p-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold\">{translate('eudr.mitigationActions.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">{translate('eudr.mitigationActions.description')}</p>\n </div>\n <Button type=\"button\" onClick={openCreateDialog}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('eudr.mitigationActions.actions.add')}\n </Button>\n </div>\n\n <DataTable<MitigationActionRow>\n title={translate('eudr.mitigationActions.tableTitle')}\n titleHeadingLevel={2}\n columns={columns}\n data={rows}\n isLoading={loading}\n error={error}\n rowActions={(row) => (\n <RowActions\n items={[\n {\n id: 'edit',\n label: translate('eudr.mitigationActions.actions.edit'),\n onSelect: () => openEditDialog(row),\n },\n {\n id: 'delete',\n label: translate('eudr.mitigationActions.actions.delete'),\n destructive: true,\n onSelect: () => {\n void handleDelete(row)\n },\n },\n ]}\n />\n )}\n emptyState={(\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={translate('eudr.mitigationActions.empty')}\n />\n )}\n perspective={{ tableId: 'eudr.risk_assessments.detail.mitigation_actions' }}\n disableRowClick\n stickyActionsColumn\n />\n\n <Dialog open={dialogMode !== null} onOpenChange={(open) => {\n if (!open) closeDialog()\n }}>\n <DialogContent size=\"lg\">\n <DialogHeader>\n <DialogTitle>\n {dialogMode === 'edit'\n ? translate('eudr.mitigationActions.editTitle')\n : translate('eudr.mitigationActions.createTitle')}\n </DialogTitle>\n </DialogHeader>\n <CrudForm<MitigationActionFormValues>\n embedded\n title={dialogMode === 'edit'\n ? translate('eudr.mitigationActions.editTitle')\n : translate('eudr.mitigationActions.createTitle')}\n submitLabel={translate('eudr.mitigationActions.form.submit')}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={async (values) => {\n const title = optionalText(values.title)\n if (!title) {\n const message = translate('eudr.mitigationActions.form.titleRequired')\n throw createCrudFormError(message, { title: message })\n }\n const payload = {\n riskAssessmentId,\n actionType: optionalText(values.actionType) ?? 'request_documents',\n title,\n description: optionalText(values.description),\n status: optionalText(values.status) ?? 'planned',\n dueDate: optionalText(values.dueDate),\n notes: optionalText(values.notes),\n }\n if (dialogMode === 'edit' && editingRow) {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(editingRow.updatedAt),\n () => updateCrud('eudr/mitigation-actions', {\n id: editingRow.id,\n ...payload,\n }, {\n errorMessage: translate('eudr.mitigationActions.updateError'),\n }),\n )\n flash(translate('eudr.mitigationActions.updateSuccess'), 'success')\n } else {\n await createCrud('eudr/mitigation-actions', payload, {\n errorMessage: translate('eudr.mitigationActions.createError'),\n })\n flash(translate('eudr.mitigationActions.createSuccess'), 'success')\n }\n closeDialog()\n refreshRows()\n }}\n />\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </section>\n )\n}\n\nexport default MitigationActionsSection\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -151,6 +151,7 @@ function StatementRiskSection({
151
151
  DataTable,
152
152
  {
153
153
  title: translate("eudr.risk.history.title"),
154
+ titleHeadingLevel: 2,
154
155
  columns: historyColumns,
155
156
  data: historyRows,
156
157
  isLoading: historyLoading,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/eudr/components/StatementRiskSection.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { AlertTriangle, ArrowRight, ShieldCheck } from 'lucide-react'\nimport { resolveCountryName } from '@open-mercato/shared/lib/location/countries'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type {\n EudrRiskConclusion,\n EudrRiskTier,\n} from '../data/validators'\n\nexport type CountryRiskView = {\n country: string\n tier: string\n}\n\nexport type StatementLatestRisk = {\n id?: string | null\n conclusion: EudrRiskConclusion\n overallTier: EudrRiskTier\n reviewDueAt: string | null\n countryRisks?: CountryRiskView[]\n} | null\n\ntype RiskHistoryRow = {\n id: string\n conclusion: EudrRiskConclusion\n overallTier: EudrRiskTier\n assessedAt: string | null\n reviewDueAt: string | null\n}\n\ntype RiskHistoryResponse = {\n items?: RiskHistoryRow[]\n}\n\nexport type StatementRiskSectionProps = {\n statementId: string\n latestRisk: StatementLatestRisk\n onAssess?: () => void\n}\n\nexport function riskTierBadgeVariant(tier: string | null | undefined): 'success' | 'warning' | 'error' | 'info' | 'neutral' {\n if (tier === 'low') return 'success'\n if (tier === 'high') return 'error'\n if (tier === 'mixed') return 'warning'\n if (tier === 'standard') return 'info'\n return 'neutral'\n}\n\nexport function riskConclusionBadgeVariant(conclusion: string | null | undefined): 'success' | 'warning' | 'neutral' {\n if (conclusion === 'negligible') return 'success'\n if (conclusion === 'non_negligible') return 'warning'\n return 'neutral'\n}\n\nfunction formatDate(value: string | null | undefined, emptyLabel: string, locale: string): string {\n if (!value) return emptyLabel\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return emptyLabel\n return date.toLocaleDateString(locale || undefined)\n}\n\nfunction isOverdue(value: string | null | undefined): boolean {\n if (!value) return false\n const date = new Date(value)\n return !Number.isNaN(date.getTime()) && date.getTime() < Date.now()\n}\n\nfunction normalizeHistoryRow(raw: RiskHistoryRow): RiskHistoryRow {\n return {\n id: raw.id,\n conclusion: raw.conclusion,\n overallTier: raw.overallTier,\n assessedAt: raw.assessedAt ?? null,\n reviewDueAt: raw.reviewDueAt ?? null,\n }\n}\n\nexport function StatementRiskSection({\n statementId,\n latestRisk,\n onAssess,\n}: StatementRiskSectionProps) {\n const translate = useT()\n const locale = useLocale()\n const [historyRows, setHistoryRows] = React.useState<RiskHistoryRow[]>([])\n const [historyLoading, setHistoryLoading] = React.useState(false)\n const [historyError, setHistoryError] = React.useState<string | null>(null)\n const assessHref = `/backend/eudr/risk-assessments/create?statementId=${encodeURIComponent(statementId)}`\n const latestRiskId = latestRisk?.id ?? historyRows[0]?.id ?? null\n\n React.useEffect(() => {\n let cancelled = false\n async function loadHistory() {\n setHistoryLoading(true)\n setHistoryError(null)\n try {\n const call = await apiCall<RiskHistoryResponse>(\n `/api/eudr/risk-assessments?statementId=${encodeURIComponent(statementId)}&pageSize=5&sortField=assessedAt&sortDir=desc`,\n undefined,\n { fallback: { items: [] } },\n )\n if (!call.ok) {\n if (!cancelled) setHistoryError(translate('eudr.risk.history.loadError'))\n return\n }\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n if (!cancelled) setHistoryRows(items.map(normalizeHistoryRow))\n } catch {\n if (!cancelled) setHistoryError(translate('eudr.risk.history.loadError'))\n } finally {\n if (!cancelled) setHistoryLoading(false)\n }\n }\n loadHistory()\n return () => {\n cancelled = true\n }\n }, [statementId, translate])\n\n const historyColumns = React.useMemo<ColumnDef<RiskHistoryRow>[]>(() => [\n {\n accessorKey: 'assessedAt',\n header: translate('eudr.risk.history.columns.assessedAt'),\n cell: ({ row }) => formatDate(row.original.assessedAt, translate('eudr.common.empty'), locale),\n },\n {\n accessorKey: 'conclusion',\n header: translate('eudr.risk.history.columns.conclusion'),\n cell: ({ row }) => (\n <StatusBadge variant={riskConclusionBadgeVariant(row.original.conclusion)}>\n {translate(`eudr.conclusion.${row.original.conclusion}`)}\n </StatusBadge>\n ),\n },\n {\n accessorKey: 'overallTier',\n header: translate('eudr.risk.history.columns.overallTier'),\n cell: ({ row }) => (\n <StatusBadge variant={riskTierBadgeVariant(row.original.overallTier)}>\n {translate(`eudr.riskTier.${row.original.overallTier}`)}\n </StatusBadge>\n ),\n },\n ], [locale, translate])\n\n return (\n <section className=\"space-y-4 rounded-lg border border-border bg-card p-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold\">{translate('eudr.risk.statementSection.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">{translate('eudr.risk.statementSection.description')}</p>\n </div>\n <Button asChild>\n <Link href={assessHref} onClick={onAssess}>\n <ShieldCheck className=\"size-4\" aria-hidden=\"true\" />\n {latestRisk ? translate('eudr.risk.statementSection.reassess') : translate('eudr.risk.statementSection.assess')}\n </Link>\n </Button>\n </div>\n\n {!latestRisk ? (\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={translate('eudr.risk.statementSection.emptyTitle')}\n description={translate('eudr.risk.statementSection.emptyDescription')}\n />\n ) : (\n <div className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge variant={riskConclusionBadgeVariant(latestRisk.conclusion)} dot>\n {translate(`eudr.conclusion.${latestRisk.conclusion}`)}\n </StatusBadge>\n <StatusBadge variant={riskTierBadgeVariant(latestRisk.overallTier)}>\n {translate(`eudr.riskTier.${latestRisk.overallTier}`)}\n </StatusBadge>\n {isOverdue(latestRisk.reviewDueAt) ? (\n <StatusBadge variant=\"warning\">\n <AlertTriangle className=\"size-3.5\" aria-hidden=\"true\" />\n {translate('eudr.risk.reviewOverdue')}\n </StatusBadge>\n ) : null}\n <span className=\"text-sm text-muted-foreground\">\n {translate('eudr.risk.reviewDueAt', {\n date: formatDate(latestRisk.reviewDueAt, translate('eudr.common.empty'), locale),\n })}\n </span>\n </div>\n {Array.isArray(latestRisk.countryRisks) && latestRisk.countryRisks.length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {latestRisk.countryRisks.map((risk) => (\n <StatusBadge key={`${risk.country}:${risk.tier}`} variant={riskTierBadgeVariant(risk.tier)}>\n {resolveCountryName(risk.country, { locale })} ({translate(`eudr.riskTier.${risk.tier}`)})\n </StatusBadge>\n ))}\n </div>\n ) : null}\n {latestRiskId ? (\n <div className=\"flex flex-wrap items-center gap-3 text-sm\">\n <Link href={`/backend/eudr/risk-assessments/${latestRiskId}`} className=\"inline-flex items-center gap-1 font-medium hover:underline\">\n {translate('eudr.risk.statementSection.viewAssessment')}\n <ArrowRight className=\"size-3.5\" aria-hidden=\"true\" />\n </Link>\n <Link href={assessHref} onClick={onAssess} className=\"inline-flex items-center gap-1 font-medium hover:underline\">\n {translate('eudr.risk.statementSection.reassess')}\n <ArrowRight className=\"size-3.5\" aria-hidden=\"true\" />\n </Link>\n </div>\n ) : null}\n </div>\n )}\n\n <DataTable<RiskHistoryRow>\n title={translate('eudr.risk.history.title')}\n columns={historyColumns}\n data={historyRows}\n isLoading={historyLoading}\n error={historyError}\n emptyState={(\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={translate('eudr.risk.history.empty')}\n />\n )}\n perspective={{ tableId: 'eudr.statements.detail.risk_history' }}\n disableRowClick\n />\n </section>\n )\n}\n\nexport default StatementRiskSection\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { AlertTriangle, ArrowRight, ShieldCheck } from 'lucide-react'\nimport { resolveCountryName } from '@open-mercato/shared/lib/location/countries'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type {\n EudrRiskConclusion,\n EudrRiskTier,\n} from '../data/validators'\n\nexport type CountryRiskView = {\n country: string\n tier: string\n}\n\nexport type StatementLatestRisk = {\n id?: string | null\n conclusion: EudrRiskConclusion\n overallTier: EudrRiskTier\n reviewDueAt: string | null\n countryRisks?: CountryRiskView[]\n} | null\n\ntype RiskHistoryRow = {\n id: string\n conclusion: EudrRiskConclusion\n overallTier: EudrRiskTier\n assessedAt: string | null\n reviewDueAt: string | null\n}\n\ntype RiskHistoryResponse = {\n items?: RiskHistoryRow[]\n}\n\nexport type StatementRiskSectionProps = {\n statementId: string\n latestRisk: StatementLatestRisk\n onAssess?: () => void\n}\n\nexport function riskTierBadgeVariant(tier: string | null | undefined): 'success' | 'warning' | 'error' | 'info' | 'neutral' {\n if (tier === 'low') return 'success'\n if (tier === 'high') return 'error'\n if (tier === 'mixed') return 'warning'\n if (tier === 'standard') return 'info'\n return 'neutral'\n}\n\nexport function riskConclusionBadgeVariant(conclusion: string | null | undefined): 'success' | 'warning' | 'neutral' {\n if (conclusion === 'negligible') return 'success'\n if (conclusion === 'non_negligible') return 'warning'\n return 'neutral'\n}\n\nfunction formatDate(value: string | null | undefined, emptyLabel: string, locale: string): string {\n if (!value) return emptyLabel\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return emptyLabel\n return date.toLocaleDateString(locale || undefined)\n}\n\nfunction isOverdue(value: string | null | undefined): boolean {\n if (!value) return false\n const date = new Date(value)\n return !Number.isNaN(date.getTime()) && date.getTime() < Date.now()\n}\n\nfunction normalizeHistoryRow(raw: RiskHistoryRow): RiskHistoryRow {\n return {\n id: raw.id,\n conclusion: raw.conclusion,\n overallTier: raw.overallTier,\n assessedAt: raw.assessedAt ?? null,\n reviewDueAt: raw.reviewDueAt ?? null,\n }\n}\n\nexport function StatementRiskSection({\n statementId,\n latestRisk,\n onAssess,\n}: StatementRiskSectionProps) {\n const translate = useT()\n const locale = useLocale()\n const [historyRows, setHistoryRows] = React.useState<RiskHistoryRow[]>([])\n const [historyLoading, setHistoryLoading] = React.useState(false)\n const [historyError, setHistoryError] = React.useState<string | null>(null)\n const assessHref = `/backend/eudr/risk-assessments/create?statementId=${encodeURIComponent(statementId)}`\n const latestRiskId = latestRisk?.id ?? historyRows[0]?.id ?? null\n\n React.useEffect(() => {\n let cancelled = false\n async function loadHistory() {\n setHistoryLoading(true)\n setHistoryError(null)\n try {\n const call = await apiCall<RiskHistoryResponse>(\n `/api/eudr/risk-assessments?statementId=${encodeURIComponent(statementId)}&pageSize=5&sortField=assessedAt&sortDir=desc`,\n undefined,\n { fallback: { items: [] } },\n )\n if (!call.ok) {\n if (!cancelled) setHistoryError(translate('eudr.risk.history.loadError'))\n return\n }\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n if (!cancelled) setHistoryRows(items.map(normalizeHistoryRow))\n } catch {\n if (!cancelled) setHistoryError(translate('eudr.risk.history.loadError'))\n } finally {\n if (!cancelled) setHistoryLoading(false)\n }\n }\n loadHistory()\n return () => {\n cancelled = true\n }\n }, [statementId, translate])\n\n const historyColumns = React.useMemo<ColumnDef<RiskHistoryRow>[]>(() => [\n {\n accessorKey: 'assessedAt',\n header: translate('eudr.risk.history.columns.assessedAt'),\n cell: ({ row }) => formatDate(row.original.assessedAt, translate('eudr.common.empty'), locale),\n },\n {\n accessorKey: 'conclusion',\n header: translate('eudr.risk.history.columns.conclusion'),\n cell: ({ row }) => (\n <StatusBadge variant={riskConclusionBadgeVariant(row.original.conclusion)}>\n {translate(`eudr.conclusion.${row.original.conclusion}`)}\n </StatusBadge>\n ),\n },\n {\n accessorKey: 'overallTier',\n header: translate('eudr.risk.history.columns.overallTier'),\n cell: ({ row }) => (\n <StatusBadge variant={riskTierBadgeVariant(row.original.overallTier)}>\n {translate(`eudr.riskTier.${row.original.overallTier}`)}\n </StatusBadge>\n ),\n },\n ], [locale, translate])\n\n return (\n <section className=\"space-y-4 rounded-lg border border-border bg-card p-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold\">{translate('eudr.risk.statementSection.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">{translate('eudr.risk.statementSection.description')}</p>\n </div>\n <Button asChild>\n <Link href={assessHref} onClick={onAssess}>\n <ShieldCheck className=\"size-4\" aria-hidden=\"true\" />\n {latestRisk ? translate('eudr.risk.statementSection.reassess') : translate('eudr.risk.statementSection.assess')}\n </Link>\n </Button>\n </div>\n\n {!latestRisk ? (\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={translate('eudr.risk.statementSection.emptyTitle')}\n description={translate('eudr.risk.statementSection.emptyDescription')}\n />\n ) : (\n <div className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge variant={riskConclusionBadgeVariant(latestRisk.conclusion)} dot>\n {translate(`eudr.conclusion.${latestRisk.conclusion}`)}\n </StatusBadge>\n <StatusBadge variant={riskTierBadgeVariant(latestRisk.overallTier)}>\n {translate(`eudr.riskTier.${latestRisk.overallTier}`)}\n </StatusBadge>\n {isOverdue(latestRisk.reviewDueAt) ? (\n <StatusBadge variant=\"warning\">\n <AlertTriangle className=\"size-3.5\" aria-hidden=\"true\" />\n {translate('eudr.risk.reviewOverdue')}\n </StatusBadge>\n ) : null}\n <span className=\"text-sm text-muted-foreground\">\n {translate('eudr.risk.reviewDueAt', {\n date: formatDate(latestRisk.reviewDueAt, translate('eudr.common.empty'), locale),\n })}\n </span>\n </div>\n {Array.isArray(latestRisk.countryRisks) && latestRisk.countryRisks.length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {latestRisk.countryRisks.map((risk) => (\n <StatusBadge key={`${risk.country}:${risk.tier}`} variant={riskTierBadgeVariant(risk.tier)}>\n {resolveCountryName(risk.country, { locale })} ({translate(`eudr.riskTier.${risk.tier}`)})\n </StatusBadge>\n ))}\n </div>\n ) : null}\n {latestRiskId ? (\n <div className=\"flex flex-wrap items-center gap-3 text-sm\">\n <Link href={`/backend/eudr/risk-assessments/${latestRiskId}`} className=\"inline-flex items-center gap-1 font-medium hover:underline\">\n {translate('eudr.risk.statementSection.viewAssessment')}\n <ArrowRight className=\"size-3.5\" aria-hidden=\"true\" />\n </Link>\n <Link href={assessHref} onClick={onAssess} className=\"inline-flex items-center gap-1 font-medium hover:underline\">\n {translate('eudr.risk.statementSection.reassess')}\n <ArrowRight className=\"size-3.5\" aria-hidden=\"true\" />\n </Link>\n </div>\n ) : null}\n </div>\n )}\n\n <DataTable<RiskHistoryRow>\n title={translate('eudr.risk.history.title')}\n titleHeadingLevel={2}\n columns={historyColumns}\n data={historyRows}\n isLoading={historyLoading}\n error={historyError}\n emptyState={(\n <EmptyState\n size=\"sm\"\n variant=\"subtle\"\n title={translate('eudr.risk.history.empty')}\n />\n )}\n perspective={{ tableId: 'eudr.statements.detail.risk_history' }}\n disableRowClick\n />\n </section>\n )\n}\n\nexport default StatementRiskSection\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -34,6 +34,7 @@ function EditFeatureTogglePage({ params }) {
34
34
  CrudForm,
35
35
  {
36
36
  title: t("feature_toggles.form.title.edit", "Edit Feature Toggle"),
37
+ titleHeadingLevel: 1,
37
38
  backHref: "/backend/feature-toggles/global",
38
39
  versionHistory: { resourceKind: "feature_toggles.global", resourceId: id ? String(id) : "" },
39
40
  fields,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../src/modules/feature_toggles/backend/feature-toggles/global/%5Bid%5D/edit/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport { Page, PageBody } from \"@open-mercato/ui/backend/Page\";\nimport { CrudForm } from \"@open-mercato/ui/backend/CrudForm\";\nimport { ErrorMessage, LoadingMessage } from \"@open-mercato/ui/backend/detail\";\nimport { E } from \"#generated/entities.ids.generated\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport * as React from 'react'\nimport { updateCrud } from \"@open-mercato/ui/backend/utils/crud\";\nimport { useFeatureToggleItem } from \"@open-mercato/core/modules/feature_toggles/components/hooks/useFeatureToggleItem\";\nimport { createFieldDefinitions, createFormGroups } from \"@open-mercato/core/modules/feature_toggles/components/formConfig\";\n\n\nexport default function EditFeatureTogglePage({ params }: { params?: { id?: string } }) {\n const { id } = params ?? {}\n const t = useT()\n const fields = createFieldDefinitions(t);\n const formGroups = createFormGroups(t);\n\n const { data: featureToggleItem, isLoading, isError } = useFeatureToggleItem(id)\n\n // Derive the form's initial values synchronously from the loaded record. Using\n // a useState+useEffect here caused #2452: `isLoading` flips to false one render\n // before the effect set `initialValues`, so CrudForm mounted with `{}` and the\n // `type` SELECT captured an empty value (text inputs re-sync from the prop, the\n // select does not). Deriving here means the value is present in the same render\n // the data arrives; the `key` below also forces a clean remount on load.\n const initialValues = React.useMemo(() => {\n if (!featureToggleItem) return null\n return {\n id: featureToggleItem.id ?? (id ? String(id) : ''),\n identifier: featureToggleItem.identifier,\n name: featureToggleItem.name,\n description: featureToggleItem.description,\n category: featureToggleItem.category,\n type: featureToggleItem.type,\n defaultValue: featureToggleItem.defaultValue,\n }\n }, [featureToggleItem, id])\n\n // Gate the form on load. Mounting CrudForm with placeholder `{}` before the\n // record arrives makes the required `type` Select mount controlled with `''`,\n // then flip empty\u2192value asynchronously \u2014 a transition the Radix trigger fails\n // to re-derive, leaving Type blank and blocking save. Rendering CrudForm only\n // once the record is present mirrors the synchronous create flow, so the\n // Select mounts a single time with the stored value already set.\n if (!initialValues) {\n return (\n <Page>\n <PageBody>\n {isError && !isLoading ? (\n <ErrorMessage label={t('feature_toggles.form.errors.load', 'Failed to load feature toggle')} />\n ) : (\n <LoadingMessage label={t('feature_toggles.form.loading', 'Loading feature toggles')} />\n )}\n </PageBody>\n </Page>\n )\n }\n\n // record_locks scope decision (Phase 6): the global feature toggle is a\n // NON-TENANT, superadmin-only entity. record_locks enrichment (presence,\n // acquire/heartbeat, conflict upgrade) is tenant-scoped \u2014 its decorator skips\n // enrichment when no tenant/resource resolves \u2014 so a global (null-tenant) record\n // cannot participate in record_locks. This surface therefore stays OSS-floor\n // guarded ONLY: the CrudForm auto-derives the optimistic-lock header from\n // `optimisticLockUpdatedAt`, the route enforces it via the OSS floor, and a stale\n // save surfaces the unified conflict bar. No `backend:record:current` presence is\n // mounted: it would never resolve a tenant-scoped lock, and this is a\n // single-superadmin surface with no concurrent-editor expectation. Per-tenant\n // override values (`api/global/[id]/override`) ARE tenant-scoped and are enabled\n // in Phase 6b.\n return (\n <Page>\n <PageBody>\n <CrudForm\n key={initialValues ? 'ft-edit-loaded' : 'ft-edit-loading'}\n title={t('feature_toggles.form.title.edit', 'Edit Feature Toggle')}\n backHref=\"/backend/feature-toggles/global\"\n versionHistory={{ resourceKind: 'feature_toggles.global', resourceId: id ? String(id) : '' }}\n fields={fields}\n entityId={E.feature_toggles.feature_toggle}\n initialValues={initialValues}\n optimisticLockUpdatedAt={featureToggleItem?.updatedAt ?? null}\n isLoading={isLoading}\n groups={formGroups}\n loadingMessage={t('feature_toggles.form.loading', 'Loading feature toggles')}\n submitLabel={t('feature_toggles.form.action.save', 'Save')}\n cancelHref=\"/backend/feature-toggles/global\"\n successRedirect={`/backend/feature-toggles/global`}\n onSubmit={async (values) => {\n if (!id) return\n const payload = {\n id: id ? String(id) : '',\n identifier: values.identifier,\n name: values.name,\n description: values.description,\n category: values.category,\n\n type: values.type,\n defaultValue: values.defaultValue,\n }\n await updateCrud('feature_toggles/global', payload)\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": ";AAkDY;AAjDZ,SAAS,MAAM,gBAAgB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,cAAc,sBAAsB;AAC7C,SAAS,SAAS;AAClB,SAAS,YAAY;AACrB,YAAY,WAAW;AACvB,SAAS,kBAAkB;AAC3B,SAAS,4BAA4B;AACrC,SAAS,wBAAwB,wBAAwB;AAG1C,SAAR,sBAAuC,EAAE,OAAO,GAAiC;AACtF,QAAM,EAAE,GAAG,IAAI,UAAU,CAAC;AAC1B,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,uBAAuB,CAAC;AACvC,QAAM,aAAa,iBAAiB,CAAC;AAErC,QAAM,EAAE,MAAM,mBAAmB,WAAW,QAAQ,IAAI,qBAAqB,EAAE;AAQ/E,QAAM,gBAAgB,MAAM,QAAQ,MAAM;AACxC,QAAI,CAAC,kBAAmB,QAAO;AAC/B,WAAO;AAAA,MACL,IAAI,kBAAkB,OAAO,KAAK,OAAO,EAAE,IAAI;AAAA,MAC/C,YAAY,kBAAkB;AAAA,MAC9B,MAAM,kBAAkB;AAAA,MACxB,aAAa,kBAAkB;AAAA,MAC/B,UAAU,kBAAkB;AAAA,MAC5B,MAAM,kBAAkB;AAAA,MACxB,cAAc,kBAAkB;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,mBAAmB,EAAE,CAAC;AAQ1B,MAAI,CAAC,eAAe;AAClB,WACE,oBAAC,QACC,8BAAC,YACE,qBAAW,CAAC,YACX,oBAAC,gBAAa,OAAO,EAAE,oCAAoC,+BAA+B,GAAG,IAE7F,oBAAC,kBAAe,OAAO,EAAE,gCAAgC,yBAAyB,GAAG,GAEzF,GACF;AAAA,EAEJ;AAcA,SACE,oBAAC,QACC,8BAAC,YACC;AAAA,IAAC;AAAA;AAAA,MAEC,OAAO,EAAE,mCAAmC,qBAAqB;AAAA,MACjE,UAAS;AAAA,MACT,gBAAgB,EAAE,cAAc,0BAA0B,YAAY,KAAK,OAAO,EAAE,IAAI,GAAG;AAAA,MAC3F;AAAA,MACA,UAAU,EAAE,gBAAgB;AAAA,MAC5B;AAAA,MACA,yBAAyB,mBAAmB,aAAa;AAAA,MACzD;AAAA,MACA,QAAQ;AAAA,MACR,gBAAgB,EAAE,gCAAgC,yBAAyB;AAAA,MAC3E,aAAa,EAAE,oCAAoC,MAAM;AAAA,MACzD,YAAW;AAAA,MACX,iBAAiB;AAAA,MACjB,UAAU,OAAO,WAAW;AAC1B,YAAI,CAAC,GAAI;AACT,cAAM,UAAU;AAAA,UACd,IAAI,KAAK,OAAO,EAAE,IAAI;AAAA,UACtB,YAAY,OAAO;AAAA,UACnB,MAAM,OAAO;AAAA,UACb,aAAa,OAAO;AAAA,UACpB,UAAU,OAAO;AAAA,UAEjB,MAAM,OAAO;AAAA,UACb,cAAc,OAAO;AAAA,QACvB;AACA,cAAM,WAAW,0BAA0B,OAAO;AAAA,MACpD;AAAA;AAAA,IA3BK,gBAAgB,mBAAmB;AAAA,EA4B1C,GACF,GACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\"\nimport { Page, PageBody } from \"@open-mercato/ui/backend/Page\";\nimport { CrudForm } from \"@open-mercato/ui/backend/CrudForm\";\nimport { ErrorMessage, LoadingMessage } from \"@open-mercato/ui/backend/detail\";\nimport { E } from \"#generated/entities.ids.generated\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport * as React from 'react'\nimport { updateCrud } from \"@open-mercato/ui/backend/utils/crud\";\nimport { useFeatureToggleItem } from \"@open-mercato/core/modules/feature_toggles/components/hooks/useFeatureToggleItem\";\nimport { createFieldDefinitions, createFormGroups } from \"@open-mercato/core/modules/feature_toggles/components/formConfig\";\n\n\nexport default function EditFeatureTogglePage({ params }: { params?: { id?: string } }) {\n const { id } = params ?? {}\n const t = useT()\n const fields = createFieldDefinitions(t);\n const formGroups = createFormGroups(t);\n\n const { data: featureToggleItem, isLoading, isError } = useFeatureToggleItem(id)\n\n // Derive the form's initial values synchronously from the loaded record. Using\n // a useState+useEffect here caused #2452: `isLoading` flips to false one render\n // before the effect set `initialValues`, so CrudForm mounted with `{}` and the\n // `type` SELECT captured an empty value (text inputs re-sync from the prop, the\n // select does not). Deriving here means the value is present in the same render\n // the data arrives; the `key` below also forces a clean remount on load.\n const initialValues = React.useMemo(() => {\n if (!featureToggleItem) return null\n return {\n id: featureToggleItem.id ?? (id ? String(id) : ''),\n identifier: featureToggleItem.identifier,\n name: featureToggleItem.name,\n description: featureToggleItem.description,\n category: featureToggleItem.category,\n type: featureToggleItem.type,\n defaultValue: featureToggleItem.defaultValue,\n }\n }, [featureToggleItem, id])\n\n // Gate the form on load. Mounting CrudForm with placeholder `{}` before the\n // record arrives makes the required `type` Select mount controlled with `''`,\n // then flip empty\u2192value asynchronously \u2014 a transition the Radix trigger fails\n // to re-derive, leaving Type blank and blocking save. Rendering CrudForm only\n // once the record is present mirrors the synchronous create flow, so the\n // Select mounts a single time with the stored value already set.\n if (!initialValues) {\n return (\n <Page>\n <PageBody>\n {isError && !isLoading ? (\n <ErrorMessage label={t('feature_toggles.form.errors.load', 'Failed to load feature toggle')} />\n ) : (\n <LoadingMessage label={t('feature_toggles.form.loading', 'Loading feature toggles')} />\n )}\n </PageBody>\n </Page>\n )\n }\n\n // record_locks scope decision (Phase 6): the global feature toggle is a\n // NON-TENANT, superadmin-only entity. record_locks enrichment (presence,\n // acquire/heartbeat, conflict upgrade) is tenant-scoped \u2014 its decorator skips\n // enrichment when no tenant/resource resolves \u2014 so a global (null-tenant) record\n // cannot participate in record_locks. This surface therefore stays OSS-floor\n // guarded ONLY: the CrudForm auto-derives the optimistic-lock header from\n // `optimisticLockUpdatedAt`, the route enforces it via the OSS floor, and a stale\n // save surfaces the unified conflict bar. No `backend:record:current` presence is\n // mounted: it would never resolve a tenant-scoped lock, and this is a\n // single-superadmin surface with no concurrent-editor expectation. Per-tenant\n // override values (`api/global/[id]/override`) ARE tenant-scoped and are enabled\n // in Phase 6b.\n return (\n <Page>\n <PageBody>\n <CrudForm\n key={initialValues ? 'ft-edit-loaded' : 'ft-edit-loading'}\n title={t('feature_toggles.form.title.edit', 'Edit Feature Toggle')}\n titleHeadingLevel={1}\n backHref=\"/backend/feature-toggles/global\"\n versionHistory={{ resourceKind: 'feature_toggles.global', resourceId: id ? String(id) : '' }}\n fields={fields}\n entityId={E.feature_toggles.feature_toggle}\n initialValues={initialValues}\n optimisticLockUpdatedAt={featureToggleItem?.updatedAt ?? null}\n isLoading={isLoading}\n groups={formGroups}\n loadingMessage={t('feature_toggles.form.loading', 'Loading feature toggles')}\n submitLabel={t('feature_toggles.form.action.save', 'Save')}\n cancelHref=\"/backend/feature-toggles/global\"\n successRedirect={`/backend/feature-toggles/global`}\n onSubmit={async (values) => {\n if (!id) return\n const payload = {\n id: id ? String(id) : '',\n identifier: values.identifier,\n name: values.name,\n description: values.description,\n category: values.category,\n\n type: values.type,\n defaultValue: values.defaultValue,\n }\n await updateCrud('feature_toggles/global', payload)\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": ";AAkDY;AAjDZ,SAAS,MAAM,gBAAgB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,cAAc,sBAAsB;AAC7C,SAAS,SAAS;AAClB,SAAS,YAAY;AACrB,YAAY,WAAW;AACvB,SAAS,kBAAkB;AAC3B,SAAS,4BAA4B;AACrC,SAAS,wBAAwB,wBAAwB;AAG1C,SAAR,sBAAuC,EAAE,OAAO,GAAiC;AACtF,QAAM,EAAE,GAAG,IAAI,UAAU,CAAC;AAC1B,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,uBAAuB,CAAC;AACvC,QAAM,aAAa,iBAAiB,CAAC;AAErC,QAAM,EAAE,MAAM,mBAAmB,WAAW,QAAQ,IAAI,qBAAqB,EAAE;AAQ/E,QAAM,gBAAgB,MAAM,QAAQ,MAAM;AACxC,QAAI,CAAC,kBAAmB,QAAO;AAC/B,WAAO;AAAA,MACL,IAAI,kBAAkB,OAAO,KAAK,OAAO,EAAE,IAAI;AAAA,MAC/C,YAAY,kBAAkB;AAAA,MAC9B,MAAM,kBAAkB;AAAA,MACxB,aAAa,kBAAkB;AAAA,MAC/B,UAAU,kBAAkB;AAAA,MAC5B,MAAM,kBAAkB;AAAA,MACxB,cAAc,kBAAkB;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,mBAAmB,EAAE,CAAC;AAQ1B,MAAI,CAAC,eAAe;AAClB,WACE,oBAAC,QACC,8BAAC,YACE,qBAAW,CAAC,YACX,oBAAC,gBAAa,OAAO,EAAE,oCAAoC,+BAA+B,GAAG,IAE7F,oBAAC,kBAAe,OAAO,EAAE,gCAAgC,yBAAyB,GAAG,GAEzF,GACF;AAAA,EAEJ;AAcA,SACE,oBAAC,QACC,8BAAC,YACC;AAAA,IAAC;AAAA;AAAA,MAEC,OAAO,EAAE,mCAAmC,qBAAqB;AAAA,MACjE,mBAAmB;AAAA,MACnB,UAAS;AAAA,MACT,gBAAgB,EAAE,cAAc,0BAA0B,YAAY,KAAK,OAAO,EAAE,IAAI,GAAG;AAAA,MAC3F;AAAA,MACA,UAAU,EAAE,gBAAgB;AAAA,MAC5B;AAAA,MACA,yBAAyB,mBAAmB,aAAa;AAAA,MACzD;AAAA,MACA,QAAQ;AAAA,MACR,gBAAgB,EAAE,gCAAgC,yBAAyB;AAAA,MAC3E,aAAa,EAAE,oCAAoC,MAAM;AAAA,MACzD,YAAW;AAAA,MACX,iBAAiB;AAAA,MACjB,UAAU,OAAO,WAAW;AAC1B,YAAI,CAAC,GAAI;AACT,cAAM,UAAU;AAAA,UACd,IAAI,KAAK,OAAO,EAAE,IAAI;AAAA,UACtB,YAAY,OAAO;AAAA,UACnB,MAAM,OAAO;AAAA,UACb,aAAa,OAAO;AAAA,UACpB,UAAU,OAAO;AAAA,UAEjB,MAAM,OAAO;AAAA,UACb,cAAc,OAAO;AAAA,QACvB;AACA,cAAM,WAAW,0BAA0B,OAAO;AAAA,MACpD;AAAA;AAAA,IA5BK,gBAAgB,mBAAmB;AAAA,EA6B1C,GACF,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -23,6 +23,7 @@ function CreateFeatureTogglePage() {
23
23
  CrudForm,
24
24
  {
25
25
  title: "Create Feature Toggle",
26
+ titleHeadingLevel: 1,
26
27
  backHref: "/backend/feature-toggles/global",
27
28
  fields,
28
29
  groups: formGroups,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/feature_toggles/backend/feature-toggles/global/create/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport { Page, PageBody } from \"@open-mercato/ui/backend/Page\";\nimport { CrudForm } from \"@open-mercato/ui/backend/CrudForm\";\nimport { createCrud } from \"@open-mercato/ui/backend/utils/crud\";\nimport { useRouter } from \"next/navigation\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { createFormGroups, createFieldDefinitions } from \"../../../../components/formConfig\";\n\nexport default function CreateFeatureTogglePage() {\n const router = useRouter();\n const t = useT();\n\n const initialValues = {\n identifier: '',\n name: '',\n description: '',\n category: '',\n type: '',\n defaultValue: null,\n }\n\n const fields = createFieldDefinitions(t);\n const formGroups = createFormGroups(t);\n\n return (\n <Page>\n <PageBody>\n <CrudForm\n title=\"Create Feature Toggle\"\n backHref=\"/backend/feature-toggles/global\"\n fields={fields}\n groups={formGroups}\n initialValues={initialValues}\n onSubmit={async (values) => {\n const payload: Record<string, unknown> = {\n identifier: values.identifier,\n name: values.name,\n description: values.description,\n category: values.category,\n type: values.type,\n defaultValue: values.defaultValue,\n }\n\n await createCrud<{ id?: string }>('feature_toggles/global', payload)\n router.push('/backend/feature-toggles/global')\n router.refresh()\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": ";AA2BQ;AA1BR,SAAS,MAAM,gBAAgB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,YAAY;AACrB,SAAS,kBAAkB,8BAA8B;AAE1C,SAAR,0BAA2C;AAChD,QAAM,SAAS,UAAU;AACzB,QAAM,IAAI,KAAK;AAEf,QAAM,gBAAgB;AAAA,IACpB,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAEA,QAAM,SAAS,uBAAuB,CAAC;AACvC,QAAM,aAAa,iBAAiB,CAAC;AAErC,SACE,oBAAC,QACC,8BAAC,YACC;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,UAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,UAAU,OAAO,WAAW;AAC1B,cAAM,UAAmC;AAAA,UACvC,YAAY,OAAO;AAAA,UACnB,MAAM,OAAO;AAAA,UACb,aAAa,OAAO;AAAA,UACpB,UAAU,OAAO;AAAA,UACjB,MAAM,OAAO;AAAA,UACb,cAAc,OAAO;AAAA,QACvB;AAEA,cAAM,WAA4B,0BAA0B,OAAO;AACnE,eAAO,KAAK,iCAAiC;AAC7C,eAAO,QAAQ;AAAA,MACjB;AAAA;AAAA,EACF,GACF,GACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\"\nimport { Page, PageBody } from \"@open-mercato/ui/backend/Page\";\nimport { CrudForm } from \"@open-mercato/ui/backend/CrudForm\";\nimport { createCrud } from \"@open-mercato/ui/backend/utils/crud\";\nimport { useRouter } from \"next/navigation\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { createFormGroups, createFieldDefinitions } from \"../../../../components/formConfig\";\n\nexport default function CreateFeatureTogglePage() {\n const router = useRouter();\n const t = useT();\n\n const initialValues = {\n identifier: '',\n name: '',\n description: '',\n category: '',\n type: '',\n defaultValue: null,\n }\n\n const fields = createFieldDefinitions(t);\n const formGroups = createFormGroups(t);\n\n return (\n <Page>\n <PageBody>\n <CrudForm\n title=\"Create Feature Toggle\"\n titleHeadingLevel={1}\n backHref=\"/backend/feature-toggles/global\"\n fields={fields}\n groups={formGroups}\n initialValues={initialValues}\n onSubmit={async (values) => {\n const payload: Record<string, unknown> = {\n identifier: values.identifier,\n name: values.name,\n description: values.description,\n category: values.category,\n type: values.type,\n defaultValue: values.defaultValue,\n }\n\n await createCrud<{ id?: string }>('feature_toggles/global', payload)\n router.push('/backend/feature-toggles/global')\n router.refresh()\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": ";AA2BQ;AA1BR,SAAS,MAAM,gBAAgB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,YAAY;AACrB,SAAS,kBAAkB,8BAA8B;AAE1C,SAAR,0BAA2C;AAChD,QAAM,SAAS,UAAU;AACzB,QAAM,IAAI,KAAK;AAEf,QAAM,gBAAgB;AAAA,IACpB,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAEA,QAAM,SAAS,uBAAuB,CAAC;AACvC,QAAM,aAAa,iBAAiB,CAAC;AAErC,SACE,oBAAC,QACC,8BAAC,YACC;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,mBAAmB;AAAA,MACnB,UAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,UAAU,OAAO,WAAW;AAC1B,cAAM,UAAmC;AAAA,UACvC,YAAY,OAAO;AAAA,UACnB,MAAM,OAAO;AAAA,UACb,aAAa,OAAO;AAAA,UACpB,UAAU,OAAO;AAAA,UACjB,MAAM,OAAO;AAAA,UACb,cAAc,OAAO;AAAA,QACvB;AAEA,cAAM,WAA4B,0BAA0B,OAAO;AACnE,eAAO,KAAK,iCAAiC;AAC7C,eAAO,QAAQ;AAAA,MACjB;AAAA;AAAA,EACF,GACF,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -155,6 +155,7 @@ function FeatureTogglesTable() {
155
155
  DataTable,
156
156
  {
157
157
  title: t("feature_toggles.global.help.title", "Feature Toggles"),
158
+ titleHeadingLevel: 1,
158
159
  disableRowClick: true,
159
160
  actions: /* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href: "/backend/feature-toggles/global/create", children: t("common.create", "Create") }) }),
160
161
  columns,