@open-mercato/core 0.6.8-develop.6925.1.cefa200fa4 → 0.6.8-develop.6930.1.1e5976efc3

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 (402) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/eudr_due_diligence_statement/index.js +47 -0
  3. package/dist/generated/entities/eudr_due_diligence_statement/index.js.map +7 -0
  4. package/dist/generated/entities/eudr_evidence_submission/index.js +51 -0
  5. package/dist/generated/entities/eudr_evidence_submission/index.js.map +7 -0
  6. package/dist/generated/entities/eudr_mitigation_action/index.js +31 -0
  7. package/dist/generated/entities/eudr_mitigation_action/index.js.map +7 -0
  8. package/dist/generated/entities/eudr_plot/index.js +39 -0
  9. package/dist/generated/entities/eudr_plot/index.js.map +7 -0
  10. package/dist/generated/entities/eudr_product_mapping/index.js +31 -0
  11. package/dist/generated/entities/eudr_product_mapping/index.js.map +7 -0
  12. package/dist/generated/entities/eudr_risk_assessment/index.js +35 -0
  13. package/dist/generated/entities/eudr_risk_assessment/index.js.map +7 -0
  14. package/dist/generated/entities.ids.generated.js +9 -0
  15. package/dist/generated/entities.ids.generated.js.map +2 -2
  16. package/dist/generated/entity-fields-registry.js +120 -0
  17. package/dist/generated/entity-fields-registry.js.map +2 -2
  18. package/dist/modules/attachments/fields/attachment.js +5 -1
  19. package/dist/modules/attachments/fields/attachment.js.map +2 -2
  20. package/dist/modules/attachments/lib/crud.js +3 -1
  21. package/dist/modules/attachments/lib/crud.js.map +2 -2
  22. package/dist/modules/eudr/acl.js +43 -0
  23. package/dist/modules/eudr/acl.js.map +7 -0
  24. package/dist/modules/eudr/ai-agents.js +205 -0
  25. package/dist/modules/eudr/ai-agents.js.map +7 -0
  26. package/dist/modules/eudr/ai-tools/compliance-pack.js +495 -0
  27. package/dist/modules/eudr/ai-tools/compliance-pack.js.map +7 -0
  28. package/dist/modules/eudr/ai-tools/types.js +10 -0
  29. package/dist/modules/eudr/ai-tools/types.js.map +7 -0
  30. package/dist/modules/eudr/ai-tools.js +10 -0
  31. package/dist/modules/eudr/ai-tools.js.map +7 -0
  32. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js +386 -0
  33. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js.map +7 -0
  34. package/dist/modules/eudr/api/evidence-submissions/route.js +318 -0
  35. package/dist/modules/eudr/api/evidence-submissions/route.js.map +7 -0
  36. package/dist/modules/eudr/api/mitigation-actions/route.js +249 -0
  37. package/dist/modules/eudr/api/mitigation-actions/route.js.map +7 -0
  38. package/dist/modules/eudr/api/openapi.js +27 -0
  39. package/dist/modules/eudr/api/openapi.js.map +7 -0
  40. package/dist/modules/eudr/api/plots/import/route.js +294 -0
  41. package/dist/modules/eudr/api/plots/import/route.js.map +7 -0
  42. package/dist/modules/eudr/api/plots/route.js +279 -0
  43. package/dist/modules/eudr/api/plots/route.js.map +7 -0
  44. package/dist/modules/eudr/api/product-mappings/route.js +257 -0
  45. package/dist/modules/eudr/api/product-mappings/route.js.map +7 -0
  46. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js +298 -0
  47. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +7 -0
  48. package/dist/modules/eudr/api/product-mappings/suggestions/route.js +132 -0
  49. package/dist/modules/eudr/api/product-mappings/suggestions/route.js.map +7 -0
  50. package/dist/modules/eudr/api/reports/annual/route.js +266 -0
  51. package/dist/modules/eudr/api/reports/annual/route.js.map +7 -0
  52. package/dist/modules/eudr/api/risk-assessments/route.js +300 -0
  53. package/dist/modules/eudr/api/risk-assessments/route.js.map +7 -0
  54. package/dist/modules/eudr/api/statements/[id]/export/route.js +631 -0
  55. package/dist/modules/eudr/api/statements/[id]/export/route.js.map +7 -0
  56. package/dist/modules/eudr/api/statements/[id]/readiness/route.js +111 -0
  57. package/dist/modules/eudr/api/statements/[id]/readiness/route.js.map +7 -0
  58. package/dist/modules/eudr/api/statements/route.js +314 -0
  59. package/dist/modules/eudr/api/statements/route.js.map +7 -0
  60. package/dist/modules/eudr/api/suppliers/compliance/route.js +173 -0
  61. package/dist/modules/eudr/api/suppliers/compliance/route.js.map +7 -0
  62. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js +468 -0
  63. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js.map +7 -0
  64. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js +16 -0
  65. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js.map +7 -0
  66. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js +351 -0
  67. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js.map +7 -0
  68. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js +17 -0
  69. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js.map +7 -0
  70. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +313 -0
  71. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +7 -0
  72. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js +16 -0
  73. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js.map +7 -0
  74. package/dist/modules/eudr/backend/eudr/page.js +360 -0
  75. package/dist/modules/eudr/backend/eudr/page.js.map +7 -0
  76. package/dist/modules/eudr/backend/eudr/page.meta.js +16 -0
  77. package/dist/modules/eudr/backend/eudr/page.meta.js.map +7 -0
  78. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js +346 -0
  79. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js.map +7 -0
  80. package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js +16 -0
  81. package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js.map +7 -0
  82. package/dist/modules/eudr/backend/eudr/plots/create/page.js +253 -0
  83. package/dist/modules/eudr/backend/eudr/plots/create/page.js.map +7 -0
  84. package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js +17 -0
  85. package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js.map +7 -0
  86. package/dist/modules/eudr/backend/eudr/plots/page.js +386 -0
  87. package/dist/modules/eudr/backend/eudr/plots/page.js.map +7 -0
  88. package/dist/modules/eudr/backend/eudr/plots/page.meta.js +16 -0
  89. package/dist/modules/eudr/backend/eudr/plots/page.meta.js.map +7 -0
  90. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js +253 -0
  91. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js.map +7 -0
  92. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js +16 -0
  93. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js.map +7 -0
  94. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js +174 -0
  95. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js.map +7 -0
  96. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js +17 -0
  97. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js.map +7 -0
  98. package/dist/modules/eudr/backend/eudr/product-mappings/page.js +306 -0
  99. package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +7 -0
  100. package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js +16 -0
  101. package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js.map +7 -0
  102. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js +335 -0
  103. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js.map +7 -0
  104. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js +16 -0
  105. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js.map +7 -0
  106. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js +220 -0
  107. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js.map +7 -0
  108. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js +17 -0
  109. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js.map +7 -0
  110. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +324 -0
  111. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +7 -0
  112. package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js +16 -0
  113. package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js.map +7 -0
  114. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js +648 -0
  115. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js.map +7 -0
  116. package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js +16 -0
  117. package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js.map +7 -0
  118. package/dist/modules/eudr/backend/eudr/statements/create/page.js +432 -0
  119. package/dist/modules/eudr/backend/eudr/statements/create/page.js.map +7 -0
  120. package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js +17 -0
  121. package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js.map +7 -0
  122. package/dist/modules/eudr/backend/eudr/statements/page.js +309 -0
  123. package/dist/modules/eudr/backend/eudr/statements/page.js.map +7 -0
  124. package/dist/modules/eudr/backend/eudr/statements/page.meta.js +16 -0
  125. package/dist/modules/eudr/backend/eudr/statements/page.meta.js.map +7 -0
  126. package/dist/modules/eudr/ce.js +56 -0
  127. package/dist/modules/eudr/ce.js.map +7 -0
  128. package/dist/modules/eudr/commands/evidence-submissions.js +571 -0
  129. package/dist/modules/eudr/commands/evidence-submissions.js.map +7 -0
  130. package/dist/modules/eudr/commands/index.js +7 -0
  131. package/dist/modules/eudr/commands/index.js.map +7 -0
  132. package/dist/modules/eudr/commands/lifecycle-events.js +19 -0
  133. package/dist/modules/eudr/commands/lifecycle-events.js.map +7 -0
  134. package/dist/modules/eudr/commands/mitigation-actions.js +488 -0
  135. package/dist/modules/eudr/commands/mitigation-actions.js.map +7 -0
  136. package/dist/modules/eudr/commands/plots.js +517 -0
  137. package/dist/modules/eudr/commands/plots.js.map +7 -0
  138. package/dist/modules/eudr/commands/product-mappings.js +468 -0
  139. package/dist/modules/eudr/commands/product-mappings.js.map +7 -0
  140. package/dist/modules/eudr/commands/risk-assessments.js +599 -0
  141. package/dist/modules/eudr/commands/risk-assessments.js.map +7 -0
  142. package/dist/modules/eudr/commands/statements.js +747 -0
  143. package/dist/modules/eudr/commands/statements.js.map +7 -0
  144. package/dist/modules/eudr/components/CountrySelectField.js +64 -0
  145. package/dist/modules/eudr/components/CountrySelectField.js.map +7 -0
  146. package/dist/modules/eudr/components/GeometryInput.js +133 -0
  147. package/dist/modules/eudr/components/GeometryInput.js.map +7 -0
  148. package/dist/modules/eudr/components/MappingSuggestionsDialog.js +307 -0
  149. package/dist/modules/eudr/components/MappingSuggestionsDialog.js.map +7 -0
  150. package/dist/modules/eudr/components/MitigationActionsSection.js +345 -0
  151. package/dist/modules/eudr/components/MitigationActionsSection.js.map +7 -0
  152. package/dist/modules/eudr/components/OrderSelectField.js +88 -0
  153. package/dist/modules/eudr/components/OrderSelectField.js.map +7 -0
  154. package/dist/modules/eudr/components/PlotImportDialog.js +229 -0
  155. package/dist/modules/eudr/components/PlotImportDialog.js.map +7 -0
  156. package/dist/modules/eudr/components/PlotMapPreview.js +35 -0
  157. package/dist/modules/eudr/components/PlotMapPreview.js.map +7 -0
  158. package/dist/modules/eudr/components/PlotMapPreviewImpl.js +97 -0
  159. package/dist/modules/eudr/components/PlotMapPreviewImpl.js.map +7 -0
  160. package/dist/modules/eudr/components/PlotMultiSelectField.js +198 -0
  161. package/dist/modules/eudr/components/PlotMultiSelectField.js.map +7 -0
  162. package/dist/modules/eudr/components/RiskCriteriaField.js +128 -0
  163. package/dist/modules/eudr/components/RiskCriteriaField.js.map +7 -0
  164. package/dist/modules/eudr/components/StatementLifecycleBar.js +274 -0
  165. package/dist/modules/eudr/components/StatementLifecycleBar.js.map +7 -0
  166. package/dist/modules/eudr/components/StatementReadinessChecklist.js +56 -0
  167. package/dist/modules/eudr/components/StatementReadinessChecklist.js.map +7 -0
  168. package/dist/modules/eudr/components/StatementRiskSection.js +179 -0
  169. package/dist/modules/eudr/components/StatementRiskSection.js.map +7 -0
  170. package/dist/modules/eudr/components/crudErrorI18n.js +31 -0
  171. package/dist/modules/eudr/components/crudErrorI18n.js.map +7 -0
  172. package/dist/modules/eudr/components/formConfig.js +593 -0
  173. package/dist/modules/eudr/components/formConfig.js.map +7 -0
  174. package/dist/modules/eudr/components/plotForm.js +68 -0
  175. package/dist/modules/eudr/components/plotForm.js.map +7 -0
  176. package/dist/modules/eudr/data/enrichers.js +62 -0
  177. package/dist/modules/eudr/data/enrichers.js.map +7 -0
  178. package/dist/modules/eudr/data/entities.js +437 -0
  179. package/dist/modules/eudr/data/entities.js.map +7 -0
  180. package/dist/modules/eudr/data/validators.js +271 -0
  181. package/dist/modules/eudr/data/validators.js.map +7 -0
  182. package/dist/modules/eudr/encryption.js +33 -0
  183. package/dist/modules/eudr/encryption.js.map +7 -0
  184. package/dist/modules/eudr/events.js +38 -0
  185. package/dist/modules/eudr/events.js.map +7 -0
  186. package/dist/modules/eudr/index.js +15 -0
  187. package/dist/modules/eudr/index.js.map +7 -0
  188. package/dist/modules/eudr/lib/annual-report.js +104 -0
  189. package/dist/modules/eudr/lib/annual-report.js.map +7 -0
  190. package/dist/modules/eudr/lib/completeness.js +64 -0
  191. package/dist/modules/eudr/lib/completeness.js.map +7 -0
  192. package/dist/modules/eudr/lib/detail-read-scope.js +16 -0
  193. package/dist/modules/eudr/lib/detail-read-scope.js.map +7 -0
  194. package/dist/modules/eudr/lib/geometry.js +142 -0
  195. package/dist/modules/eudr/lib/geometry.js.map +7 -0
  196. package/dist/modules/eudr/lib/notifications.js +56 -0
  197. package/dist/modules/eudr/lib/notifications.js.map +7 -0
  198. package/dist/modules/eudr/lib/plural.js +26 -0
  199. package/dist/modules/eudr/lib/plural.js.map +7 -0
  200. package/dist/modules/eudr/lib/reference-data.js +240 -0
  201. package/dist/modules/eudr/lib/reference-data.js.map +7 -0
  202. package/dist/modules/eudr/lib/species.js +10 -0
  203. package/dist/modules/eudr/lib/species.js.map +7 -0
  204. package/dist/modules/eudr/lib/statement-lifecycle.js +84 -0
  205. package/dist/modules/eudr/lib/statement-lifecycle.js.map +7 -0
  206. package/dist/modules/eudr/lib/statement-seeding.js +49 -0
  207. package/dist/modules/eudr/lib/statement-seeding.js.map +7 -0
  208. package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js +15 -0
  209. package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js.map +7 -0
  210. package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js +24 -0
  211. package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js.map +7 -0
  212. package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js +15 -0
  213. package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js.map +7 -0
  214. package/dist/modules/eudr/notifications.js +58 -0
  215. package/dist/modules/eudr/notifications.js.map +7 -0
  216. package/dist/modules/eudr/search.js +186 -0
  217. package/dist/modules/eudr/search.js.map +7 -0
  218. package/dist/modules/eudr/setup.js +12 -0
  219. package/dist/modules/eudr/setup.js.map +7 -0
  220. package/dist/modules/eudr/subscribers/notify-mitigation-completed.js +34 -0
  221. package/dist/modules/eudr/subscribers/notify-mitigation-completed.js.map +7 -0
  222. package/dist/modules/eudr/subscribers/notify-risk-concluded.js +35 -0
  223. package/dist/modules/eudr/subscribers/notify-risk-concluded.js.map +7 -0
  224. package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js +37 -0
  225. package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js.map +7 -0
  226. package/dist/modules/eudr/subscribers/notify-statement-submitted.js +34 -0
  227. package/dist/modules/eudr/subscribers/notify-statement-submitted.js.map +7 -0
  228. package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js +34 -0
  229. package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js.map +7 -0
  230. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js +124 -0
  231. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js.map +7 -0
  232. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js +22 -0
  233. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js.map +7 -0
  234. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js +203 -0
  235. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js.map +7 -0
  236. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js +23 -0
  237. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js.map +7 -0
  238. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js +19 -0
  239. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js.map +7 -0
  240. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js +31 -0
  241. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js.map +7 -0
  242. package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js +100 -0
  243. package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js.map +7 -0
  244. package/dist/modules/eudr/widgets/injection/order-compliance/widget.js +17 -0
  245. package/dist/modules/eudr/widgets/injection/order-compliance/widget.js.map +7 -0
  246. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js +116 -0
  247. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js.map +7 -0
  248. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js +17 -0
  249. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js.map +7 -0
  250. package/dist/modules/eudr/widgets/injection-table.js +32 -0
  251. package/dist/modules/eudr/widgets/injection-table.js.map +7 -0
  252. package/dist/modules/notifications/lib/notificationService.js +67 -3
  253. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  254. package/dist/modules/query_index/lib/engine.js +121 -48
  255. package/dist/modules/query_index/lib/engine.js.map +2 -2
  256. package/dist/modules/sales/api/documents/factory.js +17 -0
  257. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  258. package/dist/modules/sales/commands/documents.js +32 -18
  259. package/dist/modules/sales/commands/documents.js.map +2 -2
  260. package/dist/modules/sales/data/entities.js +1 -0
  261. package/dist/modules/sales/data/entities.js.map +2 -2
  262. package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js +17 -0
  263. package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js.map +7 -0
  264. package/generated/entities/eudr_due_diligence_statement/index.ts +22 -0
  265. package/generated/entities/eudr_evidence_submission/index.ts +24 -0
  266. package/generated/entities/eudr_mitigation_action/index.ts +14 -0
  267. package/generated/entities/eudr_plot/index.ts +18 -0
  268. package/generated/entities/eudr_product_mapping/index.ts +14 -0
  269. package/generated/entities/eudr_risk_assessment/index.ts +16 -0
  270. package/generated/entities.ids.generated.ts +9 -0
  271. package/generated/entity-fields-registry.ts +120 -0
  272. package/package.json +7 -7
  273. package/src/modules/attachments/fields/attachment.tsx +5 -0
  274. package/src/modules/attachments/lib/crud.ts +2 -0
  275. package/src/modules/eudr/acl.ts +39 -0
  276. package/src/modules/eudr/ai-agents.ts +258 -0
  277. package/src/modules/eudr/ai-tools/compliance-pack.ts +618 -0
  278. package/src/modules/eudr/ai-tools/types.ts +44 -0
  279. package/src/modules/eudr/ai-tools.ts +15 -0
  280. package/src/modules/eudr/api/dashboard/widgets/compliance-overview/route.ts +481 -0
  281. package/src/modules/eudr/api/evidence-submissions/route.ts +335 -0
  282. package/src/modules/eudr/api/mitigation-actions/route.ts +263 -0
  283. package/src/modules/eudr/api/openapi.ts +28 -0
  284. package/src/modules/eudr/api/plots/import/route.ts +369 -0
  285. package/src/modules/eudr/api/plots/route.ts +296 -0
  286. package/src/modules/eudr/api/product-mappings/route.ts +269 -0
  287. package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +382 -0
  288. package/src/modules/eudr/api/product-mappings/suggestions/route.ts +169 -0
  289. package/src/modules/eudr/api/reports/annual/route.ts +457 -0
  290. package/src/modules/eudr/api/risk-assessments/route.ts +323 -0
  291. package/src/modules/eudr/api/statements/[id]/export/route.ts +713 -0
  292. package/src/modules/eudr/api/statements/[id]/readiness/route.ts +129 -0
  293. package/src/modules/eudr/api/statements/route.ts +329 -0
  294. package/src/modules/eudr/api/suppliers/compliance/route.ts +241 -0
  295. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.ts +12 -0
  296. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.tsx +545 -0
  297. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.ts +13 -0
  298. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.tsx +383 -0
  299. package/src/modules/eudr/backend/eudr/evidence-submissions/page.meta.ts +12 -0
  300. package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +379 -0
  301. package/src/modules/eudr/backend/eudr/page.meta.ts +12 -0
  302. package/src/modules/eudr/backend/eudr/page.tsx +477 -0
  303. package/src/modules/eudr/backend/eudr/plots/[id]/page.meta.ts +12 -0
  304. package/src/modules/eudr/backend/eudr/plots/[id]/page.tsx +404 -0
  305. package/src/modules/eudr/backend/eudr/plots/create/page.meta.ts +13 -0
  306. package/src/modules/eudr/backend/eudr/plots/create/page.tsx +267 -0
  307. package/src/modules/eudr/backend/eudr/plots/page.meta.ts +12 -0
  308. package/src/modules/eudr/backend/eudr/plots/page.tsx +442 -0
  309. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.ts +12 -0
  310. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.tsx +311 -0
  311. package/src/modules/eudr/backend/eudr/product-mappings/create/page.meta.ts +13 -0
  312. package/src/modules/eudr/backend/eudr/product-mappings/create/page.tsx +190 -0
  313. package/src/modules/eudr/backend/eudr/product-mappings/page.meta.ts +12 -0
  314. package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +344 -0
  315. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.ts +12 -0
  316. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.tsx +421 -0
  317. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.meta.ts +13 -0
  318. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.tsx +247 -0
  319. package/src/modules/eudr/backend/eudr/risk-assessments/page.meta.ts +12 -0
  320. package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +383 -0
  321. package/src/modules/eudr/backend/eudr/statements/[id]/page.meta.ts +12 -0
  322. package/src/modules/eudr/backend/eudr/statements/[id]/page.tsx +777 -0
  323. package/src/modules/eudr/backend/eudr/statements/create/page.meta.ts +13 -0
  324. package/src/modules/eudr/backend/eudr/statements/create/page.tsx +511 -0
  325. package/src/modules/eudr/backend/eudr/statements/page.meta.ts +12 -0
  326. package/src/modules/eudr/backend/eudr/statements/page.tsx +372 -0
  327. package/src/modules/eudr/ce.ts +52 -0
  328. package/src/modules/eudr/commands/evidence-submissions.ts +699 -0
  329. package/src/modules/eudr/commands/index.ts +6 -0
  330. package/src/modules/eudr/commands/lifecycle-events.ts +28 -0
  331. package/src/modules/eudr/commands/mitigation-actions.ts +574 -0
  332. package/src/modules/eudr/commands/plots.ts +627 -0
  333. package/src/modules/eudr/commands/product-mappings.ts +556 -0
  334. package/src/modules/eudr/commands/risk-assessments.ts +728 -0
  335. package/src/modules/eudr/commands/statements.ts +933 -0
  336. package/src/modules/eudr/components/CountrySelectField.tsx +77 -0
  337. package/src/modules/eudr/components/GeometryInput.tsx +170 -0
  338. package/src/modules/eudr/components/MappingSuggestionsDialog.tsx +385 -0
  339. package/src/modules/eudr/components/MitigationActionsSection.tsx +417 -0
  340. package/src/modules/eudr/components/OrderSelectField.tsx +116 -0
  341. package/src/modules/eudr/components/PlotImportDialog.tsx +277 -0
  342. package/src/modules/eudr/components/PlotMapPreview.tsx +46 -0
  343. package/src/modules/eudr/components/PlotMapPreviewImpl.tsx +111 -0
  344. package/src/modules/eudr/components/PlotMultiSelectField.tsx +238 -0
  345. package/src/modules/eudr/components/RiskCriteriaField.tsx +173 -0
  346. package/src/modules/eudr/components/StatementLifecycleBar.tsx +363 -0
  347. package/src/modules/eudr/components/StatementReadinessChecklist.tsx +82 -0
  348. package/src/modules/eudr/components/StatementRiskSection.tsx +242 -0
  349. package/src/modules/eudr/components/crudErrorI18n.ts +36 -0
  350. package/src/modules/eudr/components/formConfig.tsx +717 -0
  351. package/src/modules/eudr/components/plotForm.ts +75 -0
  352. package/src/modules/eudr/data/enrichers.ts +82 -0
  353. package/src/modules/eudr/data/entities.ts +369 -0
  354. package/src/modules/eudr/data/validators.ts +357 -0
  355. package/src/modules/eudr/encryption.ts +31 -0
  356. package/src/modules/eudr/events.ts +38 -0
  357. package/src/modules/eudr/i18n/de.json +747 -0
  358. package/src/modules/eudr/i18n/en.json +747 -0
  359. package/src/modules/eudr/i18n/es.json +747 -0
  360. package/src/modules/eudr/i18n/ko.json +747 -0
  361. package/src/modules/eudr/i18n/pl.json +747 -0
  362. package/src/modules/eudr/index.ts +13 -0
  363. package/src/modules/eudr/lib/annual-report.ts +120 -0
  364. package/src/modules/eudr/lib/completeness.ts +90 -0
  365. package/src/modules/eudr/lib/detail-read-scope.ts +44 -0
  366. package/src/modules/eudr/lib/geometry.ts +191 -0
  367. package/src/modules/eudr/lib/notifications.ts +85 -0
  368. package/src/modules/eudr/lib/plural.ts +36 -0
  369. package/src/modules/eudr/lib/reference-data.ts +128 -0
  370. package/src/modules/eudr/lib/species.ts +12 -0
  371. package/src/modules/eudr/lib/statement-lifecycle.ts +109 -0
  372. package/src/modules/eudr/lib/statement-seeding.ts +86 -0
  373. package/src/modules/eudr/migrations/.snapshot-open-mercato.json +2046 -0
  374. package/src/modules/eudr/migrations/Migration20260706102002_eudr.ts +16 -0
  375. package/src/modules/eudr/migrations/Migration20260706152612_eudr.ts +30 -0
  376. package/src/modules/eudr/migrations/Migration20260722100000_eudr.ts +17 -0
  377. package/src/modules/eudr/notifications.ts +56 -0
  378. package/src/modules/eudr/search.ts +212 -0
  379. package/src/modules/eudr/setup.ts +10 -0
  380. package/src/modules/eudr/subscribers/notify-mitigation-completed.ts +56 -0
  381. package/src/modules/eudr/subscribers/notify-risk-concluded.ts +58 -0
  382. package/src/modules/eudr/subscribers/notify-statement-reference-issued.ts +59 -0
  383. package/src/modules/eudr/subscribers/notify-statement-submitted.ts +49 -0
  384. package/src/modules/eudr/subscribers/notify-statement-withdrawn.ts +49 -0
  385. package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-created.ts +189 -0
  386. package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.ts +31 -0
  387. package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.client.tsx +271 -0
  388. package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.ts +24 -0
  389. package/src/modules/eudr/widgets/injection/eudr-product-column/widget.client.tsx +37 -0
  390. package/src/modules/eudr/widgets/injection/eudr-product-column/widget.ts +30 -0
  391. package/src/modules/eudr/widgets/injection/order-compliance/widget.client.tsx +131 -0
  392. package/src/modules/eudr/widgets/injection/order-compliance/widget.ts +16 -0
  393. package/src/modules/eudr/widgets/injection/supplier-compliance/widget.client.tsx +168 -0
  394. package/src/modules/eudr/widgets/injection/supplier-compliance/widget.ts +16 -0
  395. package/src/modules/eudr/widgets/injection-table.ts +31 -0
  396. package/src/modules/notifications/lib/notificationService.ts +83 -4
  397. package/src/modules/query_index/lib/engine.ts +139 -51
  398. package/src/modules/sales/api/documents/factory.ts +29 -0
  399. package/src/modules/sales/commands/documents.ts +65 -18
  400. package/src/modules/sales/data/entities.ts +1 -0
  401. package/src/modules/sales/migrations/.snapshot-open-mercato.json +10 -0
  402. package/src/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.ts +59 -0
@@ -0,0 +1,189 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql'
2
+ import { sql } from 'kysely'
3
+ import { createLogger } from '@open-mercato/shared/lib/logger'
4
+ import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
5
+ import { EudrEvidenceSubmission, EudrPlot } from '../data/entities'
6
+ import { computeSubmissionCompleteness } from '../lib/completeness'
7
+
8
+ const logger = createLogger('eudr').child({ component: 'attachment-created-completeness' })
9
+
10
+ const EVIDENCE_SUBMISSION_ENTITY_ID = 'eudr:eudr_evidence_submission'
11
+
12
+ export const metadata = {
13
+ event: 'attachments.attachment.created',
14
+ persistent: false,
15
+ id: 'eudr:attachment-created-completeness',
16
+ }
17
+
18
+ type AttachmentCountDatabase = {
19
+ attachments: {
20
+ entity_id: string
21
+ record_id: string
22
+ tenant_id: string | null
23
+ organization_id: string | null
24
+ }
25
+ }
26
+
27
+ type AttachmentEventPayload = {
28
+ entityId?: unknown
29
+ recordId?: unknown
30
+ tenantId?: unknown
31
+ organizationId?: unknown
32
+ }
33
+
34
+ type ScopedAttachmentPayload = {
35
+ recordId: string
36
+ tenantId: string
37
+ organizationId: string
38
+ }
39
+
40
+ type EventBusLike = {
41
+ emitEvent(
42
+ eventName: string,
43
+ payload: Record<string, unknown>,
44
+ options?: { tenantId?: string | null; organizationId?: string | null },
45
+ ): Promise<void> | void
46
+ }
47
+
48
+ export type AttachmentSubscriberContext = {
49
+ resolve: <T = unknown>(name: string) => T
50
+ container?: { resolve<T = unknown>(name: string): T }
51
+ }
52
+
53
+ function parsePayload(payload: AttachmentEventPayload): ScopedAttachmentPayload | null {
54
+ if (payload.entityId !== EVIDENCE_SUBMISSION_ENTITY_ID) return null
55
+ if (typeof payload.recordId !== 'string' || payload.recordId.trim().length === 0) return null
56
+ if (typeof payload.tenantId !== 'string' || payload.tenantId.trim().length === 0) return null
57
+ if (typeof payload.organizationId !== 'string' || payload.organizationId.trim().length === 0) return null
58
+ return {
59
+ recordId: payload.recordId,
60
+ tenantId: payload.tenantId,
61
+ organizationId: payload.organizationId,
62
+ }
63
+ }
64
+
65
+ function parseCountValue(value: string | number | bigint | null | undefined): number | undefined {
66
+ if (typeof value === 'number') return Number.isFinite(value) ? value : undefined
67
+ if (typeof value === 'bigint') return Number(value)
68
+ if (typeof value === 'string') {
69
+ const parsed = Number(value)
70
+ return Number.isFinite(parsed) ? parsed : undefined
71
+ }
72
+ return undefined
73
+ }
74
+
75
+ async function countLinkedAttachments(
76
+ em: EntityManager,
77
+ scope: ScopedAttachmentPayload,
78
+ ): Promise<number | undefined> {
79
+ try {
80
+ const db = em.getKysely<AttachmentCountDatabase>()
81
+ const row = await db
82
+ .selectFrom('attachments')
83
+ .select(sql<string | number | bigint>`count(*)`.as('attachment_count'))
84
+ .where('entity_id', '=', EVIDENCE_SUBMISSION_ENTITY_ID)
85
+ .where('record_id', '=', scope.recordId)
86
+ .where('tenant_id', '=', scope.tenantId)
87
+ .where('organization_id', '=', scope.organizationId)
88
+ .executeTakeFirst()
89
+ return parseCountValue(row?.attachment_count)
90
+ } catch {
91
+ return undefined
92
+ }
93
+ }
94
+
95
+ async function countActivePlots(
96
+ em: EntityManager,
97
+ submission: EudrEvidenceSubmission,
98
+ ): Promise<number> {
99
+ const plotIds = Array.from(new Set(Array.isArray(submission.plotIds) ? submission.plotIds : []))
100
+ if (plotIds.length === 0) return 0
101
+ return em.count(EudrPlot, {
102
+ id: { $in: plotIds },
103
+ tenantId: submission.tenantId,
104
+ organizationId: submission.organizationId,
105
+ deletedAt: null,
106
+ isActive: true,
107
+ })
108
+ }
109
+
110
+ async function emitSubmissionReindex(
111
+ ctx: AttachmentSubscriberContext,
112
+ submission: EudrEvidenceSubmission,
113
+ ): Promise<void> {
114
+ const bus = ctx.resolve<EventBusLike>('eventBus')
115
+ await bus.emitEvent(
116
+ 'query_index.upsert_one',
117
+ {
118
+ entityType: EVIDENCE_SUBMISSION_ENTITY_ID,
119
+ recordId: submission.id,
120
+ organizationId: submission.organizationId,
121
+ tenantId: submission.tenantId,
122
+ crudAction: 'updated',
123
+ },
124
+ {
125
+ organizationId: submission.organizationId,
126
+ tenantId: submission.tenantId,
127
+ },
128
+ )
129
+ }
130
+
131
+ export async function recomputeSubmissionCompletenessFromAttachmentPayload(
132
+ payload: AttachmentEventPayload,
133
+ ctx: AttachmentSubscriberContext,
134
+ ): Promise<void> {
135
+ const scopedPayload = parsePayload(payload)
136
+ if (!scopedPayload) return
137
+
138
+ const baseEm = ctx.resolve<EntityManager>('em')
139
+ const em = baseEm.fork()
140
+ const submission = await findOneWithDecryption(
141
+ em,
142
+ EudrEvidenceSubmission,
143
+ {
144
+ id: scopedPayload.recordId,
145
+ tenantId: scopedPayload.tenantId,
146
+ organizationId: scopedPayload.organizationId,
147
+ deletedAt: null,
148
+ },
149
+ undefined,
150
+ {
151
+ tenantId: scopedPayload.tenantId,
152
+ organizationId: scopedPayload.organizationId,
153
+ },
154
+ )
155
+ if (!submission) return
156
+
157
+ const [activePlotCount, linkedAttachmentCount] = await Promise.all([
158
+ countActivePlots(em, submission),
159
+ countLinkedAttachments(em, scopedPayload),
160
+ ])
161
+ const completeness = computeSubmissionCompleteness({
162
+ originCountry: submission.originCountry ?? null,
163
+ geolocation: submission.geolocation ?? null,
164
+ quantityKg: submission.quantityKg ?? null,
165
+ harvestFrom: submission.harvestFrom ?? null,
166
+ harvestTo: submission.harvestTo ?? null,
167
+ producerName: submission.producerName ?? null,
168
+ attachmentIds: submission.attachmentIds ?? [],
169
+ }, {
170
+ activePlotCount,
171
+ linkedAttachmentCount,
172
+ })
173
+ submission.completenessScore = completeness.score
174
+ submission.missingFields = [...completeness.missingFields]
175
+ // Projection update only: attachment CRUD already owns the undoable write.
176
+ await em.flush()
177
+ await emitSubmissionReindex(ctx, submission)
178
+ }
179
+
180
+ export default async function handleAttachmentCreated(
181
+ payload: AttachmentEventPayload,
182
+ ctx: AttachmentSubscriberContext,
183
+ ): Promise<void> {
184
+ try {
185
+ await recomputeSubmissionCompletenessFromAttachmentPayload(payload, ctx)
186
+ } catch (error) {
187
+ logger.warn('attachment-created completeness recompute failed', { err: error })
188
+ }
189
+ }
@@ -0,0 +1,31 @@
1
+ import { createLogger } from '@open-mercato/shared/lib/logger'
2
+ import {
3
+ recomputeSubmissionCompletenessFromAttachmentPayload,
4
+ type AttachmentSubscriberContext,
5
+ } from './recompute-completeness-on-attachment-created'
6
+
7
+ const logger = createLogger('eudr').child({ component: 'attachment-deleted-completeness' })
8
+
9
+ export const metadata = {
10
+ event: 'attachments.attachment.deleted',
11
+ persistent: false,
12
+ id: 'eudr:attachment-deleted-completeness',
13
+ }
14
+
15
+ type AttachmentEventPayload = {
16
+ entityId?: unknown
17
+ recordId?: unknown
18
+ tenantId?: unknown
19
+ organizationId?: unknown
20
+ }
21
+
22
+ export default async function handleAttachmentDeleted(
23
+ payload: AttachmentEventPayload,
24
+ ctx: AttachmentSubscriberContext,
25
+ ): Promise<void> {
26
+ try {
27
+ await recomputeSubmissionCompletenessFromAttachmentPayload(payload, ctx)
28
+ } catch (error) {
29
+ logger.warn('attachment-deleted completeness recompute failed', { err: error })
30
+ }
31
+ }
@@ -0,0 +1,271 @@
1
+ "use client"
2
+
3
+ import * as React from 'react'
4
+ import { useRouter } from 'next/navigation'
5
+ import type { DashboardWidgetComponentProps } from '@open-mercato/shared/modules/dashboard/widgets'
6
+ import { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'
7
+ import { EmptyState } from '@open-mercato/ui/backend/EmptyState'
8
+ import { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'
9
+ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
10
+ import { Button } from '@open-mercato/ui/primitives/button'
11
+ import { Leaf } from 'lucide-react'
12
+ import type { EudrComplianceOverviewSettings } from './widget'
13
+
14
+ type StatusCounts = Record<string, number>
15
+
16
+ type ComplianceOverview = {
17
+ deadline: {
18
+ date: string
19
+ daysLeft: number
20
+ }
21
+ mappingsInScope?: number
22
+ submissions?: {
23
+ total: number
24
+ byStatus: StatusCounts
25
+ avgCompleteness: number | null
26
+ incomplete: number
27
+ }
28
+ statements: {
29
+ total: number
30
+ byStatus: StatusCounts
31
+ notReady: number
32
+ missingReference: number
33
+ }
34
+ riskReviewsDueSoon?: number
35
+ }
36
+
37
+ type Translate = (
38
+ key: string,
39
+ fallbackOrParams?: string | Record<string, string | number>,
40
+ params?: Record<string, string | number>,
41
+ ) => string
42
+
43
+ const SUBMISSION_STATUSES = ['draft', 'submitted', 'verified', 'rejected'] as const
44
+ const STATEMENT_STATUSES = ['draft', 'submitted', 'available', 'withdrawn', 'archived'] as const
45
+
46
+ async function loadOverview(): Promise<ComplianceOverview> {
47
+ const call = await apiCall<ComplianceOverview>('/api/eudr/dashboard/widgets/compliance-overview')
48
+ if (!call.ok || !call.result) {
49
+ const message = `[internal] EUDR compliance overview request failed with status ${call.status}`
50
+ throw new Error(message)
51
+ }
52
+ return call.result
53
+ }
54
+
55
+ function formatDeadlineDate(value: string, locale: string): string {
56
+ const date = new Date(`${value}T00:00:00.000Z`)
57
+ if (Number.isNaN(date.getTime())) return value
58
+ return date.toLocaleDateString(locale || undefined)
59
+ }
60
+
61
+ function formatCompleteness(value: number | null, t: Translate): string {
62
+ if (typeof value !== 'number' || !Number.isFinite(value)) return t('eudr.common.empty')
63
+ return `${Math.round(value)}%`
64
+ }
65
+
66
+ function isOverviewEmpty(data: ComplianceOverview): boolean {
67
+ return (data.mappingsInScope ?? 0) === 0
68
+ && (data.submissions?.total ?? 0) === 0
69
+ && data.statements.total === 0
70
+ && (data.riskReviewsDueSoon ?? 0) === 0
71
+ }
72
+
73
+ function StatusBreakdown({
74
+ title,
75
+ statuses,
76
+ byStatus,
77
+ labelPrefix,
78
+ t,
79
+ }: {
80
+ title: string
81
+ statuses: readonly string[]
82
+ byStatus: StatusCounts
83
+ labelPrefix: string
84
+ t: Translate
85
+ }) {
86
+ return (
87
+ <div className="space-y-1">
88
+ <p className="text-xs font-semibold uppercase text-muted-foreground">{title}</p>
89
+ <div className="flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground">
90
+ {statuses.map((status) => (
91
+ <span key={status}>
92
+ {t(`${labelPrefix}.${status}`)}: {byStatus[status] ?? 0}
93
+ </span>
94
+ ))}
95
+ </div>
96
+ </div>
97
+ )
98
+ }
99
+
100
+ function StatTile({
101
+ label,
102
+ value,
103
+ href,
104
+ onOpen,
105
+ }: {
106
+ label: string
107
+ value: number
108
+ href?: string
109
+ onOpen: (href: string) => void
110
+ }) {
111
+ const content = (
112
+ <span className="flex w-full items-center justify-between gap-3">
113
+ <span className="text-left text-xs font-medium text-muted-foreground">{label}</span>
114
+ <span className="text-lg font-semibold text-foreground">{value}</span>
115
+ </span>
116
+ )
117
+
118
+ if (!href) {
119
+ return (
120
+ <div className="flex min-h-16 items-center rounded-md border bg-background px-3 py-2">
121
+ {content}
122
+ </div>
123
+ )
124
+ }
125
+
126
+ return (
127
+ <Button
128
+ type="button"
129
+ variant="outline"
130
+ className="min-h-16 w-full justify-start px-3 py-2"
131
+ onClick={() => onOpen(href)}
132
+ >
133
+ {content}
134
+ </Button>
135
+ )
136
+ }
137
+
138
+ const EudrComplianceOverviewWidget: React.FC<DashboardWidgetComponentProps<EudrComplianceOverviewSettings>> = ({
139
+ mode,
140
+ refreshToken,
141
+ onRefreshStateChange,
142
+ }) => {
143
+ const t = useT()
144
+ const locale = useLocale()
145
+ const router = useRouter()
146
+ const [overview, setOverview] = React.useState<ComplianceOverview | null>(null)
147
+ const [loading, setLoading] = React.useState(true)
148
+ const [error, setError] = React.useState<string | null>(null)
149
+
150
+ const refresh = React.useCallback(async () => {
151
+ onRefreshStateChange?.(true)
152
+ setLoading(true)
153
+ setError(null)
154
+ try {
155
+ const data = await loadOverview()
156
+ setOverview(data)
157
+ } catch {
158
+ setError(t('eudr.dashboard.error'))
159
+ } finally {
160
+ setLoading(false)
161
+ onRefreshStateChange?.(false)
162
+ }
163
+ }, [onRefreshStateChange, t])
164
+
165
+ React.useEffect(() => {
166
+ refresh().catch(() => {})
167
+ }, [refresh, refreshToken])
168
+
169
+ if (mode === 'settings') {
170
+ return (
171
+ <p className="text-sm text-muted-foreground">{t('eudr.dashboard.noSettings')}</p>
172
+ )
173
+ }
174
+
175
+ if (loading) {
176
+ return <LoadingMessage label={t('eudr.dashboard.loading')} />
177
+ }
178
+
179
+ if (error) {
180
+ return <ErrorMessage label={error} />
181
+ }
182
+
183
+ if (!overview || isOverviewEmpty(overview)) {
184
+ return (
185
+ <EmptyState
186
+ size="sm"
187
+ variant="subtle"
188
+ icon={<Leaf className="h-5 w-5" aria-hidden />}
189
+ title={t('eudr.dashboard.empty.title')}
190
+ description={t('eudr.dashboard.empty.description')}
191
+ />
192
+ )
193
+ }
194
+
195
+ const deadlineDate = formatDeadlineDate(overview.deadline.date, locale)
196
+
197
+ return (
198
+ <div className="space-y-4">
199
+ <div className="space-y-1">
200
+ <p className="text-sm font-semibold">
201
+ {t('eudr.dashboard.daysToDeadline', {
202
+ daysLeft: overview.deadline.daysLeft,
203
+ date: deadlineDate,
204
+ })}
205
+ </p>
206
+ {overview.mappingsInScope !== undefined ? (
207
+ <p className="text-xs text-muted-foreground">
208
+ {t('eudr.dashboard.mappingsInScope', { count: overview.mappingsInScope })}
209
+ </p>
210
+ ) : null}
211
+ </div>
212
+
213
+ <div className="grid grid-cols-2 gap-2">
214
+ <StatTile
215
+ label={t('eudr.dashboard.notReady')}
216
+ value={overview.statements.notReady}
217
+ href="/backend/eudr/statements?status=draft"
218
+ onOpen={router.push}
219
+ />
220
+ {overview.submissions ? (
221
+ <StatTile
222
+ label={t('eudr.dashboard.incompleteSubmissions')}
223
+ value={overview.submissions.incomplete}
224
+ href="/backend/eudr/evidence-submissions"
225
+ onOpen={router.push}
226
+ />
227
+ ) : null}
228
+ <StatTile
229
+ label={t('eudr.dashboard.missingReference')}
230
+ value={overview.statements.missingReference}
231
+ href="/backend/eudr/statements"
232
+ onOpen={router.push}
233
+ />
234
+ {overview.riskReviewsDueSoon !== undefined ? (
235
+ <StatTile
236
+ label={t('eudr.dashboard.riskReviewsDueSoon')}
237
+ value={overview.riskReviewsDueSoon}
238
+ onOpen={router.push}
239
+ />
240
+ ) : null}
241
+ </div>
242
+
243
+ <div className="space-y-3 rounded-md border bg-muted/20 p-3">
244
+ {overview.submissions ? (
245
+ <>
246
+ <div className="flex items-center justify-between gap-3 text-sm">
247
+ <span className="text-muted-foreground">{t('eudr.dashboard.avgCompleteness')}</span>
248
+ <span className="font-medium">{formatCompleteness(overview.submissions.avgCompleteness, t)}</span>
249
+ </div>
250
+ <StatusBreakdown
251
+ title={t('eudr.dashboard.submissionsByStatus')}
252
+ statuses={SUBMISSION_STATUSES}
253
+ byStatus={overview.submissions.byStatus}
254
+ labelPrefix="eudr.submissionStatus"
255
+ t={t}
256
+ />
257
+ </>
258
+ ) : null}
259
+ <StatusBreakdown
260
+ title={t('eudr.dashboard.statementsByStatus')}
261
+ statuses={STATEMENT_STATUSES}
262
+ byStatus={overview.statements.byStatus}
263
+ labelPrefix="eudr.statementStatus"
264
+ t={t}
265
+ />
266
+ </div>
267
+ </div>
268
+ )
269
+ }
270
+
271
+ export default EudrComplianceOverviewWidget
@@ -0,0 +1,24 @@
1
+ import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
2
+
3
+ export type EudrComplianceOverviewSettings = Record<string, never>
4
+
5
+ const EudrComplianceOverviewWidget = lazyDashboardWidget<EudrComplianceOverviewSettings>(() => import('./widget.client'))
6
+
7
+ const widget: DashboardWidgetModule<EudrComplianceOverviewSettings> = {
8
+ metadata: {
9
+ id: 'eudr.dashboard.complianceOverview',
10
+ title: 'EUDR compliance',
11
+ description: 'Track due diligence readiness, evidence completeness, and upcoming EUDR review work.',
12
+ features: ['dashboards.view', 'eudr.statements.view'],
13
+ defaultSize: 'md',
14
+ defaultEnabled: false,
15
+ defaultSettings: {},
16
+ tags: ['eudr', 'compliance'],
17
+ category: 'compliance',
18
+ icon: 'leaf',
19
+ supportsRefresh: true,
20
+ },
21
+ Widget: EudrComplianceOverviewWidget,
22
+ }
23
+
24
+ export default widget
@@ -0,0 +1,37 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
5
+ import { Tag } from '@open-mercato/ui/primitives/tag'
6
+
7
+ export type EudrProductColumnValue = {
8
+ commodity?: string | null
9
+ isInScope?: boolean | null
10
+ } | null | undefined
11
+
12
+ export default function EudrProductColumnWidget({ value }: { value: EudrProductColumnValue }) {
13
+ const t = useT()
14
+
15
+ if (!value || typeof value.commodity !== 'string' || value.commodity.length === 0) {
16
+ return (
17
+ <span className="text-muted-foreground" aria-label={t('eudr.productColumn.noMapping')}>
18
+ {t('eudr.common.empty')}
19
+ </span>
20
+ )
21
+ }
22
+
23
+ const inScope = value.isInScope !== false
24
+
25
+ return (
26
+ <span className="flex min-w-0 flex-wrap items-center gap-1.5">
27
+ <Tag variant={inScope ? 'success' : 'neutral'}>
28
+ {t(`eudr.commodity.${value.commodity}`)}
29
+ </Tag>
30
+ {!inScope ? (
31
+ <span className="text-xs text-muted-foreground">
32
+ {t('eudr.productColumn.outOfScope')}
33
+ </span>
34
+ ) : null}
35
+ </span>
36
+ )
37
+ }
@@ -0,0 +1,30 @@
1
+ import * as React from 'react'
2
+ import type { InjectionColumnWidget } from '@open-mercato/shared/modules/widgets/injection'
3
+ import EudrProductColumnWidget, { type EudrProductColumnValue } from './widget.client'
4
+
5
+ const widget: InjectionColumnWidget = {
6
+ metadata: {
7
+ id: 'eudr.injection.product-column',
8
+ title: 'EUDR product column',
9
+ description: 'Renders EUDR commodity and scope information on catalog product lists.',
10
+ features: ['eudr.mappings.view'],
11
+ priority: 50,
12
+ enabled: true,
13
+ },
14
+ columns: [
15
+ {
16
+ id: 'eudr.product-column',
17
+ header: 'eudr.productColumn.header',
18
+ accessorKey: '_eudr',
19
+ size: 180,
20
+ sortable: false,
21
+ cell: ({ getValue }) => {
22
+ return React.createElement(EudrProductColumnWidget, {
23
+ value: getValue() as EudrProductColumnValue,
24
+ })
25
+ },
26
+ },
27
+ ],
28
+ }
29
+
30
+ export default widget