@open-mercato/core 0.6.8-develop.6925.1.cefa200fa4 → 0.6.8-develop.6931.1.4a1e1c786b
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.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/eudr_due_diligence_statement/index.js +47 -0
- package/dist/generated/entities/eudr_due_diligence_statement/index.js.map +7 -0
- package/dist/generated/entities/eudr_evidence_submission/index.js +51 -0
- package/dist/generated/entities/eudr_evidence_submission/index.js.map +7 -0
- package/dist/generated/entities/eudr_mitigation_action/index.js +31 -0
- package/dist/generated/entities/eudr_mitigation_action/index.js.map +7 -0
- package/dist/generated/entities/eudr_plot/index.js +39 -0
- package/dist/generated/entities/eudr_plot/index.js.map +7 -0
- package/dist/generated/entities/eudr_product_mapping/index.js +31 -0
- package/dist/generated/entities/eudr_product_mapping/index.js.map +7 -0
- package/dist/generated/entities/eudr_risk_assessment/index.js +35 -0
- package/dist/generated/entities/eudr_risk_assessment/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +9 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +120 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/ui.js +3 -0
- package/dist/helpers/integration/ui.js.map +2 -2
- package/dist/modules/attachments/fields/attachment.js +5 -1
- package/dist/modules/attachments/fields/attachment.js.map +2 -2
- package/dist/modules/attachments/lib/crud.js +3 -1
- package/dist/modules/attachments/lib/crud.js.map +2 -2
- package/dist/modules/eudr/acl.js +43 -0
- package/dist/modules/eudr/acl.js.map +7 -0
- package/dist/modules/eudr/ai-agents.js +205 -0
- package/dist/modules/eudr/ai-agents.js.map +7 -0
- package/dist/modules/eudr/ai-tools/compliance-pack.js +495 -0
- package/dist/modules/eudr/ai-tools/compliance-pack.js.map +7 -0
- package/dist/modules/eudr/ai-tools/types.js +10 -0
- package/dist/modules/eudr/ai-tools/types.js.map +7 -0
- package/dist/modules/eudr/ai-tools.js +10 -0
- package/dist/modules/eudr/ai-tools.js.map +7 -0
- package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js +386 -0
- package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js.map +7 -0
- package/dist/modules/eudr/api/evidence-submissions/route.js +318 -0
- package/dist/modules/eudr/api/evidence-submissions/route.js.map +7 -0
- package/dist/modules/eudr/api/mitigation-actions/route.js +249 -0
- package/dist/modules/eudr/api/mitigation-actions/route.js.map +7 -0
- package/dist/modules/eudr/api/openapi.js +27 -0
- package/dist/modules/eudr/api/openapi.js.map +7 -0
- package/dist/modules/eudr/api/plots/import/route.js +294 -0
- package/dist/modules/eudr/api/plots/import/route.js.map +7 -0
- package/dist/modules/eudr/api/plots/route.js +279 -0
- package/dist/modules/eudr/api/plots/route.js.map +7 -0
- package/dist/modules/eudr/api/product-mappings/route.js +257 -0
- package/dist/modules/eudr/api/product-mappings/route.js.map +7 -0
- package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js +298 -0
- package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +7 -0
- package/dist/modules/eudr/api/product-mappings/suggestions/route.js +132 -0
- package/dist/modules/eudr/api/product-mappings/suggestions/route.js.map +7 -0
- package/dist/modules/eudr/api/reports/annual/route.js +266 -0
- package/dist/modules/eudr/api/reports/annual/route.js.map +7 -0
- package/dist/modules/eudr/api/risk-assessments/route.js +300 -0
- package/dist/modules/eudr/api/risk-assessments/route.js.map +7 -0
- package/dist/modules/eudr/api/statements/[id]/export/route.js +631 -0
- package/dist/modules/eudr/api/statements/[id]/export/route.js.map +7 -0
- package/dist/modules/eudr/api/statements/[id]/readiness/route.js +111 -0
- package/dist/modules/eudr/api/statements/[id]/readiness/route.js.map +7 -0
- package/dist/modules/eudr/api/statements/route.js +314 -0
- package/dist/modules/eudr/api/statements/route.js.map +7 -0
- package/dist/modules/eudr/api/suppliers/compliance/route.js +173 -0
- package/dist/modules/eudr/api/suppliers/compliance/route.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js +468 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js +351 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +313 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/page.js +360 -0
- package/dist/modules/eudr/backend/eudr/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/[id]/page.js +346 -0
- package/dist/modules/eudr/backend/eudr/plots/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/create/page.js +253 -0
- package/dist/modules/eudr/backend/eudr/plots/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js +386 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/plots/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/plots/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js +253 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js +174 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js +306 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js +335 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js +220 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +324 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/[id]/page.js +648 -0
- package/dist/modules/eudr/backend/eudr/statements/[id]/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/create/page.js +432 -0
- package/dist/modules/eudr/backend/eudr/statements/create/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js +17 -0
- package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js +309 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js.map +7 -0
- package/dist/modules/eudr/backend/eudr/statements/page.meta.js +16 -0
- package/dist/modules/eudr/backend/eudr/statements/page.meta.js.map +7 -0
- package/dist/modules/eudr/ce.js +56 -0
- package/dist/modules/eudr/ce.js.map +7 -0
- package/dist/modules/eudr/commands/evidence-submissions.js +571 -0
- package/dist/modules/eudr/commands/evidence-submissions.js.map +7 -0
- package/dist/modules/eudr/commands/index.js +7 -0
- package/dist/modules/eudr/commands/index.js.map +7 -0
- package/dist/modules/eudr/commands/lifecycle-events.js +19 -0
- package/dist/modules/eudr/commands/lifecycle-events.js.map +7 -0
- package/dist/modules/eudr/commands/mitigation-actions.js +488 -0
- package/dist/modules/eudr/commands/mitigation-actions.js.map +7 -0
- package/dist/modules/eudr/commands/plots.js +517 -0
- package/dist/modules/eudr/commands/plots.js.map +7 -0
- package/dist/modules/eudr/commands/product-mappings.js +468 -0
- package/dist/modules/eudr/commands/product-mappings.js.map +7 -0
- package/dist/modules/eudr/commands/risk-assessments.js +599 -0
- package/dist/modules/eudr/commands/risk-assessments.js.map +7 -0
- package/dist/modules/eudr/commands/statements.js +747 -0
- package/dist/modules/eudr/commands/statements.js.map +7 -0
- package/dist/modules/eudr/components/CountrySelectField.js +64 -0
- package/dist/modules/eudr/components/CountrySelectField.js.map +7 -0
- package/dist/modules/eudr/components/GeometryInput.js +133 -0
- package/dist/modules/eudr/components/GeometryInput.js.map +7 -0
- package/dist/modules/eudr/components/MappingSuggestionsDialog.js +307 -0
- package/dist/modules/eudr/components/MappingSuggestionsDialog.js.map +7 -0
- package/dist/modules/eudr/components/MitigationActionsSection.js +345 -0
- package/dist/modules/eudr/components/MitigationActionsSection.js.map +7 -0
- package/dist/modules/eudr/components/OrderSelectField.js +88 -0
- package/dist/modules/eudr/components/OrderSelectField.js.map +7 -0
- package/dist/modules/eudr/components/PlotImportDialog.js +229 -0
- package/dist/modules/eudr/components/PlotImportDialog.js.map +7 -0
- package/dist/modules/eudr/components/PlotMapPreview.js +35 -0
- package/dist/modules/eudr/components/PlotMapPreview.js.map +7 -0
- package/dist/modules/eudr/components/PlotMapPreviewImpl.js +97 -0
- package/dist/modules/eudr/components/PlotMapPreviewImpl.js.map +7 -0
- package/dist/modules/eudr/components/PlotMultiSelectField.js +198 -0
- package/dist/modules/eudr/components/PlotMultiSelectField.js.map +7 -0
- package/dist/modules/eudr/components/RiskCriteriaField.js +128 -0
- package/dist/modules/eudr/components/RiskCriteriaField.js.map +7 -0
- package/dist/modules/eudr/components/StatementLifecycleBar.js +274 -0
- package/dist/modules/eudr/components/StatementLifecycleBar.js.map +7 -0
- package/dist/modules/eudr/components/StatementReadinessChecklist.js +56 -0
- package/dist/modules/eudr/components/StatementReadinessChecklist.js.map +7 -0
- package/dist/modules/eudr/components/StatementRiskSection.js +179 -0
- package/dist/modules/eudr/components/StatementRiskSection.js.map +7 -0
- package/dist/modules/eudr/components/crudErrorI18n.js +31 -0
- package/dist/modules/eudr/components/crudErrorI18n.js.map +7 -0
- package/dist/modules/eudr/components/formConfig.js +593 -0
- package/dist/modules/eudr/components/formConfig.js.map +7 -0
- package/dist/modules/eudr/components/plotForm.js +68 -0
- package/dist/modules/eudr/components/plotForm.js.map +7 -0
- package/dist/modules/eudr/data/enrichers.js +62 -0
- package/dist/modules/eudr/data/enrichers.js.map +7 -0
- package/dist/modules/eudr/data/entities.js +437 -0
- package/dist/modules/eudr/data/entities.js.map +7 -0
- package/dist/modules/eudr/data/validators.js +271 -0
- package/dist/modules/eudr/data/validators.js.map +7 -0
- package/dist/modules/eudr/encryption.js +33 -0
- package/dist/modules/eudr/encryption.js.map +7 -0
- package/dist/modules/eudr/events.js +38 -0
- package/dist/modules/eudr/events.js.map +7 -0
- package/dist/modules/eudr/index.js +15 -0
- package/dist/modules/eudr/index.js.map +7 -0
- package/dist/modules/eudr/lib/annual-report.js +104 -0
- package/dist/modules/eudr/lib/annual-report.js.map +7 -0
- package/dist/modules/eudr/lib/completeness.js +64 -0
- package/dist/modules/eudr/lib/completeness.js.map +7 -0
- package/dist/modules/eudr/lib/detail-read-scope.js +16 -0
- package/dist/modules/eudr/lib/detail-read-scope.js.map +7 -0
- package/dist/modules/eudr/lib/geometry.js +142 -0
- package/dist/modules/eudr/lib/geometry.js.map +7 -0
- package/dist/modules/eudr/lib/notifications.js +56 -0
- package/dist/modules/eudr/lib/notifications.js.map +7 -0
- package/dist/modules/eudr/lib/plural.js +26 -0
- package/dist/modules/eudr/lib/plural.js.map +7 -0
- package/dist/modules/eudr/lib/reference-data.js +240 -0
- package/dist/modules/eudr/lib/reference-data.js.map +7 -0
- package/dist/modules/eudr/lib/species.js +10 -0
- package/dist/modules/eudr/lib/species.js.map +7 -0
- package/dist/modules/eudr/lib/statement-lifecycle.js +84 -0
- package/dist/modules/eudr/lib/statement-lifecycle.js.map +7 -0
- package/dist/modules/eudr/lib/statement-seeding.js +49 -0
- package/dist/modules/eudr/lib/statement-seeding.js.map +7 -0
- package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js +15 -0
- package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js.map +7 -0
- package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js +24 -0
- package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js.map +7 -0
- package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js +15 -0
- package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js.map +7 -0
- package/dist/modules/eudr/notifications.js +58 -0
- package/dist/modules/eudr/notifications.js.map +7 -0
- package/dist/modules/eudr/search.js +186 -0
- package/dist/modules/eudr/search.js.map +7 -0
- package/dist/modules/eudr/setup.js +12 -0
- package/dist/modules/eudr/setup.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-mitigation-completed.js +34 -0
- package/dist/modules/eudr/subscribers/notify-mitigation-completed.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-risk-concluded.js +35 -0
- package/dist/modules/eudr/subscribers/notify-risk-concluded.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js +37 -0
- package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-statement-submitted.js +34 -0
- package/dist/modules/eudr/subscribers/notify-statement-submitted.js.map +7 -0
- package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js +34 -0
- package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js.map +7 -0
- package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js +124 -0
- package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js.map +7 -0
- package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js +22 -0
- package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js.map +7 -0
- package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js +203 -0
- package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js.map +7 -0
- package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js +23 -0
- package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js +19 -0
- package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js +31 -0
- package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js +100 -0
- package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/order-compliance/widget.js +17 -0
- package/dist/modules/eudr/widgets/injection/order-compliance/widget.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js +116 -0
- package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js.map +7 -0
- package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js +17 -0
- package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js.map +7 -0
- package/dist/modules/eudr/widgets/injection-table.js +32 -0
- package/dist/modules/eudr/widgets/injection-table.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +67 -3
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +121 -48
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +17 -0
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +32 -18
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/data/entities.js +1 -0
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js +17 -0
- package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js.map +7 -0
- package/generated/entities/eudr_due_diligence_statement/index.ts +22 -0
- package/generated/entities/eudr_evidence_submission/index.ts +24 -0
- package/generated/entities/eudr_mitigation_action/index.ts +14 -0
- package/generated/entities/eudr_plot/index.ts +18 -0
- package/generated/entities/eudr_product_mapping/index.ts +14 -0
- package/generated/entities/eudr_risk_assessment/index.ts +16 -0
- package/generated/entities.ids.generated.ts +9 -0
- package/generated/entity-fields-registry.ts +120 -0
- package/package.json +7 -7
- package/src/helpers/integration/ui.ts +12 -0
- package/src/modules/attachments/fields/attachment.tsx +5 -0
- package/src/modules/attachments/lib/crud.ts +2 -0
- package/src/modules/eudr/acl.ts +39 -0
- package/src/modules/eudr/ai-agents.ts +258 -0
- package/src/modules/eudr/ai-tools/compliance-pack.ts +618 -0
- package/src/modules/eudr/ai-tools/types.ts +44 -0
- package/src/modules/eudr/ai-tools.ts +15 -0
- package/src/modules/eudr/api/dashboard/widgets/compliance-overview/route.ts +481 -0
- package/src/modules/eudr/api/evidence-submissions/route.ts +335 -0
- package/src/modules/eudr/api/mitigation-actions/route.ts +263 -0
- package/src/modules/eudr/api/openapi.ts +28 -0
- package/src/modules/eudr/api/plots/import/route.ts +369 -0
- package/src/modules/eudr/api/plots/route.ts +296 -0
- package/src/modules/eudr/api/product-mappings/route.ts +269 -0
- package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +382 -0
- package/src/modules/eudr/api/product-mappings/suggestions/route.ts +169 -0
- package/src/modules/eudr/api/reports/annual/route.ts +457 -0
- package/src/modules/eudr/api/risk-assessments/route.ts +323 -0
- package/src/modules/eudr/api/statements/[id]/export/route.ts +713 -0
- package/src/modules/eudr/api/statements/[id]/readiness/route.ts +129 -0
- package/src/modules/eudr/api/statements/route.ts +329 -0
- package/src/modules/eudr/api/suppliers/compliance/route.ts +241 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.tsx +545 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.tsx +383 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +379 -0
- package/src/modules/eudr/backend/eudr/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/page.tsx +477 -0
- package/src/modules/eudr/backend/eudr/plots/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/plots/[id]/page.tsx +404 -0
- package/src/modules/eudr/backend/eudr/plots/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/plots/create/page.tsx +267 -0
- package/src/modules/eudr/backend/eudr/plots/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/plots/page.tsx +442 -0
- package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.tsx +311 -0
- package/src/modules/eudr/backend/eudr/product-mappings/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/product-mappings/create/page.tsx +190 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +344 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.tsx +421 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/create/page.tsx +247 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +383 -0
- package/src/modules/eudr/backend/eudr/statements/[id]/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/statements/[id]/page.tsx +777 -0
- package/src/modules/eudr/backend/eudr/statements/create/page.meta.ts +13 -0
- package/src/modules/eudr/backend/eudr/statements/create/page.tsx +511 -0
- package/src/modules/eudr/backend/eudr/statements/page.meta.ts +12 -0
- package/src/modules/eudr/backend/eudr/statements/page.tsx +372 -0
- package/src/modules/eudr/ce.ts +52 -0
- package/src/modules/eudr/commands/evidence-submissions.ts +699 -0
- package/src/modules/eudr/commands/index.ts +6 -0
- package/src/modules/eudr/commands/lifecycle-events.ts +28 -0
- package/src/modules/eudr/commands/mitigation-actions.ts +574 -0
- package/src/modules/eudr/commands/plots.ts +627 -0
- package/src/modules/eudr/commands/product-mappings.ts +556 -0
- package/src/modules/eudr/commands/risk-assessments.ts +728 -0
- package/src/modules/eudr/commands/statements.ts +933 -0
- package/src/modules/eudr/components/CountrySelectField.tsx +77 -0
- package/src/modules/eudr/components/GeometryInput.tsx +170 -0
- package/src/modules/eudr/components/MappingSuggestionsDialog.tsx +385 -0
- package/src/modules/eudr/components/MitigationActionsSection.tsx +417 -0
- package/src/modules/eudr/components/OrderSelectField.tsx +116 -0
- package/src/modules/eudr/components/PlotImportDialog.tsx +277 -0
- package/src/modules/eudr/components/PlotMapPreview.tsx +46 -0
- package/src/modules/eudr/components/PlotMapPreviewImpl.tsx +111 -0
- package/src/modules/eudr/components/PlotMultiSelectField.tsx +238 -0
- package/src/modules/eudr/components/RiskCriteriaField.tsx +173 -0
- package/src/modules/eudr/components/StatementLifecycleBar.tsx +363 -0
- package/src/modules/eudr/components/StatementReadinessChecklist.tsx +82 -0
- package/src/modules/eudr/components/StatementRiskSection.tsx +242 -0
- package/src/modules/eudr/components/crudErrorI18n.ts +36 -0
- package/src/modules/eudr/components/formConfig.tsx +717 -0
- package/src/modules/eudr/components/plotForm.ts +75 -0
- package/src/modules/eudr/data/enrichers.ts +82 -0
- package/src/modules/eudr/data/entities.ts +369 -0
- package/src/modules/eudr/data/validators.ts +357 -0
- package/src/modules/eudr/encryption.ts +31 -0
- package/src/modules/eudr/events.ts +38 -0
- package/src/modules/eudr/i18n/de.json +747 -0
- package/src/modules/eudr/i18n/en.json +747 -0
- package/src/modules/eudr/i18n/es.json +747 -0
- package/src/modules/eudr/i18n/ko.json +747 -0
- package/src/modules/eudr/i18n/pl.json +747 -0
- package/src/modules/eudr/index.ts +13 -0
- package/src/modules/eudr/lib/annual-report.ts +120 -0
- package/src/modules/eudr/lib/completeness.ts +90 -0
- package/src/modules/eudr/lib/detail-read-scope.ts +44 -0
- package/src/modules/eudr/lib/geometry.ts +191 -0
- package/src/modules/eudr/lib/notifications.ts +85 -0
- package/src/modules/eudr/lib/plural.ts +36 -0
- package/src/modules/eudr/lib/reference-data.ts +128 -0
- package/src/modules/eudr/lib/species.ts +12 -0
- package/src/modules/eudr/lib/statement-lifecycle.ts +109 -0
- package/src/modules/eudr/lib/statement-seeding.ts +86 -0
- package/src/modules/eudr/migrations/.snapshot-open-mercato.json +2046 -0
- package/src/modules/eudr/migrations/Migration20260706102002_eudr.ts +16 -0
- package/src/modules/eudr/migrations/Migration20260706152612_eudr.ts +30 -0
- package/src/modules/eudr/migrations/Migration20260722100000_eudr.ts +17 -0
- package/src/modules/eudr/notifications.ts +56 -0
- package/src/modules/eudr/search.ts +212 -0
- package/src/modules/eudr/setup.ts +10 -0
- package/src/modules/eudr/subscribers/notify-mitigation-completed.ts +56 -0
- package/src/modules/eudr/subscribers/notify-risk-concluded.ts +58 -0
- package/src/modules/eudr/subscribers/notify-statement-reference-issued.ts +59 -0
- package/src/modules/eudr/subscribers/notify-statement-submitted.ts +49 -0
- package/src/modules/eudr/subscribers/notify-statement-withdrawn.ts +49 -0
- package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-created.ts +189 -0
- package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.ts +31 -0
- package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.client.tsx +271 -0
- package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.ts +24 -0
- package/src/modules/eudr/widgets/injection/eudr-product-column/widget.client.tsx +37 -0
- package/src/modules/eudr/widgets/injection/eudr-product-column/widget.ts +30 -0
- package/src/modules/eudr/widgets/injection/order-compliance/widget.client.tsx +131 -0
- package/src/modules/eudr/widgets/injection/order-compliance/widget.ts +16 -0
- package/src/modules/eudr/widgets/injection/supplier-compliance/widget.client.tsx +168 -0
- package/src/modules/eudr/widgets/injection/supplier-compliance/widget.ts +16 -0
- package/src/modules/eudr/widgets/injection-table.ts +31 -0
- package/src/modules/notifications/lib/notificationService.ts +83 -4
- package/src/modules/query_index/lib/engine.ts +139 -51
- package/src/modules/sales/api/documents/factory.ts +29 -0
- package/src/modules/sales/commands/documents.ts +65 -18
- package/src/modules/sales/data/entities.ts +1 -0
- package/src/modules/sales/migrations/.snapshot-open-mercato.json +10 -0
- package/src/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.ts +59 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/components/PlotMultiSelectField.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Plus, X } from 'lucide-react'\nimport { resolveCountryName } from '@open-mercato/shared/lib/location/countries'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { LookupSelect, type LookupSelectItem } from '@open-mercato/ui/backend/inputs'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { PICKER_PAGE_SIZE } from './formConfig'\nimport { translatePlural } from '../lib/plural'\n\ntype PlotOption = {\n id: string\n name: string\n originCountry: string | null\n plotType: string | null\n areaHa: number | string | null\n}\n\ntype PlotListResponse = {\n items?: unknown[]\n}\n\nexport type PlotMultiSelectFieldProps = {\n id: string\n value: string[]\n onChange: (value: string[]) => void\n supplierEntityId?: string | null\n disabled?: boolean\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction readString(record: Record<string, unknown>, key: string): string | null {\n const value = record[key]\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null\n}\n\nfunction normalizePlotOption(raw: unknown): PlotOption | null {\n if (!isRecord(raw)) return null\n const id = readString(raw, 'id')\n const name = readString(raw, 'name')\n if (!id || !name) return null\n const areaHa = raw.areaHa\n return {\n id,\n name,\n originCountry: readString(raw, 'originCountry'),\n plotType: readString(raw, 'plotType'),\n areaHa: typeof areaHa === 'number' || typeof areaHa === 'string' ? areaHa : null,\n }\n}\n\nfunction formatArea(value: PlotOption['areaHa'], emptyLabel: string): string {\n if (value === null || value === undefined || value === '') return emptyLabel\n const numeric = typeof value === 'number' ? value : Number(value)\n if (!Number.isFinite(numeric)) return String(value)\n return new Intl.NumberFormat(undefined, { maximumFractionDigits: 4 }).format(numeric)\n}\n\nexport function PlotMultiSelectField({\n id,\n value,\n onChange,\n supplierEntityId,\n disabled,\n}: PlotMultiSelectFieldProps) {\n const translate = useT()\n const locale = useLocale()\n const router = useRouter()\n const [plotNames, setPlotNames] = React.useState<Record<string, string | null>>({})\n const selectedPlotIds = React.useMemo(() => (Array.isArray(value) ? value : []), [value])\n const selectedIds = React.useMemo(() => new Set(selectedPlotIds), [selectedPlotIds])\n const normalizedSupplierId = typeof supplierEntityId === 'string' && supplierEntityId.trim().length > 0\n ? supplierEntityId.trim()\n : null\n const previousSupplierIdRef = React.useRef(normalizedSupplierId)\n\n React.useEffect(() => {\n const previousSupplierId = previousSupplierIdRef.current\n previousSupplierIdRef.current = normalizedSupplierId\n if (previousSupplierId === normalizedSupplierId || selectedPlotIds.length === 0) return\n onChange([])\n }, [normalizedSupplierId, onChange, selectedPlotIds.length])\n\n React.useEffect(() => {\n const missing = selectedPlotIds.filter((plotId) => !(plotId in plotNames))\n if (!missing.length) return\n let cancelled = false\n async function resolveNames() {\n const params = new URLSearchParams({ ids: missing.join(','), pageSize: '100' })\n const call = await apiCall<PlotListResponse>(\n `/api/eudr/plots?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n if (cancelled) return\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const resolved: Record<string, string | null> = {}\n for (const plotId of missing) resolved[plotId] = null\n for (const item of items) {\n const option = normalizePlotOption(item)\n if (option) resolved[option.id] = option.name\n }\n setPlotNames((current) => ({ ...current, ...resolved }))\n }\n resolveNames().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [plotNames, selectedPlotIds])\n\n const plotSubtitle = React.useCallback((plot: PlotOption): string => {\n const country = plot.originCountry\n ? `${resolveCountryName(plot.originCountry, { locale })} (${plot.originCountry})`\n : translate('eudr.common.empty')\n const plotType = plot.plotType ?? 'point'\n const area = translate('eudr.plots.list.areaHaValue', {\n value: formatArea(plot.areaHa, translate('eudr.common.empty')),\n })\n return `${country} - ${translate(`eudr.plotType.${plotType}`)} - ${area}`\n }, [locale, translate])\n\n const fetchPlotItems = React.useCallback(async (query: string): Promise<LookupSelectItem[]> => {\n if (!normalizedSupplierId) return []\n const params = new URLSearchParams({\n page: '1',\n pageSize: String(PICKER_PAGE_SIZE),\n supplierEntityId: normalizedSupplierId,\n isActive: 'true',\n })\n if (query) params.set('search', query)\n const call = await apiCall<PlotListResponse>(\n `/api/eudr/plots?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n if (!call.ok) {\n flash(translate('eudr.evidenceSubmissions.form.plotsLoadError'), 'error')\n return []\n }\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const options = items\n .map((item) => normalizePlotOption(item))\n .filter((option): option is PlotOption => option !== null)\n setPlotNames((current) => {\n const next = { ...current }\n for (const option of options) next[option.id] = option.name\n return next\n })\n return options.map((option) => ({\n id: option.id,\n title: option.name,\n subtitle: plotSubtitle(option),\n disabled: selectedIds.has(option.id),\n }))\n }, [normalizedSupplierId, plotSubtitle, selectedIds, translate])\n\n const addPlot = React.useCallback((plotId: string | null) => {\n if (!plotId || selectedIds.has(plotId)) return\n onChange([...selectedPlotIds, plotId])\n }, [onChange, selectedIds, selectedPlotIds])\n\n const removePlot = React.useCallback((plotId: string) => {\n onChange(selectedPlotIds.filter((entry) => entry !== plotId))\n }, [onChange, selectedPlotIds])\n\n return (\n <div id={id} className=\"space-y-3\">\n {!normalizedSupplierId ? (\n <p className=\"rounded-md border border-dashed border-border/70 bg-muted/30 px-3 py-2 text-sm text-muted-foreground\">\n {translate('eudr.evidenceSubmissions.form.plotsSupplierHint')}\n </p>\n ) : (\n <>\n <div className=\"flex items-center justify-between gap-3\">\n <p className=\"text-sm text-muted-foreground\">\n {translatePlural(translate, locale, 'eudr.evidenceSubmissions.form.plotsSelectedCount', selectedPlotIds.length)}\n </p>\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"sm\"\n onClick={() => router.push('/backend/eudr/plots/create')}\n >\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('eudr.plots.list.actions.create')}\n </Button>\n </div>\n {selectedPlotIds.length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {value\n .filter((plotId) => plotId in plotNames)\n .map((plotId) => {\n const name = plotNames[plotId] ?? translate('eudr.common.recordUnavailable')\n return (\n <span\n key={plotId}\n className=\"inline-flex items-center gap-1 rounded-full border border-border bg-muted/30 py-0.5 pl-3 pr-1 text-sm text-foreground\"\n >\n <span className=\"max-w-56 truncate\">{name}</span>\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n disabled={disabled}\n aria-label={translate('eudr.evidenceSubmissions.form.plotsRemove', { name })}\n onClick={() => removePlot(plotId)}\n >\n <X className=\"size-3\" aria-hidden=\"true\" />\n </IconButton>\n </span>\n )\n })}\n </div>\n ) : null}\n <LookupSelect\n key={normalizedSupplierId}\n value={null}\n minQuery={0}\n disabled={disabled}\n searchPlaceholder={translate('eudr.plots.list.searchPlaceholder')}\n fetchItems={fetchPlotItems}\n onChange={addPlot}\n />\n </>\n )}\n </div>\n )\n}\n\nexport default PlotMultiSelectField\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
5
|
+
import { Alert } from "@open-mercato/ui/primitives/alert";
|
|
6
|
+
import { Input } from "@open-mercato/ui/primitives/input";
|
|
7
|
+
import { Label } from "@open-mercato/ui/primitives/label";
|
|
8
|
+
import {
|
|
9
|
+
SegmentedControl,
|
|
10
|
+
SegmentedControlItem
|
|
11
|
+
} from "@open-mercato/ui/primitives/segmented-control";
|
|
12
|
+
import { EUDR_RISK_CRITERIA_GROUPS } from "../lib/reference-data.js";
|
|
13
|
+
import {
|
|
14
|
+
EUDR_CRITERIA_ANSWERS
|
|
15
|
+
} from "../data/validators.js";
|
|
16
|
+
const criteriaKeys = new Set(
|
|
17
|
+
EUDR_RISK_CRITERIA_GROUPS.flatMap((group) => [...group.criteria])
|
|
18
|
+
);
|
|
19
|
+
function isRecord(value) {
|
|
20
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
21
|
+
}
|
|
22
|
+
function isCriteriaAnswer(value) {
|
|
23
|
+
return typeof value === "string" && EUDR_CRITERIA_ANSWERS.some((answer) => answer === value);
|
|
24
|
+
}
|
|
25
|
+
function normalizeCriteriaValue(value) {
|
|
26
|
+
if (!isRecord(value)) return {};
|
|
27
|
+
const normalized = {};
|
|
28
|
+
for (const [key, rawEntry] of Object.entries(value)) {
|
|
29
|
+
if (!criteriaKeys.has(key) || !isRecord(rawEntry) || !isCriteriaAnswer(rawEntry.answer)) continue;
|
|
30
|
+
const note = typeof rawEntry.note === "string" && rawEntry.note.trim().length > 0 ? rawEntry.note : null;
|
|
31
|
+
normalized[key] = note ? { answer: rawEntry.answer, note } : { answer: rawEntry.answer };
|
|
32
|
+
}
|
|
33
|
+
return normalized;
|
|
34
|
+
}
|
|
35
|
+
function countAnsweredCriteria(value) {
|
|
36
|
+
const criteria = normalizeCriteriaValue(value);
|
|
37
|
+
return { answered: Object.keys(criteria).length, total: criteriaKeys.size };
|
|
38
|
+
}
|
|
39
|
+
function RiskConclusionCriteriaWarning({
|
|
40
|
+
conclusion,
|
|
41
|
+
criteria
|
|
42
|
+
}) {
|
|
43
|
+
const translate = useT();
|
|
44
|
+
if (conclusion !== "negligible") return null;
|
|
45
|
+
const { answered, total } = countAnsweredCriteria(criteria);
|
|
46
|
+
if (answered >= total) return null;
|
|
47
|
+
return /* @__PURE__ */ jsx(Alert, { status: "warning", style: "lighter", children: /* @__PURE__ */ jsx("div", { className: "text-sm leading-5", children: translate("eudr.riskAssessments.form.negligibleCriteriaWarning", { answered, total }) }) });
|
|
48
|
+
}
|
|
49
|
+
function RiskCriteriaField({
|
|
50
|
+
id,
|
|
51
|
+
value,
|
|
52
|
+
onChange,
|
|
53
|
+
disabled
|
|
54
|
+
}) {
|
|
55
|
+
const translate = useT();
|
|
56
|
+
const criteria = React.useMemo(() => normalizeCriteriaValue(value), [value]);
|
|
57
|
+
const total = criteriaKeys.size;
|
|
58
|
+
const answered = Object.keys(criteria).filter((key) => criteriaKeys.has(key)).length;
|
|
59
|
+
const updateAnswer = React.useCallback((criterionKey, answer) => {
|
|
60
|
+
const current = criteria[criterionKey];
|
|
61
|
+
const next = { ...criteria };
|
|
62
|
+
const note = answer === "concern" && current?.note ? current.note : null;
|
|
63
|
+
next[criterionKey] = note ? { answer, note } : { answer };
|
|
64
|
+
onChange(next);
|
|
65
|
+
}, [criteria, onChange]);
|
|
66
|
+
const updateNote = React.useCallback((criterionKey, note) => {
|
|
67
|
+
const current = criteria[criterionKey];
|
|
68
|
+
if (!current || current.answer !== "concern") return;
|
|
69
|
+
const trimmed = note.trim();
|
|
70
|
+
onChange({
|
|
71
|
+
...criteria,
|
|
72
|
+
[criterionKey]: trimmed ? { answer: current.answer, note } : { answer: current.answer }
|
|
73
|
+
});
|
|
74
|
+
}, [criteria, onChange]);
|
|
75
|
+
return /* @__PURE__ */ jsxs("div", { id, className: "space-y-5", children: [
|
|
76
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: translate("eudr.risk.criteria.answeredCount", { answered, total }) }),
|
|
77
|
+
EUDR_RISK_CRITERIA_GROUPS.map((group) => /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
|
|
78
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold", children: translate(`eudr.risk.criteriaGroup.${group.key}`) }),
|
|
79
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: group.criteria.map((criterionKey) => {
|
|
80
|
+
const entry = criteria[criterionKey];
|
|
81
|
+
const criterionId = `${id}-${criterionKey}`;
|
|
82
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-md border border-border bg-background p-3", children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 lg:flex-row lg:items-center lg:justify-between", children: [
|
|
84
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: criterionId, className: "text-sm font-medium", children: translate(`eudr.risk.criteria.${criterionKey}`) }),
|
|
85
|
+
/* @__PURE__ */ jsx(
|
|
86
|
+
SegmentedControl,
|
|
87
|
+
{
|
|
88
|
+
id: criterionId,
|
|
89
|
+
value: entry?.answer,
|
|
90
|
+
onValueChange: (nextValue) => {
|
|
91
|
+
if (isCriteriaAnswer(nextValue)) updateAnswer(criterionKey, nextValue);
|
|
92
|
+
},
|
|
93
|
+
disabled,
|
|
94
|
+
"aria-label": translate(`eudr.risk.criteria.${criterionKey}`),
|
|
95
|
+
children: EUDR_CRITERIA_ANSWERS.map((answer) => /* @__PURE__ */ jsx(
|
|
96
|
+
SegmentedControlItem,
|
|
97
|
+
{
|
|
98
|
+
value: answer,
|
|
99
|
+
className: answer === "concern" ? "data-[state=checked]:bg-status-warning-bg data-[state=checked]:text-status-warning-text" : void 0,
|
|
100
|
+
children: translate(`eudr.risk.criteriaAnswer.${answer}`)
|
|
101
|
+
},
|
|
102
|
+
answer
|
|
103
|
+
))
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
] }),
|
|
107
|
+
entry?.answer === "concern" ? /* @__PURE__ */ jsx(
|
|
108
|
+
Input,
|
|
109
|
+
{
|
|
110
|
+
value: entry.note ?? "",
|
|
111
|
+
disabled,
|
|
112
|
+
placeholder: translate("eudr.risk.criteria.notePlaceholder"),
|
|
113
|
+
onChange: (event) => updateNote(criterionKey, event.target.value)
|
|
114
|
+
}
|
|
115
|
+
) : null
|
|
116
|
+
] }, criterionKey);
|
|
117
|
+
}) })
|
|
118
|
+
] }, group.key))
|
|
119
|
+
] });
|
|
120
|
+
}
|
|
121
|
+
var RiskCriteriaField_default = RiskCriteriaField;
|
|
122
|
+
export {
|
|
123
|
+
RiskConclusionCriteriaWarning,
|
|
124
|
+
RiskCriteriaField,
|
|
125
|
+
countAnsweredCriteria,
|
|
126
|
+
RiskCriteriaField_default as default
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=RiskCriteriaField.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/components/RiskCriteriaField.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport {\n SegmentedControl,\n SegmentedControlItem,\n} from '@open-mercato/ui/primitives/segmented-control'\nimport { EUDR_RISK_CRITERIA_GROUPS } from '../lib/reference-data'\nimport {\n EUDR_CRITERIA_ANSWERS,\n type EudrCriteriaAnswer,\n} from '../data/validators'\n\nexport type RiskCriteriaEntry = {\n answer: EudrCriteriaAnswer\n note?: string | null\n}\n\nexport type RiskCriteriaValue = Record<string, RiskCriteriaEntry>\n\nexport type RiskCriteriaFieldProps = {\n id: string\n value: unknown\n onChange: (value: RiskCriteriaValue) => void\n disabled?: boolean\n}\n\nconst criteriaKeys = new Set<string>(\n EUDR_RISK_CRITERIA_GROUPS.flatMap((group) => [...group.criteria]),\n)\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isCriteriaAnswer(value: unknown): value is EudrCriteriaAnswer {\n return typeof value === 'string' && EUDR_CRITERIA_ANSWERS.some((answer) => answer === value)\n}\n\nfunction normalizeCriteriaValue(value: unknown): RiskCriteriaValue {\n if (!isRecord(value)) return {}\n const normalized: RiskCriteriaValue = {}\n for (const [key, rawEntry] of Object.entries(value)) {\n if (!criteriaKeys.has(key) || !isRecord(rawEntry) || !isCriteriaAnswer(rawEntry.answer)) continue\n const note = typeof rawEntry.note === 'string' && rawEntry.note.trim().length > 0\n ? rawEntry.note\n : null\n normalized[key] = note ? { answer: rawEntry.answer, note } : { answer: rawEntry.answer }\n }\n return normalized\n}\n\nexport function countAnsweredCriteria(value: unknown): { answered: number; total: number } {\n const criteria = normalizeCriteriaValue(value)\n return { answered: Object.keys(criteria).length, total: criteriaKeys.size }\n}\n\nexport function RiskConclusionCriteriaWarning({\n conclusion,\n criteria,\n}: {\n conclusion: unknown\n criteria: unknown\n}) {\n const translate = useT()\n if (conclusion !== 'negligible') return null\n const { answered, total } = countAnsweredCriteria(criteria)\n if (answered >= total) return null\n return (\n <Alert status=\"warning\" style=\"lighter\">\n <div className=\"text-sm leading-5\">\n {translate('eudr.riskAssessments.form.negligibleCriteriaWarning', { answered, total })}\n </div>\n </Alert>\n )\n}\n\nexport function RiskCriteriaField({\n id,\n value,\n onChange,\n disabled,\n}: RiskCriteriaFieldProps) {\n const translate = useT()\n const criteria = React.useMemo(() => normalizeCriteriaValue(value), [value])\n const total = criteriaKeys.size\n const answered = Object.keys(criteria).filter((key) => criteriaKeys.has(key)).length\n\n const updateAnswer = React.useCallback((criterionKey: string, answer: EudrCriteriaAnswer) => {\n const current = criteria[criterionKey]\n const next: RiskCriteriaValue = { ...criteria }\n const note = answer === 'concern' && current?.note ? current.note : null\n next[criterionKey] = note ? { answer, note } : { answer }\n onChange(next)\n }, [criteria, onChange])\n\n const updateNote = React.useCallback((criterionKey: string, note: string) => {\n const current = criteria[criterionKey]\n if (!current || current.answer !== 'concern') return\n const trimmed = note.trim()\n onChange({\n ...criteria,\n [criterionKey]: trimmed\n ? { answer: current.answer, note }\n : { answer: current.answer },\n })\n }, [criteria, onChange])\n\n return (\n <div id={id} className=\"space-y-5\">\n <div className=\"text-sm text-muted-foreground\">\n {translate('eudr.risk.criteria.answeredCount', { answered, total })}\n </div>\n {EUDR_RISK_CRITERIA_GROUPS.map((group) => (\n <section key={group.key} className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">\n {translate(`eudr.risk.criteriaGroup.${group.key}`)}\n </h3>\n <div className=\"space-y-3\">\n {group.criteria.map((criterionKey) => {\n const entry = criteria[criterionKey]\n const criterionId = `${id}-${criterionKey}`\n return (\n <div key={criterionKey} className=\"space-y-2 rounded-md border border-border bg-background p-3\">\n <div className=\"flex flex-col gap-2 lg:flex-row lg:items-center lg:justify-between\">\n <Label htmlFor={criterionId} className=\"text-sm font-medium\">\n {translate(`eudr.risk.criteria.${criterionKey}`)}\n </Label>\n <SegmentedControl\n id={criterionId}\n value={entry?.answer}\n onValueChange={(nextValue) => {\n if (isCriteriaAnswer(nextValue)) updateAnswer(criterionKey, nextValue)\n }}\n disabled={disabled}\n aria-label={translate(`eudr.risk.criteria.${criterionKey}`)}\n >\n {EUDR_CRITERIA_ANSWERS.map((answer) => (\n <SegmentedControlItem\n key={answer}\n value={answer}\n className={answer === 'concern'\n ? 'data-[state=checked]:bg-status-warning-bg data-[state=checked]:text-status-warning-text'\n : undefined}\n >\n {translate(`eudr.risk.criteriaAnswer.${answer}`)}\n </SegmentedControlItem>\n ))}\n </SegmentedControl>\n </div>\n {entry?.answer === 'concern' ? (\n <Input\n value={entry.note ?? ''}\n disabled={disabled}\n placeholder={translate('eudr.risk.criteria.notePlaceholder')}\n onChange={(event) => updateNote(criterionKey, event.target.value)}\n />\n ) : null}\n </div>\n )\n })}\n </div>\n </section>\n ))}\n </div>\n )\n}\n\nexport default RiskCriteriaField\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { CheckCircle2 } from "lucide-react";
|
|
5
|
+
import { useLocale, useT } from "@open-mercato/shared/lib/i18n/context";
|
|
6
|
+
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
|
|
7
|
+
import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
|
|
8
|
+
import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
|
|
9
|
+
import { buildOptimisticLockHeader, extractOptimisticLockConflict } from "@open-mercato/ui/backend/utils/optimisticLock";
|
|
10
|
+
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
11
|
+
import { updateCrud } from "@open-mercato/ui/backend/utils/crud";
|
|
12
|
+
import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
13
|
+
import { withScopedApiRequestHeaders } from "@open-mercato/ui/backend/utils/apiCall";
|
|
14
|
+
import {
|
|
15
|
+
Alert,
|
|
16
|
+
AlertTitle
|
|
17
|
+
} from "@open-mercato/ui/primitives/alert";
|
|
18
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
19
|
+
import {
|
|
20
|
+
Dialog,
|
|
21
|
+
DialogContent,
|
|
22
|
+
DialogHeader,
|
|
23
|
+
DialogTitle
|
|
24
|
+
} from "@open-mercato/ui/primitives/dialog";
|
|
25
|
+
import { StatusBadge } from "@open-mercato/ui/primitives/status-badge";
|
|
26
|
+
import {
|
|
27
|
+
EUDR_AMEND_WINDOW_MS,
|
|
28
|
+
EUDR_STATEMENT_TRANSITIONS
|
|
29
|
+
} from "../lib/statement-lifecycle.js";
|
|
30
|
+
import { statusBadgeVariant } from "./formConfig.js";
|
|
31
|
+
function isRecord(value) {
|
|
32
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
33
|
+
}
|
|
34
|
+
function extractGateReasons(error) {
|
|
35
|
+
const candidates = [];
|
|
36
|
+
if (isRecord(error)) {
|
|
37
|
+
candidates.push(error.details);
|
|
38
|
+
candidates.push(error);
|
|
39
|
+
}
|
|
40
|
+
for (const candidate of candidates) {
|
|
41
|
+
if (!isRecord(candidate) || !Array.isArray(candidate.reasons)) continue;
|
|
42
|
+
return candidate.reasons.filter((reason) => typeof reason === "string" && reason.trim().length > 0).map((reason) => reason.startsWith("eudr.") ? reason : `eudr.gate.${reason}`);
|
|
43
|
+
}
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
function parseDate(value) {
|
|
47
|
+
if (!value) return null;
|
|
48
|
+
const date = new Date(value);
|
|
49
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
50
|
+
}
|
|
51
|
+
function addYears(date, years) {
|
|
52
|
+
const next = new Date(date);
|
|
53
|
+
next.setFullYear(next.getFullYear() + years);
|
|
54
|
+
return next;
|
|
55
|
+
}
|
|
56
|
+
function remainingParts(ms) {
|
|
57
|
+
const totalMinutes = Math.max(0, Math.ceil(ms / 6e4));
|
|
58
|
+
return { hours: Math.floor(totalMinutes / 60), minutes: totalMinutes % 60 };
|
|
59
|
+
}
|
|
60
|
+
function toDateTimeLocalInput(date) {
|
|
61
|
+
const offsetMs = date.getTimezoneOffset() * 6e4;
|
|
62
|
+
return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16);
|
|
63
|
+
}
|
|
64
|
+
function optionalText(value) {
|
|
65
|
+
if (typeof value !== "string") return null;
|
|
66
|
+
const trimmed = value.trim();
|
|
67
|
+
return trimmed.length ? trimmed : null;
|
|
68
|
+
}
|
|
69
|
+
function transitionActionKey(status) {
|
|
70
|
+
return `eudr.lifecycle.actions.to${status.charAt(0).toUpperCase()}${status.slice(1)}`;
|
|
71
|
+
}
|
|
72
|
+
const confirmTitleKeys = {
|
|
73
|
+
draft: "eudr.lifecycle.confirmReturnToDraft",
|
|
74
|
+
submitted: "eudr.lifecycle.confirmSubmit",
|
|
75
|
+
available: "eudr.lifecycle.confirmMarkAvailable",
|
|
76
|
+
withdrawn: "eudr.lifecycle.confirmWithdraw",
|
|
77
|
+
archived: "eudr.lifecycle.confirmArchive"
|
|
78
|
+
};
|
|
79
|
+
const confirmBodyKeys = {
|
|
80
|
+
draft: "eudr.lifecycle.confirmReturnToDraftBody",
|
|
81
|
+
submitted: "eudr.lifecycle.confirmSubmitBody",
|
|
82
|
+
available: "eudr.lifecycle.confirmMarkAvailableBody",
|
|
83
|
+
withdrawn: "eudr.lifecycle.confirmWithdrawBody",
|
|
84
|
+
archived: "eudr.lifecycle.confirmArchiveBody"
|
|
85
|
+
};
|
|
86
|
+
function StatementLifecycleBar({
|
|
87
|
+
statement,
|
|
88
|
+
speciesMissing = false,
|
|
89
|
+
onChanged
|
|
90
|
+
}) {
|
|
91
|
+
const translate = useT();
|
|
92
|
+
const locale = useLocale();
|
|
93
|
+
const { confirm, ConfirmDialogElement } = useConfirmDialog();
|
|
94
|
+
const [now, setNow] = React.useState(() => /* @__PURE__ */ new Date());
|
|
95
|
+
const [referenceDialogOpen, setReferenceDialogOpen] = React.useState(false);
|
|
96
|
+
const [gateReasons, setGateReasons] = React.useState([]);
|
|
97
|
+
const mutationContextId = `eudr-statement-lifecycle:${statement.id}`;
|
|
98
|
+
const { runMutation, retryLastMutation } = useGuardedMutation({
|
|
99
|
+
contextId: mutationContextId,
|
|
100
|
+
blockedMessage: translate("ui.forms.flash.saveBlocked")
|
|
101
|
+
});
|
|
102
|
+
React.useEffect(() => {
|
|
103
|
+
if (statement.status !== "available") return;
|
|
104
|
+
const interval = window.setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
105
|
+
setNow(/* @__PURE__ */ new Date());
|
|
106
|
+
return () => window.clearInterval(interval);
|
|
107
|
+
}, [statement.status, statement.referenceIssuedAt]);
|
|
108
|
+
const issuedAt = parseDate(statement.referenceIssuedAt);
|
|
109
|
+
const submittedAt = parseDate(statement.submittedAt);
|
|
110
|
+
const amendRemainingMs = statement.status === "available" && issuedAt ? issuedAt.getTime() + EUDR_AMEND_WINDOW_MS - now.getTime() : 0;
|
|
111
|
+
const amendWindowOpen = statement.status === "available" && issuedAt !== null && now.getTime() >= issuedAt.getTime() && amendRemainingMs > 0;
|
|
112
|
+
const retainUntil = submittedAt ? addYears(submittedAt, 5) : null;
|
|
113
|
+
const performTransition = React.useCallback(async (nextStatus, extraPayload) => {
|
|
114
|
+
setGateReasons([]);
|
|
115
|
+
try {
|
|
116
|
+
await runMutation({
|
|
117
|
+
operation: () => withScopedApiRequestHeaders(
|
|
118
|
+
buildOptimisticLockHeader(statement.updatedAt),
|
|
119
|
+
() => updateCrud("eudr/statements", {
|
|
120
|
+
id: statement.id,
|
|
121
|
+
status: nextStatus,
|
|
122
|
+
...extraPayload ?? {}
|
|
123
|
+
}, {
|
|
124
|
+
errorMessage: translate("eudr.lifecycle.transitionError")
|
|
125
|
+
})
|
|
126
|
+
),
|
|
127
|
+
context: {
|
|
128
|
+
formId: mutationContextId,
|
|
129
|
+
resourceKind: "eudr.due_diligence_statement",
|
|
130
|
+
resourceId: statement.id,
|
|
131
|
+
retryLastMutation
|
|
132
|
+
},
|
|
133
|
+
mutationPayload: { id: statement.id, status: nextStatus, ...extraPayload ?? {} }
|
|
134
|
+
});
|
|
135
|
+
flash(translate("eudr.lifecycle.transitionSuccess"), "success");
|
|
136
|
+
onChanged();
|
|
137
|
+
return true;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
const reasons = extractGateReasons(error);
|
|
140
|
+
if (reasons.length > 0) {
|
|
141
|
+
setGateReasons(reasons);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (extractOptimisticLockConflict(error)) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
flash(translate("eudr.lifecycle.transitionError"), "error");
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}, [mutationContextId, onChanged, retryLastMutation, runMutation, statement.id, statement.updatedAt, translate]);
|
|
151
|
+
const handleTransitionClick = React.useCallback(async (nextStatus) => {
|
|
152
|
+
if (statement.status === "submitted" && nextStatus === "available") {
|
|
153
|
+
setReferenceDialogOpen(true);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const confirmed = await confirm({
|
|
157
|
+
title: translate(confirmTitleKeys[nextStatus]),
|
|
158
|
+
text: translate(confirmBodyKeys[nextStatus]),
|
|
159
|
+
variant: nextStatus === "archived" || nextStatus === "withdrawn" ? "destructive" : "default"
|
|
160
|
+
});
|
|
161
|
+
if (!confirmed) return;
|
|
162
|
+
await performTransition(nextStatus);
|
|
163
|
+
}, [confirm, performTransition, statement.status, translate]);
|
|
164
|
+
const referenceFields = React.useMemo(() => [
|
|
165
|
+
{
|
|
166
|
+
id: "referenceNumber",
|
|
167
|
+
label: translate("eudr.statements.form.referenceNumber"),
|
|
168
|
+
type: "text",
|
|
169
|
+
required: true
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: "verificationNumber",
|
|
173
|
+
label: translate("eudr.statements.form.verificationNumber"),
|
|
174
|
+
type: "text",
|
|
175
|
+
required: true
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: "referenceIssuedAt",
|
|
179
|
+
label: translate("eudr.statements.form.referenceIssuedAt"),
|
|
180
|
+
type: "datetime-local",
|
|
181
|
+
maxDate: /* @__PURE__ */ new Date()
|
|
182
|
+
}
|
|
183
|
+
], [translate]);
|
|
184
|
+
const referenceGroups = React.useMemo(() => [
|
|
185
|
+
{
|
|
186
|
+
id: "reference",
|
|
187
|
+
title: translate("eudr.lifecycle.referenceDialog.details"),
|
|
188
|
+
column: 1,
|
|
189
|
+
fields: ["referenceNumber", "verificationNumber", "referenceIssuedAt"]
|
|
190
|
+
}
|
|
191
|
+
], [translate]);
|
|
192
|
+
return /* @__PURE__ */ jsxs("section", { className: "space-y-4 rounded-lg border border-border bg-card p-4", children: [
|
|
193
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between", children: [
|
|
194
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
195
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
196
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: translate("eudr.lifecycle.currentStatus") }),
|
|
197
|
+
/* @__PURE__ */ jsx(StatusBadge, { variant: statusBadgeVariant(statement.status), dot: true, children: translate(`eudr.statementStatus.${statement.status}`) }),
|
|
198
|
+
statement.status === "available" && issuedAt ? amendWindowOpen ? /* @__PURE__ */ jsx(StatusBadge, { variant: "info", children: translate("eudr.lifecycle.amendWindowRemaining", remainingParts(amendRemainingMs)) }) : /* @__PURE__ */ jsx(StatusBadge, { variant: "neutral", children: translate("eudr.lifecycle.amendWindowClosed") }) : null,
|
|
199
|
+
speciesMissing ? /* @__PURE__ */ jsx(StatusBadge, { variant: "warning", children: translate("eudr.warnings.speciesMissing") }) : null
|
|
200
|
+
] }),
|
|
201
|
+
retainUntil ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: translate("eudr.lifecycle.retainUntil", { date: retainUntil.toLocaleDateString(locale || void 0) }) }) : null
|
|
202
|
+
] }),
|
|
203
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", children: EUDR_STATEMENT_TRANSITIONS[statement.status].map((nextStatus) => /* @__PURE__ */ jsxs(
|
|
204
|
+
Button,
|
|
205
|
+
{
|
|
206
|
+
type: "button",
|
|
207
|
+
variant: nextStatus === "archived" || nextStatus === "withdrawn" ? "outline" : "default",
|
|
208
|
+
onClick: () => void handleTransitionClick(nextStatus),
|
|
209
|
+
children: [
|
|
210
|
+
/* @__PURE__ */ jsx(CheckCircle2, { className: "size-4", "aria-hidden": "true" }),
|
|
211
|
+
translate(transitionActionKey(nextStatus))
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
nextStatus
|
|
215
|
+
)) })
|
|
216
|
+
] }),
|
|
217
|
+
gateReasons.length > 0 ? /* @__PURE__ */ jsxs(Alert, { status: "warning", style: "lighter", children: [
|
|
218
|
+
/* @__PURE__ */ jsx(AlertTitle, { children: translate("eudr.lifecycle.gateFailureTitle") }),
|
|
219
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm leading-5", children: /* @__PURE__ */ jsx("ul", { className: "list-disc space-y-1 pl-5", children: gateReasons.map((reason) => /* @__PURE__ */ jsx("li", { children: translate(reason) }, reason)) }) })
|
|
220
|
+
] }) : null,
|
|
221
|
+
/* @__PURE__ */ jsx(Dialog, { open: referenceDialogOpen, onOpenChange: setReferenceDialogOpen, children: /* @__PURE__ */ jsxs(DialogContent, { size: "lg", children: [
|
|
222
|
+
/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: translate("eudr.lifecycle.referenceDialog.title") }) }),
|
|
223
|
+
/* @__PURE__ */ jsx(
|
|
224
|
+
CrudForm,
|
|
225
|
+
{
|
|
226
|
+
embedded: true,
|
|
227
|
+
title: translate("eudr.lifecycle.referenceDialog.title"),
|
|
228
|
+
submitLabel: translate("eudr.lifecycle.referenceDialog.submit"),
|
|
229
|
+
fields: referenceFields,
|
|
230
|
+
groups: referenceGroups,
|
|
231
|
+
initialValues: {
|
|
232
|
+
referenceNumber: statement.referenceNumber ?? "",
|
|
233
|
+
verificationNumber: statement.verificationNumber ?? "",
|
|
234
|
+
referenceIssuedAt: statement.referenceIssuedAt ? toDateTimeLocalInput(new Date(statement.referenceIssuedAt)) : toDateTimeLocalInput(/* @__PURE__ */ new Date())
|
|
235
|
+
},
|
|
236
|
+
onSubmit: async (values) => {
|
|
237
|
+
const referenceNumber = optionalText(values.referenceNumber);
|
|
238
|
+
if (!referenceNumber) {
|
|
239
|
+
const message = translate("eudr.lifecycle.referenceDialog.referenceNumberRequired");
|
|
240
|
+
throw createCrudFormError(message, { referenceNumber: message });
|
|
241
|
+
}
|
|
242
|
+
const verificationNumber = optionalText(values.verificationNumber);
|
|
243
|
+
if (!verificationNumber) {
|
|
244
|
+
const message = translate("eudr.lifecycle.referenceDialog.verificationNumberRequired");
|
|
245
|
+
throw createCrudFormError(message, { verificationNumber: message });
|
|
246
|
+
}
|
|
247
|
+
const issuedAtText = optionalText(values.referenceIssuedAt);
|
|
248
|
+
const issuedAt2 = issuedAtText ? new Date(issuedAtText) : /* @__PURE__ */ new Date();
|
|
249
|
+
if (Number.isNaN(issuedAt2.getTime()) || issuedAt2.getTime() > Date.now()) {
|
|
250
|
+
const message = translate("eudr.lifecycle.referenceDialog.referenceIssuedAtInvalid");
|
|
251
|
+
throw createCrudFormError(message, { referenceIssuedAt: message });
|
|
252
|
+
}
|
|
253
|
+
const ok = await performTransition("available", {
|
|
254
|
+
referenceNumber,
|
|
255
|
+
verificationNumber,
|
|
256
|
+
referenceIssuedAt: issuedAt2.toISOString()
|
|
257
|
+
});
|
|
258
|
+
if (!ok) {
|
|
259
|
+
throw createCrudFormError(translate("eudr.lifecycle.transitionBlocked"));
|
|
260
|
+
}
|
|
261
|
+
setReferenceDialogOpen(false);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
] }) }),
|
|
266
|
+
ConfirmDialogElement
|
|
267
|
+
] });
|
|
268
|
+
}
|
|
269
|
+
var StatementLifecycleBar_default = StatementLifecycleBar;
|
|
270
|
+
export {
|
|
271
|
+
StatementLifecycleBar,
|
|
272
|
+
StatementLifecycleBar_default as default
|
|
273
|
+
};
|
|
274
|
+
//# sourceMappingURL=StatementLifecycleBar.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/components/StatementLifecycleBar.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { CheckCircle2 } from 'lucide-react'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { buildOptimisticLockHeader, extractOptimisticLockConflict } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport {\n Alert,\n AlertTitle,\n} from '@open-mercato/ui/primitives/alert'\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 { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport type { EudrStatementStatus } from '../data/validators'\nimport {\n EUDR_AMEND_WINDOW_MS,\n EUDR_STATEMENT_TRANSITIONS,\n} from '../lib/statement-lifecycle'\nimport { statusBadgeVariant } from './formConfig'\n\ntype StatementLifecycleRecord = {\n id: string\n status: EudrStatementStatus\n referenceNumber: string | null\n verificationNumber: string | null\n referenceIssuedAt: string | null\n submittedAt: string | null\n updatedAt: string\n}\n\ntype ReferenceFormValues = {\n referenceNumber: string\n verificationNumber: string\n referenceIssuedAt: 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 StatementLifecycleBarProps = {\n statement: StatementLifecycleRecord\n speciesMissing?: boolean\n onChanged: () => void\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction extractGateReasons(error: unknown): string[] {\n const candidates: unknown[] = []\n if (isRecord(error)) {\n candidates.push(error.details)\n candidates.push(error)\n }\n for (const candidate of candidates) {\n if (!isRecord(candidate) || !Array.isArray(candidate.reasons)) continue\n return candidate.reasons\n .filter((reason): reason is string => typeof reason === 'string' && reason.trim().length > 0)\n .map((reason) => reason.startsWith('eudr.') ? reason : `eudr.gate.${reason}`)\n }\n return []\n}\n\nfunction parseDate(value: string | null | undefined): Date | null {\n if (!value) return null\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? null : date\n}\n\nfunction addYears(date: Date, years: number): Date {\n const next = new Date(date)\n next.setFullYear(next.getFullYear() + years)\n return next\n}\n\nfunction remainingParts(ms: number): { hours: number; minutes: number } {\n const totalMinutes = Math.max(0, Math.ceil(ms / 60_000))\n return { hours: Math.floor(totalMinutes / 60), minutes: totalMinutes % 60 }\n}\n\nfunction toDateTimeLocalInput(date: Date): string {\n const offsetMs = date.getTimezoneOffset() * 60_000\n return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16)\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 transitionActionKey(status: EudrStatementStatus): string {\n return `eudr.lifecycle.actions.to${status.charAt(0).toUpperCase()}${status.slice(1)}`\n}\n\nconst confirmTitleKeys: Record<EudrStatementStatus, string> = {\n draft: 'eudr.lifecycle.confirmReturnToDraft',\n submitted: 'eudr.lifecycle.confirmSubmit',\n available: 'eudr.lifecycle.confirmMarkAvailable',\n withdrawn: 'eudr.lifecycle.confirmWithdraw',\n archived: 'eudr.lifecycle.confirmArchive',\n}\n\nconst confirmBodyKeys: Record<EudrStatementStatus, string> = {\n draft: 'eudr.lifecycle.confirmReturnToDraftBody',\n submitted: 'eudr.lifecycle.confirmSubmitBody',\n available: 'eudr.lifecycle.confirmMarkAvailableBody',\n withdrawn: 'eudr.lifecycle.confirmWithdrawBody',\n archived: 'eudr.lifecycle.confirmArchiveBody',\n}\n\nexport function StatementLifecycleBar({\n statement,\n speciesMissing = false,\n onChanged,\n}: StatementLifecycleBarProps) {\n const translate = useT()\n const locale = useLocale()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [now, setNow] = React.useState(() => new Date())\n const [referenceDialogOpen, setReferenceDialogOpen] = React.useState(false)\n const [gateReasons, setGateReasons] = React.useState<string[]>([])\n const mutationContextId = `eudr-statement-lifecycle:${statement.id}`\n const { runMutation, retryLastMutation } = useGuardedMutation<MutationContext>({\n contextId: mutationContextId,\n blockedMessage: translate('ui.forms.flash.saveBlocked'),\n })\n\n React.useEffect(() => {\n if (statement.status !== 'available') return\n const interval = window.setInterval(() => setNow(new Date()), 60_000)\n setNow(new Date())\n return () => window.clearInterval(interval)\n }, [statement.status, statement.referenceIssuedAt])\n\n const issuedAt = parseDate(statement.referenceIssuedAt)\n const submittedAt = parseDate(statement.submittedAt)\n const amendRemainingMs = statement.status === 'available' && issuedAt\n ? issuedAt.getTime() + EUDR_AMEND_WINDOW_MS - now.getTime()\n : 0\n const amendWindowOpen = statement.status === 'available'\n && issuedAt !== null\n && now.getTime() >= issuedAt.getTime()\n && amendRemainingMs > 0\n const retainUntil = submittedAt ? addYears(submittedAt, 5) : null\n\n const performTransition = React.useCallback(async (\n nextStatus: EudrStatementStatus,\n extraPayload?: Record<string, unknown>,\n ): Promise<boolean> => {\n setGateReasons([])\n try {\n await runMutation({\n operation: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(statement.updatedAt),\n () => updateCrud('eudr/statements', {\n id: statement.id,\n status: nextStatus,\n ...(extraPayload ?? {}),\n }, {\n errorMessage: translate('eudr.lifecycle.transitionError'),\n }),\n ),\n context: {\n formId: mutationContextId,\n resourceKind: 'eudr.due_diligence_statement',\n resourceId: statement.id,\n retryLastMutation,\n },\n mutationPayload: { id: statement.id, status: nextStatus, ...(extraPayload ?? {}) },\n })\n flash(translate('eudr.lifecycle.transitionSuccess'), 'success')\n onChanged()\n return true\n } catch (error) {\n const reasons = extractGateReasons(error)\n if (reasons.length > 0) {\n setGateReasons(reasons)\n return false\n }\n if (extractOptimisticLockConflict(error)) {\n return false\n }\n flash(translate('eudr.lifecycle.transitionError'), 'error')\n return false\n }\n }, [mutationContextId, onChanged, retryLastMutation, runMutation, statement.id, statement.updatedAt, translate])\n\n const handleTransitionClick = React.useCallback(async (nextStatus: EudrStatementStatus) => {\n if (statement.status === 'submitted' && nextStatus === 'available') {\n setReferenceDialogOpen(true)\n return\n }\n const confirmed = await confirm({\n title: translate(confirmTitleKeys[nextStatus]),\n text: translate(confirmBodyKeys[nextStatus]),\n variant: nextStatus === 'archived' || nextStatus === 'withdrawn' ? 'destructive' : 'default',\n })\n if (!confirmed) return\n await performTransition(nextStatus)\n }, [confirm, performTransition, statement.status, translate])\n\n const referenceFields = React.useMemo<CrudField[]>(() => [\n {\n id: 'referenceNumber',\n label: translate('eudr.statements.form.referenceNumber'),\n type: 'text',\n required: true,\n },\n {\n id: 'verificationNumber',\n label: translate('eudr.statements.form.verificationNumber'),\n type: 'text',\n required: true,\n },\n {\n id: 'referenceIssuedAt',\n label: translate('eudr.statements.form.referenceIssuedAt'),\n type: 'datetime-local',\n maxDate: new Date(),\n },\n ], [translate])\n\n const referenceGroups = React.useMemo<CrudFormGroup[]>(() => [\n {\n id: 'reference',\n title: translate('eudr.lifecycle.referenceDialog.details'),\n column: 1,\n fields: ['referenceNumber', 'verificationNumber', 'referenceIssuedAt'],\n },\n ], [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 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium\">{translate('eudr.lifecycle.currentStatus')}</span>\n <StatusBadge variant={statusBadgeVariant(statement.status)} dot>\n {translate(`eudr.statementStatus.${statement.status}`)}\n </StatusBadge>\n {statement.status === 'available' && issuedAt ? (\n amendWindowOpen ? (\n <StatusBadge variant=\"info\">\n {translate('eudr.lifecycle.amendWindowRemaining', remainingParts(amendRemainingMs))}\n </StatusBadge>\n ) : (\n <StatusBadge variant=\"neutral\">\n {translate('eudr.lifecycle.amendWindowClosed')}\n </StatusBadge>\n )\n ) : null}\n {speciesMissing ? (\n <StatusBadge variant=\"warning\">\n {translate('eudr.warnings.speciesMissing')}\n </StatusBadge>\n ) : null}\n </div>\n {retainUntil ? (\n <p className=\"text-sm text-muted-foreground\">\n {translate('eudr.lifecycle.retainUntil', { date: retainUntil.toLocaleDateString(locale || undefined) })}\n </p>\n ) : null}\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n {EUDR_STATEMENT_TRANSITIONS[statement.status].map((nextStatus) => (\n <Button\n key={nextStatus}\n type=\"button\"\n variant={nextStatus === 'archived' || nextStatus === 'withdrawn' ? 'outline' : 'default'}\n onClick={() => void handleTransitionClick(nextStatus)}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate(transitionActionKey(nextStatus))}\n </Button>\n ))}\n </div>\n </div>\n\n {gateReasons.length > 0 ? (\n <Alert status=\"warning\" style=\"lighter\">\n <AlertTitle>{translate('eudr.lifecycle.gateFailureTitle')}</AlertTitle>\n <div className=\"text-sm leading-5\">\n <ul className=\"list-disc space-y-1 pl-5\">\n {gateReasons.map((reason) => (\n <li key={reason}>{translate(reason)}</li>\n ))}\n </ul>\n </div>\n </Alert>\n ) : null}\n\n <Dialog open={referenceDialogOpen} onOpenChange={setReferenceDialogOpen}>\n <DialogContent size=\"lg\">\n <DialogHeader>\n <DialogTitle>{translate('eudr.lifecycle.referenceDialog.title')}</DialogTitle>\n </DialogHeader>\n <CrudForm<ReferenceFormValues>\n embedded\n title={translate('eudr.lifecycle.referenceDialog.title')}\n submitLabel={translate('eudr.lifecycle.referenceDialog.submit')}\n fields={referenceFields}\n groups={referenceGroups}\n initialValues={{\n referenceNumber: statement.referenceNumber ?? '',\n verificationNumber: statement.verificationNumber ?? '',\n referenceIssuedAt: statement.referenceIssuedAt\n ? toDateTimeLocalInput(new Date(statement.referenceIssuedAt))\n : toDateTimeLocalInput(new Date()),\n }}\n onSubmit={async (values) => {\n const referenceNumber = optionalText(values.referenceNumber)\n if (!referenceNumber) {\n const message = translate('eudr.lifecycle.referenceDialog.referenceNumberRequired')\n throw createCrudFormError(message, { referenceNumber: message })\n }\n const verificationNumber = optionalText(values.verificationNumber)\n if (!verificationNumber) {\n const message = translate('eudr.lifecycle.referenceDialog.verificationNumberRequired')\n throw createCrudFormError(message, { verificationNumber: message })\n }\n const issuedAtText = optionalText(values.referenceIssuedAt)\n const issuedAt = issuedAtText ? new Date(issuedAtText) : new Date()\n if (Number.isNaN(issuedAt.getTime()) || issuedAt.getTime() > Date.now()) {\n const message = translate('eudr.lifecycle.referenceDialog.referenceIssuedAtInvalid')\n throw createCrudFormError(message, { referenceIssuedAt: message })\n }\n const ok = await performTransition('available', {\n referenceNumber,\n verificationNumber,\n referenceIssuedAt: issuedAt.toISOString(),\n })\n if (!ok) {\n throw createCrudFormError(translate('eudr.lifecycle.transitionBlocked'))\n }\n setReferenceDialogOpen(false)\n }}\n />\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </section>\n )\n}\n\nexport default StatementLifecycleBar\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["issuedAt"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { CheckCircle2, CircleDashed } from "lucide-react";
|
|
5
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
6
|
+
import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
|
|
7
|
+
import { Alert, AlertTitle } from "@open-mercato/ui/primitives/alert";
|
|
8
|
+
function StatementReadinessChecklist({
|
|
9
|
+
statementId,
|
|
10
|
+
status,
|
|
11
|
+
updatedAt
|
|
12
|
+
}) {
|
|
13
|
+
const translate = useT();
|
|
14
|
+
const [readiness, setReadiness] = React.useState(null);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
if (status !== "draft") {
|
|
17
|
+
setReadiness(null);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
let cancelled = false;
|
|
21
|
+
async function loadReadiness() {
|
|
22
|
+
const call = await apiCall(
|
|
23
|
+
`/api/eudr/statements/${encodeURIComponent(statementId)}/readiness`,
|
|
24
|
+
void 0,
|
|
25
|
+
{ fallback: null }
|
|
26
|
+
);
|
|
27
|
+
if (cancelled || !call.ok || !call.result) return;
|
|
28
|
+
const reasons = Array.isArray(call.result.reasons) ? call.result.reasons.filter((reason) => typeof reason === "string" && reason.length > 0) : [];
|
|
29
|
+
setReadiness({ allowed: call.result.allowed === true, reasons });
|
|
30
|
+
}
|
|
31
|
+
void loadReadiness();
|
|
32
|
+
return () => {
|
|
33
|
+
cancelled = true;
|
|
34
|
+
};
|
|
35
|
+
}, [statementId, status, updatedAt]);
|
|
36
|
+
if (status !== "draft" || readiness === null) return null;
|
|
37
|
+
if (readiness.allowed) {
|
|
38
|
+
return /* @__PURE__ */ jsx(Alert, { status: "success", style: "lighter", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm leading-5", children: [
|
|
39
|
+
/* @__PURE__ */ jsx(CheckCircle2, { className: "size-4 shrink-0", "aria-hidden": "true" }),
|
|
40
|
+
translate("eudr.lifecycle.readinessReady")
|
|
41
|
+
] }) });
|
|
42
|
+
}
|
|
43
|
+
return /* @__PURE__ */ jsxs(Alert, { status: "information", style: "lighter", children: [
|
|
44
|
+
/* @__PURE__ */ jsx(AlertTitle, { children: translate("eudr.lifecycle.readinessTitle") }),
|
|
45
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-1 text-sm leading-5", children: readiness.reasons.map((reason) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2", children: [
|
|
46
|
+
/* @__PURE__ */ jsx(CircleDashed, { className: "mt-0.5 size-4 shrink-0", "aria-hidden": "true" }),
|
|
47
|
+
/* @__PURE__ */ jsx("span", { children: translate(reason) })
|
|
48
|
+
] }, reason)) })
|
|
49
|
+
] });
|
|
50
|
+
}
|
|
51
|
+
var StatementReadinessChecklist_default = StatementReadinessChecklist;
|
|
52
|
+
export {
|
|
53
|
+
StatementReadinessChecklist,
|
|
54
|
+
StatementReadinessChecklist_default as default
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=StatementReadinessChecklist.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/eudr/components/StatementReadinessChecklist.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { CheckCircle2, CircleDashed } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Alert, AlertTitle } from '@open-mercato/ui/primitives/alert'\nimport type { EudrStatementStatus } from '../data/validators'\n\ntype ReadinessResponse = {\n status?: string\n allowed?: boolean\n reasons?: string[]\n}\n\nexport type StatementReadinessChecklistProps = {\n statementId: string\n status: EudrStatementStatus\n updatedAt: string\n}\n\nexport function StatementReadinessChecklist({\n statementId,\n status,\n updatedAt,\n}: StatementReadinessChecklistProps) {\n const translate = useT()\n const [readiness, setReadiness] = React.useState<{ allowed: boolean; reasons: string[] } | null>(null)\n\n React.useEffect(() => {\n if (status !== 'draft') {\n setReadiness(null)\n return\n }\n let cancelled = false\n async function loadReadiness() {\n const call = await apiCall<ReadinessResponse>(\n `/api/eudr/statements/${encodeURIComponent(statementId)}/readiness`,\n undefined,\n { fallback: null },\n )\n if (cancelled || !call.ok || !call.result) return\n const reasons = Array.isArray(call.result.reasons)\n ? call.result.reasons.filter((reason): reason is string => typeof reason === 'string' && reason.length > 0)\n : []\n setReadiness({ allowed: call.result.allowed === true, reasons })\n }\n void loadReadiness()\n return () => {\n cancelled = true\n }\n }, [statementId, status, updatedAt])\n\n if (status !== 'draft' || readiness === null) return null\n\n if (readiness.allowed) {\n return (\n <Alert status=\"success\" style=\"lighter\">\n <div className=\"flex items-center gap-2 text-sm leading-5\">\n <CheckCircle2 className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n {translate('eudr.lifecycle.readinessReady')}\n </div>\n </Alert>\n )\n }\n\n return (\n <Alert status=\"information\" style=\"lighter\">\n <AlertTitle>{translate('eudr.lifecycle.readinessTitle')}</AlertTitle>\n <ul className=\"space-y-1 text-sm leading-5\">\n {readiness.reasons.map((reason) => (\n <li key={reason} className=\"flex items-start gap-2\">\n <CircleDashed className=\"mt-0.5 size-4 shrink-0\" aria-hidden=\"true\" />\n <span>{translate(reason)}</span>\n </li>\n ))}\n </ul>\n </Alert>\n )\n}\n\nexport default StatementReadinessChecklist\n"],
|
|
5
|
+
"mappings": ";AA0DQ,SACE,KADF;AAxDR,YAAY,WAAW;AACvB,SAAS,cAAc,oBAAoB;AAC3C,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,OAAO,kBAAkB;AAe3B,SAAS,4BAA4B;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AACF,GAAqC;AACnC,QAAM,YAAY,KAAK;AACvB,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAyD,IAAI;AAErG,QAAM,UAAU,MAAM;AACpB,QAAI,WAAW,SAAS;AACtB,mBAAa,IAAI;AACjB;AAAA,IACF;AACA,QAAI,YAAY;AAChB,mBAAe,gBAAgB;AAC7B,YAAM,OAAO,MAAM;AAAA,QACjB,wBAAwB,mBAAmB,WAAW,CAAC;AAAA,QACvD;AAAA,QACA,EAAE,UAAU,KAAK;AAAA,MACnB;AACA,UAAI,aAAa,CAAC,KAAK,MAAM,CAAC,KAAK,OAAQ;AAC3C,YAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,OAAO,IAC7C,KAAK,OAAO,QAAQ,OAAO,CAAC,WAA6B,OAAO,WAAW,YAAY,OAAO,SAAS,CAAC,IACxG,CAAC;AACL,mBAAa,EAAE,SAAS,KAAK,OAAO,YAAY,MAAM,QAAQ,CAAC;AAAA,IACjE;AACA,SAAK,cAAc;AACnB,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,aAAa,QAAQ,SAAS,CAAC;AAEnC,MAAI,WAAW,WAAW,cAAc,KAAM,QAAO;AAErD,MAAI,UAAU,SAAS;AACrB,WACE,oBAAC,SAAM,QAAO,WAAU,OAAM,WAC5B,+BAAC,SAAI,WAAU,6CACb;AAAA,0BAAC,gBAAa,WAAU,mBAAkB,eAAY,QAAO;AAAA,MAC5D,UAAU,+BAA+B;AAAA,OAC5C,GACF;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAM,QAAO,eAAc,OAAM,WAChC;AAAA,wBAAC,cAAY,oBAAU,+BAA+B,GAAE;AAAA,IACxD,oBAAC,QAAG,WAAU,+BACX,oBAAU,QAAQ,IAAI,CAAC,WACtB,qBAAC,QAAgB,WAAU,0BACzB;AAAA,0BAAC,gBAAa,WAAU,0BAAyB,eAAY,QAAO;AAAA,MACpE,oBAAC,UAAM,oBAAU,MAAM,GAAE;AAAA,SAFlB,MAGT,CACD,GACH;AAAA,KACF;AAEJ;AAEA,IAAO,sCAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|