@dainamite/cpq 0.2.2
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/CHANGELOG.md +70 -0
- package/LICENSE +21 -0
- package/MIGRATION.md +236 -0
- package/README.md +108 -0
- package/dist/modules/cpq/acl.js +30 -0
- package/dist/modules/cpq/acl.js.map +7 -0
- package/dist/modules/cpq/api/_helpers/handleArcError.js +37 -0
- package/dist/modules/cpq/api/_helpers/handleArcError.js.map +7 -0
- package/dist/modules/cpq/api/attribute-options/route.js +47 -0
- package/dist/modules/cpq/api/attribute-options/route.js.map +7 -0
- package/dist/modules/cpq/api/bundle-slots/route.js +101 -0
- package/dist/modules/cpq/api/bundle-slots/route.js.map +7 -0
- package/dist/modules/cpq/api/bundle-tree/route.js +28 -0
- package/dist/modules/cpq/api/bundle-tree/route.js.map +7 -0
- package/dist/modules/cpq/api/context.js +29 -0
- package/dist/modules/cpq/api/context.js.map +7 -0
- package/dist/modules/cpq/api/inventory/assets/route.js +113 -0
- package/dist/modules/cpq/api/inventory/assets/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/assets/status/route.js +35 -0
- package/dist/modules/cpq/api/inventory/assets/status/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.js +30 -0
- package/dist/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/customer/[customerId]/route.js +31 -0
- package/dist/modules/cpq/api/inventory/customer/[customerId]/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscription-items/route.js +99 -0
- package/dist/modules/cpq/api/inventory/subscription-items/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.js +57 -0
- package/dist/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscriptions/expiring/route.js +62 -0
- package/dist/modules/cpq/api/inventory/subscriptions/expiring/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscriptions/route.js +116 -0
- package/dist/modules/cpq/api/inventory/subscriptions/route.js.map +7 -0
- package/dist/modules/cpq/api/inventory/subscriptions/status/route.js +35 -0
- package/dist/modules/cpq/api/inventory/subscriptions/status/route.js.map +7 -0
- package/dist/modules/cpq/api/offering-components/route.js +91 -0
- package/dist/modules/cpq/api/offering-components/route.js.map +7 -0
- package/dist/modules/cpq/api/orders/[orderId]/activate/route.js +39 -0
- package/dist/modules/cpq/api/orders/[orderId]/activate/route.js.map +7 -0
- package/dist/modules/cpq/api/orders/[orderId]/route.js +28 -0
- package/dist/modules/cpq/api/orders/[orderId]/route.js.map +7 -0
- package/dist/modules/cpq/api/orders/[orderId]/status/route.js +38 -0
- package/dist/modules/cpq/api/orders/[orderId]/status/route.js.map +7 -0
- package/dist/modules/cpq/api/orders/route.js +71 -0
- package/dist/modules/cpq/api/orders/route.js.map +7 -0
- package/dist/modules/cpq/api/price-rules/route.js +180 -0
- package/dist/modules/cpq/api/price-rules/route.js.map +7 -0
- package/dist/modules/cpq/api/pricing-table-entries/route.js +142 -0
- package/dist/modules/cpq/api/pricing-table-entries/route.js.map +7 -0
- package/dist/modules/cpq/api/pricing-tables/route.js +179 -0
- package/dist/modules/cpq/api/pricing-tables/route.js.map +7 -0
- package/dist/modules/cpq/api/product-attributes/route.js +160 -0
- package/dist/modules/cpq/api/product-attributes/route.js.map +7 -0
- package/dist/modules/cpq/api/product-charges/route.js +166 -0
- package/dist/modules/cpq/api/product-charges/route.js.map +7 -0
- package/dist/modules/cpq/api/product-offerings/route.js +294 -0
- package/dist/modules/cpq/api/product-offerings/route.js.map +7 -0
- package/dist/modules/cpq/api/product-relationships/route.js +144 -0
- package/dist/modules/cpq/api/product-relationships/route.js.map +7 -0
- package/dist/modules/cpq/api/product-specifications/route.js +292 -0
- package/dist/modules/cpq/api/product-specifications/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.js +71 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js +29 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js +54 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js +27 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/merge-meta/route.js +72 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/merge-meta/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js +35 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/route.js +102 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js +27 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.js +79 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.js +95 -0
- package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/attributes/route.js +52 -0
- package/dist/modules/cpq/api/quotes/attributes/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/from-subscription/route.js +72 -0
- package/dist/modules/cpq/api/quotes/from-subscription/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/price/route.js +69 -0
- package/dist/modules/cpq/api/quotes/price/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/route.js +97 -0
- package/dist/modules/cpq/api/quotes/route.js.map +7 -0
- package/dist/modules/cpq/api/quotes/validate-relationships/route.js +86 -0
- package/dist/modules/cpq/api/quotes/validate-relationships/route.js.map +7 -0
- package/dist/modules/cpq/api/resolveQuotingService.js +7 -0
- package/dist/modules/cpq/api/resolveQuotingService.js.map +7 -0
- package/dist/modules/cpq/api/wizards/resolve/route.js +38 -0
- package/dist/modules/cpq/api/wizards/resolve/route.js.map +7 -0
- package/dist/modules/cpq/api/wizards/route.js +111 -0
- package/dist/modules/cpq/api/wizards/route.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js +136 -0
- package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js +185 -0
- package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js +343 -0
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js +13 -0
- package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/page.js +35 -0
- package/dist/modules/cpq/backend/cpq/inventory/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/shared.js +20 -0
- package/dist/modules/cpq/backend/cpq/inventory/shared.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +794 -0
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js +13 -0
- package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js +917 -0
- package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/offerings/page.js +405 -0
- package/dist/modules/cpq/backend/cpq/offerings/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/offerings/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/offerings/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +677 -0
- package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/orders/page.js +134 -0
- package/dist/modules/cpq/backend/cpq/orders/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/orders/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/orders/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js +272 -0
- package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js +407 -0
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js +13 -0
- package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/page.js +211 -0
- package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/price-rules/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/price-rules/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js +275 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js +112 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js +492 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.js +50 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js +249 -0
- package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/page.js +87 -0
- package/dist/modules/cpq/backend/cpq/pricing/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/pricing/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/pricing/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js +652 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js +1289 -0
- package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/page.js +283 -0
- package/dist/modules/cpq/backend/cpq/quotes/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/quotes/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/quotes/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js +214 -0
- package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js +1399 -0
- package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/specifications/page.js +148 -0
- package/dist/modules/cpq/backend/cpq/specifications/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/specifications/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/specifications/page.meta.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js +204 -0
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js +191 -0
- package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/wizards/page.js +119 -0
- package/dist/modules/cpq/backend/cpq/wizards/page.js.map +7 -0
- package/dist/modules/cpq/backend/cpq/wizards/page.meta.js +18 -0
- package/dist/modules/cpq/backend/cpq/wizards/page.meta.js.map +7 -0
- package/dist/modules/cpq/ce.js +151 -0
- package/dist/modules/cpq/ce.js.map +7 -0
- package/dist/modules/cpq/cli.js +11 -0
- package/dist/modules/cpq/cli.js.map +7 -0
- package/dist/modules/cpq/components/CpqListView.js +265 -0
- package/dist/modules/cpq/components/CpqListView.js.map +7 -0
- package/dist/modules/cpq/components/NumberInput.js +95 -0
- package/dist/modules/cpq/components/NumberInput.js.map +7 -0
- package/dist/modules/cpq/components/StatusPath.js +60 -0
- package/dist/modules/cpq/components/StatusPath.js.map +7 -0
- package/dist/modules/cpq/components/statusMaps.js +66 -0
- package/dist/modules/cpq/components/statusMaps.js.map +7 -0
- package/dist/modules/cpq/components/useCpqRowActions.js +125 -0
- package/dist/modules/cpq/components/useCpqRowActions.js.map +7 -0
- package/dist/modules/cpq/data/entities.js +1556 -0
- package/dist/modules/cpq/data/entities.js.map +7 -0
- package/dist/modules/cpq/data/validators.js +575 -0
- package/dist/modules/cpq/data/validators.js.map +7 -0
- package/dist/modules/cpq/di.js +57 -0
- package/dist/modules/cpq/di.js.map +7 -0
- package/dist/modules/cpq/events.js +50 -0
- package/dist/modules/cpq/events.js.map +7 -0
- package/dist/modules/cpq/index.js +16 -0
- package/dist/modules/cpq/index.js.map +7 -0
- package/dist/modules/cpq/lib/seeds/api.js +32 -0
- package/dist/modules/cpq/lib/seeds/api.js.map +7 -0
- package/dist/modules/cpq/lib/seeds/tenant-provisioning.js +158 -0
- package/dist/modules/cpq/lib/seeds/tenant-provisioning.js.map +7 -0
- package/dist/modules/cpq/lib/seeds.js +6 -0
- package/dist/modules/cpq/lib/seeds.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260220220000_cpq.js +40 -0
- package/dist/modules/cpq/migrations/Migration20260220220000_cpq.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.js +54 -0
- package/dist/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.js +15 -0
- package/dist/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.js +62 -0
- package/dist/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260402000000_cpq_workflows.js +56 -0
- package/dist/modules/cpq/migrations/Migration20260402000000_cpq_workflows.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.js +26 -0
- package/dist/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.js +37 -0
- package/dist/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.js +35 -0
- package/dist/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.js +21 -0
- package/dist/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.js +46 -0
- package/dist/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260410100000_cpq_inventory.js +118 -0
- package/dist/modules/cpq/migrations/Migration20260410100000_cpq_inventory.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260411000000_cpq_orders.js +63 -0
- package/dist/modules/cpq/migrations/Migration20260411000000_cpq_orders.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.js +28 -0
- package/dist/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260504064621_cpq_arc.js +36 -0
- package/dist/modules/cpq/migrations/Migration20260504064621_cpq_arc.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.js +14 -0
- package/dist/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.js +14 -0
- package/dist/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.js +58 -0
- package/dist/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.js +29 -0
- package/dist/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.js.map +7 -0
- package/dist/modules/cpq/services/cpqBundleService.js +447 -0
- package/dist/modules/cpq/services/cpqBundleService.js.map +7 -0
- package/dist/modules/cpq/services/cpqInventoryService.js +1371 -0
- package/dist/modules/cpq/services/cpqInventoryService.js.map +7 -0
- package/dist/modules/cpq/services/cpqOrderService.js +901 -0
- package/dist/modules/cpq/services/cpqOrderService.js.map +7 -0
- package/dist/modules/cpq/services/cpqPricingService.js +289 -0
- package/dist/modules/cpq/services/cpqPricingService.js.map +7 -0
- package/dist/modules/cpq/services/cpqProductService.js +204 -0
- package/dist/modules/cpq/services/cpqProductService.js.map +7 -0
- package/dist/modules/cpq/services/cpqQuotingService.js +1867 -0
- package/dist/modules/cpq/services/cpqQuotingService.js.map +7 -0
- package/dist/modules/cpq/services/cpqValidationService.js +234 -0
- package/dist/modules/cpq/services/cpqValidationService.js.map +7 -0
- package/dist/modules/cpq/services/cpqWizardService.js +137 -0
- package/dist/modules/cpq/services/cpqWizardService.js.map +7 -0
- package/dist/modules/cpq/services/types.js +114 -0
- package/dist/modules/cpq/services/types.js.map +7 -0
- package/dist/modules/cpq/setup.js +49 -0
- package/dist/modules/cpq/setup.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-amended-log.js +18 -0
- package/dist/modules/cpq/subscribers/subscription-amended-log.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-cancelled-log.js +19 -0
- package/dist/modules/cpq/subscribers/subscription-cancelled-log.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-merged-log.js +20 -0
- package/dist/modules/cpq/subscribers/subscription-merged-log.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-renewed-log.js +18 -0
- package/dist/modules/cpq/subscribers/subscription-renewed-log.js.map +7 -0
- package/dist/modules/cpq/subscribers/subscription-superseded-log.js +18 -0
- package/dist/modules/cpq/subscribers/subscription-superseded-log.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js +192 -0
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.js +17 -0
- package/dist/modules/cpq/widgets/injection/customer-inventory/widget.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js +79 -0
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.js +17 -0
- package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js +181 -0
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js.map +7 -0
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.js +17 -0
- package/dist/modules/cpq/widgets/injection/quote-configurator/widget.js.map +7 -0
- package/dist/modules/cpq/widgets/injection-table.js +44 -0
- package/dist/modules/cpq/widgets/injection-table.js.map +7 -0
- package/dist/modules/cpq/workflows/WizardRunner.js +113 -0
- package/dist/modules/cpq/workflows/WizardRunner.js.map +7 -0
- package/dist/modules/cpq/workflows/WizardTrigger.js +116 -0
- package/dist/modules/cpq/workflows/WizardTrigger.js.map +7 -0
- package/dist/modules/cpq/workflows/engine.js +188 -0
- package/dist/modules/cpq/workflows/engine.js.map +7 -0
- package/dist/modules/cpq/workflows/registry.js +16 -0
- package/dist/modules/cpq/workflows/registry.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js +119 -0
- package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/InventorySelectStep.js +24 -0
- package/dist/modules/cpq/workflows/steps/InventorySelectStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/ItemListStep.js +115 -0
- package/dist/modules/cpq/workflows/steps/ItemListStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js +327 -0
- package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js +231 -0
- package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/ReviewStep.js +152 -0
- package/dist/modules/cpq/workflows/steps/ReviewStep.js.map +7 -0
- package/dist/modules/cpq/workflows/steps/index.js +49 -0
- package/dist/modules/cpq/workflows/steps/index.js.map +7 -0
- package/dist/modules/cpq/workflows/types.js +1 -0
- package/dist/modules/cpq/workflows/types.js.map +7 -0
- package/package.json +150 -0
- package/src/modules/cpq/__integration__/TC-CPQ-001.spec.ts +177 -0
- package/src/modules/cpq/__integration__/TC-CPQ-002.spec.ts +123 -0
- package/src/modules/cpq/__integration__/TC-CPQ-003.spec.ts +115 -0
- package/src/modules/cpq/__integration__/TC-CPQ-004.spec.ts +184 -0
- package/src/modules/cpq/__integration__/TC-CPQ-005.spec.ts +43 -0
- package/src/modules/cpq/__integration__/TC-CPQ-006.spec.ts +87 -0
- package/src/modules/cpq/__integration__/TC-CPQ-007.spec.ts +79 -0
- package/src/modules/cpq/__integration__/TC-CPQ-008.spec.ts +55 -0
- package/src/modules/cpq/__integration__/TC-CPQ-009.spec.ts +45 -0
- package/src/modules/cpq/__integration__/TC-CPQ-010.spec.ts +54 -0
- package/src/modules/cpq/__integration__/TC-CPQ-011.spec.ts +24 -0
- package/src/modules/cpq/__integration__/TC-CPQ-012.spec.ts +62 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-001.spec.ts +52 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-002.spec.ts +65 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-003.spec.ts +107 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-004.spec.ts +74 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-005.spec.ts +86 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-006.spec.ts +79 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-007.spec.ts +63 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-008.spec.ts +62 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-009.spec.ts +62 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-010.spec.ts +59 -0
- package/src/modules/cpq/__integration__/TC-CPQ-ARC-011.spec.ts +128 -0
- package/src/modules/cpq/__integration__/_helpers/cpqArcFixtures.ts +208 -0
- package/src/modules/cpq/__tests__/package-isolation.test.ts +232 -0
- package/src/modules/cpq/acl.ts +26 -0
- package/src/modules/cpq/api/_helpers/__tests__/handleArcError.test.ts +117 -0
- package/src/modules/cpq/api/_helpers/handleArcError.ts +81 -0
- package/src/modules/cpq/api/attribute-options/route.ts +55 -0
- package/src/modules/cpq/api/bundle-slots/route.ts +112 -0
- package/src/modules/cpq/api/bundle-tree/route.ts +31 -0
- package/src/modules/cpq/api/context.ts +39 -0
- package/src/modules/cpq/api/inventory/assets/route.ts +123 -0
- package/src/modules/cpq/api/inventory/assets/status/route.ts +34 -0
- package/src/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.ts +30 -0
- package/src/modules/cpq/api/inventory/customer/[customerId]/route.ts +31 -0
- package/src/modules/cpq/api/inventory/subscription-items/route.ts +107 -0
- package/src/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.ts +64 -0
- package/src/modules/cpq/api/inventory/subscriptions/expiring/route.ts +66 -0
- package/src/modules/cpq/api/inventory/subscriptions/route.ts +126 -0
- package/src/modules/cpq/api/inventory/subscriptions/status/route.ts +34 -0
- package/src/modules/cpq/api/offering-components/route.ts +103 -0
- package/src/modules/cpq/api/orders/[orderId]/activate/route.ts +48 -0
- package/src/modules/cpq/api/orders/[orderId]/route.ts +28 -0
- package/src/modules/cpq/api/orders/[orderId]/status/route.ts +38 -0
- package/src/modules/cpq/api/orders/route.ts +77 -0
- package/src/modules/cpq/api/price-rules/route.ts +210 -0
- package/src/modules/cpq/api/pricing-table-entries/route.ts +159 -0
- package/src/modules/cpq/api/pricing-tables/route.ts +202 -0
- package/src/modules/cpq/api/product-attributes/route.ts +175 -0
- package/src/modules/cpq/api/product-charges/route.ts +181 -0
- package/src/modules/cpq/api/product-offerings/route.ts +329 -0
- package/src/modules/cpq/api/product-relationships/route.ts +156 -0
- package/src/modules/cpq/api/product-specifications/route.ts +325 -0
- package/src/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.ts +77 -0
- package/src/modules/cpq/api/quotes/[quoteId]/clone/route.ts +28 -0
- package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.ts +55 -0
- package/src/modules/cpq/api/quotes/[quoteId]/items/route.ts +26 -0
- package/src/modules/cpq/api/quotes/[quoteId]/merge-meta/route.ts +78 -0
- package/src/modules/cpq/api/quotes/[quoteId]/recalculate/route.ts +34 -0
- package/src/modules/cpq/api/quotes/[quoteId]/route.ts +109 -0
- package/src/modules/cpq/api/quotes/[quoteId]/status/route.ts +26 -0
- package/src/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.ts +91 -0
- package/src/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.ts +107 -0
- package/src/modules/cpq/api/quotes/attributes/route.ts +61 -0
- package/src/modules/cpq/api/quotes/from-subscription/route.ts +85 -0
- package/src/modules/cpq/api/quotes/price/route.ts +81 -0
- package/src/modules/cpq/api/quotes/route.ts +114 -0
- package/src/modules/cpq/api/quotes/validate-relationships/route.ts +100 -0
- package/src/modules/cpq/api/resolveQuotingService.ts +11 -0
- package/src/modules/cpq/api/wizards/resolve/route.ts +39 -0
- package/src/modules/cpq/api/wizards/route.ts +127 -0
- package/src/modules/cpq/backend/cpq/inventory/AssetsTable.tsx +166 -0
- package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +251 -0
- package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.ts +9 -0
- package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.tsx +440 -0
- package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/inventory/page.tsx +49 -0
- package/src/modules/cpq/backend/cpq/inventory/shared.tsx +32 -0
- package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.ts +9 -0
- package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +1085 -0
- package/src/modules/cpq/backend/cpq/offerings/[id]/page.tsx +1165 -0
- package/src/modules/cpq/backend/cpq/offerings/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/offerings/page.tsx +468 -0
- package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +921 -0
- package/src/modules/cpq/backend/cpq/orders/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/orders/page.tsx +182 -0
- package/src/modules/cpq/backend/cpq/price-rules/PriceRuleForm.tsx +310 -0
- package/src/modules/cpq/backend/cpq/price-rules/[id]/page.meta.ts +9 -0
- package/src/modules/cpq/backend/cpq/price-rules/[id]/page.tsx +472 -0
- package/src/modules/cpq/backend/cpq/price-rules/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/price-rules/page.tsx +253 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.tsx +431 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.tsx +122 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/page.tsx +588 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.ts +90 -0
- package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.ts +338 -0
- package/src/modules/cpq/backend/cpq/pricing/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/pricing/page.tsx +111 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.tsx +737 -0
- package/src/modules/cpq/backend/cpq/quotes/[id]/page.tsx +1721 -0
- package/src/modules/cpq/backend/cpq/quotes/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/quotes/page.tsx +370 -0
- package/src/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.tsx +300 -0
- package/src/modules/cpq/backend/cpq/specifications/[id]/page.tsx +1722 -0
- package/src/modules/cpq/backend/cpq/specifications/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/specifications/page.tsx +191 -0
- package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.tsx +319 -0
- package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/page.tsx +234 -0
- package/src/modules/cpq/backend/cpq/wizards/page.meta.ts +16 -0
- package/src/modules/cpq/backend/cpq/wizards/page.tsx +141 -0
- package/src/modules/cpq/ce.ts +150 -0
- package/src/modules/cpq/cli.ts +10 -0
- package/src/modules/cpq/components/CpqListView.tsx +431 -0
- package/src/modules/cpq/components/NumberInput.tsx +166 -0
- package/src/modules/cpq/components/StatusPath.tsx +116 -0
- package/src/modules/cpq/components/statusMaps.ts +148 -0
- package/src/modules/cpq/components/useCpqRowActions.tsx +183 -0
- package/src/modules/cpq/data/__tests__/validators.arc.test.ts +271 -0
- package/src/modules/cpq/data/__tests__/validators.test.ts +782 -0
- package/src/modules/cpq/data/entities.ts +1467 -0
- package/src/modules/cpq/data/validators.ts +663 -0
- package/src/modules/cpq/di.ts +70 -0
- package/src/modules/cpq/events.ts +62 -0
- package/src/modules/cpq/index.ts +15 -0
- package/src/modules/cpq/lib/seeds/__tests__/api.test.ts +86 -0
- package/src/modules/cpq/lib/seeds/__tests__/tenant-provisioning.test.ts +349 -0
- package/src/modules/cpq/lib/seeds/api.ts +119 -0
- package/src/modules/cpq/lib/seeds/tenant-provisioning.ts +239 -0
- package/src/modules/cpq/lib/seeds.ts +18 -0
- package/src/modules/cpq/migrations/.snapshot-open-mercato.json +7473 -0
- package/src/modules/cpq/migrations/Migration20260220220000_cpq.ts +51 -0
- package/src/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.ts +70 -0
- package/src/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.ts +15 -0
- package/src/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.ts +73 -0
- package/src/modules/cpq/migrations/Migration20260402000000_cpq_workflows.ts +59 -0
- package/src/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.ts +30 -0
- package/src/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.ts +36 -0
- package/src/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.ts +33 -0
- package/src/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.ts +22 -0
- package/src/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.ts +56 -0
- package/src/modules/cpq/migrations/Migration20260410100000_cpq_inventory.ts +118 -0
- package/src/modules/cpq/migrations/Migration20260411000000_cpq_orders.ts +62 -0
- package/src/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.ts +33 -0
- package/src/modules/cpq/migrations/Migration20260504064621_cpq_arc.ts +68 -0
- package/src/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.ts +30 -0
- package/src/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.ts +27 -0
- package/src/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.ts +82 -0
- package/src/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.ts +52 -0
- package/src/modules/cpq/services/__tests__/_helpers/mockEm.ts +59 -0
- package/src/modules/cpq/services/__tests__/cpqBundleService.test.ts +661 -0
- package/src/modules/cpq/services/__tests__/cpqInventoryService.arc.test.ts +357 -0
- package/src/modules/cpq/services/__tests__/cpqInventoryService.test.ts +718 -0
- package/src/modules/cpq/services/__tests__/cpqOrderService.test.ts +603 -0
- package/src/modules/cpq/services/__tests__/cpqPricingService.test.ts +1012 -0
- package/src/modules/cpq/services/__tests__/cpqProductService.test.ts +603 -0
- package/src/modules/cpq/services/__tests__/cpqQuotingService.arc.test.ts +143 -0
- package/src/modules/cpq/services/__tests__/cpqQuotingService.test.ts +658 -0
- package/src/modules/cpq/services/__tests__/cpqValidationService.test.ts +811 -0
- package/src/modules/cpq/services/__tests__/cpqWizardService.test.ts +389 -0
- package/src/modules/cpq/services/__tests__/types.test.ts +359 -0
- package/src/modules/cpq/services/cpqBundleService.ts +671 -0
- package/src/modules/cpq/services/cpqInventoryService.ts +1929 -0
- package/src/modules/cpq/services/cpqOrderService.ts +1230 -0
- package/src/modules/cpq/services/cpqPricingService.ts +412 -0
- package/src/modules/cpq/services/cpqProductService.ts +311 -0
- package/src/modules/cpq/services/cpqQuotingService.ts +2638 -0
- package/src/modules/cpq/services/cpqValidationService.ts +323 -0
- package/src/modules/cpq/services/cpqWizardService.ts +204 -0
- package/src/modules/cpq/services/types.ts +303 -0
- package/src/modules/cpq/setup.ts +63 -0
- package/src/modules/cpq/subscribers/subscription-amended-log.ts +20 -0
- package/src/modules/cpq/subscribers/subscription-cancelled-log.ts +19 -0
- package/src/modules/cpq/subscribers/subscription-merged-log.ts +22 -0
- package/src/modules/cpq/subscribers/subscription-renewed-log.ts +18 -0
- package/src/modules/cpq/subscribers/subscription-superseded-log.ts +19 -0
- package/src/modules/cpq/widgets/injection/customer-inventory/widget.client.tsx +339 -0
- package/src/modules/cpq/widgets/injection/customer-inventory/widget.ts +16 -0
- package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.client.tsx +96 -0
- package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.ts +16 -0
- package/src/modules/cpq/widgets/injection/quote-configurator/widget.client.tsx +265 -0
- package/src/modules/cpq/widgets/injection/quote-configurator/widget.ts +16 -0
- package/src/modules/cpq/widgets/injection-table.ts +42 -0
- package/src/modules/cpq/workflows/WizardRunner.tsx +158 -0
- package/src/modules/cpq/workflows/WizardTrigger.tsx +142 -0
- package/src/modules/cpq/workflows/engine.tsx +278 -0
- package/src/modules/cpq/workflows/registry.ts +15 -0
- package/src/modules/cpq/workflows/steps/CustomerSelectStep.tsx +136 -0
- package/src/modules/cpq/workflows/steps/InventorySelectStep.tsx +34 -0
- package/src/modules/cpq/workflows/steps/ItemListStep.tsx +146 -0
- package/src/modules/cpq/workflows/steps/OfferingSelectStep.tsx +438 -0
- package/src/modules/cpq/workflows/steps/ProductConfigureStep.tsx +287 -0
- package/src/modules/cpq/workflows/steps/ReviewStep.tsx +219 -0
- package/src/modules/cpq/workflows/steps/index.ts +51 -0
- package/src/modules/cpq/workflows/types.ts +102 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/cpq/backend/cpq/specifications/%5Bid%5D/page.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useParams, useRouter } from 'next/navigation'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { NumberInput } from '../../../../components/NumberInput'\nimport {\n formatStatusLabel,\n lifecycleStatusMap,\n specificationLifecycleStatusMap,\n type LifecycleStatus,\n type SpecificationLifecycleStatus,\n} from '../../../../components/statusMaps'\nimport { DependsOnRulesEditor } from './DependsOnRulesEditor'\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n// Attribute \u2192 attribute dependency contract. The validator\n// (`cpqValidationService.validateAttributes`) reads `attributeCode` to look\n// up the parent value and walks `rules[].when` to decide what happens to\n// this attribute. `effect` controls the interpretation of `rules[].then`:\n//\n// - `filter_options`: `then` is a comma-separated list of allowed values\n// that this attribute may take when the parent matches `when`.\n// - `set_value`: `then` is a single value to assign to this attribute\n// when the parent matches `when`.\n// - `toggle_required`: `then` is a boolean \u2014 `true` makes this attribute\n// required when the parent matches `when`, `false` makes it optional.\n//\n// Storage stays generic (`{ when: string; then: unknown }`) so we don't\n// have to migrate older configs when the surface grows.\nexport type DependsOnEffect = 'filter_options' | 'set_value' | 'toggle_required'\n\nexport type DependsOnRule = {\n when: string\n then: unknown\n}\n\nexport type AttributeDependsOn = {\n attributeCode: string\n effect: DependsOnEffect\n rules: DependsOnRule[]\n}\n\ntype Specification = {\n id: string\n productId: string\n code: string\n name: string\n description: string | null\n specType: string\n isAssetizable: boolean\n lifecycleStatus: string\n version: number\n effectiveFrom: string | null\n effectiveTo: string | null\n metadata: Record<string, unknown> | null\n isActive: boolean\n}\n\ntype Attribute = {\n id: string\n code: string\n name: string\n attributeType: string\n resolutionTime: string\n options: Array<{ value: string; label: string }> | null\n constraints: Record<string, unknown> | null\n referenceEntity: string | null\n referenceFilter: Record<string, unknown> | null\n dependsOn: AttributeDependsOn | null\n defaultValue: unknown | null\n helpText: string | null\n sortOrder: number\n isRequired: boolean\n isActive: boolean\n}\n\ntype Offering = {\n id: string\n code: string\n name: string\n description: string | null\n offeringType: string\n designTimeValues: Record<string, unknown>\n lifecycleStatus: string\n isActive: boolean\n}\n\ntype BundleSlot = {\n id: string\n specId: string\n targetSpecId: string\n targetSpec: { id: string; code: string; name: string; specType: string } | null\n componentGroup: string\n name: string\n description: string | null\n cardinalityMin: number\n cardinalityMax: number | null\n sortOrder: number\n isActive: boolean\n}\n\ntype EditingSlot = {\n id?: string\n targetSpecId: string\n componentGroup: string\n name: string\n description: string\n cardinalityMin: number\n cardinalityMax: number | null\n sortOrder: number\n}\n\ntype Relationship = {\n id: string\n sourceSpecId: string\n targetSpecId: string\n relationshipType: string\n cardinalityMin: number\n cardinalityMax: number | null\n condition: Record<string, unknown> | null\n isActive: boolean\n}\n\ntype Charge = {\n id: string\n code: string\n name: string\n description: string | null\n chargeType: string\n pricingMethod: string\n pricingTableId: string | null\n priceColumnKey: string | null\n fixedPrice: string | null\n currencyCode: string | null\n quantityAttributeCode: string | null\n applicabilityCondition: Record<string, unknown> | null\n sortOrder: number\n isActive: boolean\n}\n\ntype PricingTableRef = { id: string; code: string; name: string; dimensions: Array<{ key: string; label: string }>; priceColumns: Array<{ key: string; label: string }> }\n\ntype EditingAttribute = Omit<Attribute, 'id'> & { id?: string }\ntype EditingOffering = Omit<Offering, 'id'> & { id?: string }\ntype EditingRelationship = Omit<Relationship, 'id'> & { id?: string }\ntype EditingCharge = Omit<Charge, 'id'> & { id?: string }\n\n// \u2500\u2500\u2500 Defaults \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst EMPTY_SPEC = {\n code: '',\n name: '',\n description: '',\n specType: 'simple' as string,\n isAssetizable: false,\n lifecycleStatus: 'draft',\n version: 1,\n effectiveFrom: null as string | null,\n effectiveTo: null as string | null,\n isActive: true,\n}\n\nconst EMPTY_SLOT: EditingSlot = {\n targetSpecId: '',\n componentGroup: '',\n name: '',\n description: '',\n cardinalityMin: 0,\n cardinalityMax: null,\n sortOrder: 0,\n}\n\nconst EMPTY_ATTRIBUTE: EditingAttribute = {\n code: '',\n name: '',\n attributeType: 'text',\n resolutionTime: 'run_time',\n options: null,\n constraints: null,\n referenceEntity: null,\n referenceFilter: null,\n dependsOn: null,\n defaultValue: null,\n helpText: null,\n sortOrder: 0,\n isRequired: true,\n isActive: true,\n}\n\nconst EMPTY_OFFERING: EditingOffering = {\n code: '',\n name: '',\n description: null,\n offeringType: 'simple',\n designTimeValues: {},\n lifecycleStatus: 'draft',\n isActive: true,\n}\n\nconst EMPTY_CHARGE: EditingCharge = {\n code: '',\n name: '',\n description: null,\n chargeType: 'mrc',\n pricingMethod: 'flat',\n pricingTableId: null,\n priceColumnKey: null,\n fixedPrice: null,\n currencyCode: null,\n quantityAttributeCode: null,\n applicabilityCondition: null,\n sortOrder: 0,\n isActive: true,\n}\n\nconst EMPTY_RELATIONSHIP: EditingRelationship = {\n sourceSpecId: '',\n targetSpecId: '',\n relationshipType: 'requires',\n cardinalityMin: 0,\n cardinalityMax: null,\n condition: null,\n isActive: true,\n}\n\n// \u2500\u2500\u2500 Component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default function SpecificationDetailPage(props: { params?: { id?: string } }) {\n const t = useT()\n const router = useRouter()\n const urlParams = useParams()\n const specId = (props.params?.id ?? urlParams?.id) as string\n const isNew = specId === 'new'\n\n // \u2500\u2500\u2500 State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const [tab, setTab] = React.useState<'general' | 'attributes' | 'offerings' | 'relationships' | 'slots'>('general')\n const [form, setForm] = React.useState(EMPTY_SPEC)\n const [attributes, setAttributes] = React.useState<Attribute[]>([])\n const [offerings, setOfferings] = React.useState<Offering[]>([])\n const [relationships, setRelationships] = React.useState<Relationship[]>([])\n const [bundleSlots, setBundleSlots] = React.useState<BundleSlot[]>([])\n const [allSpecs, setAllSpecs] = React.useState<Array<{ id: string; code: string; name: string; specType?: string }>>([])\n\n const [loading, setLoading] = React.useState(!isNew)\n const [saving, setSaving] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const [editingAttr, setEditingAttr] = React.useState<EditingAttribute | null>(null)\n const [editingOffering, setEditingOffering] = React.useState<EditingOffering | null>(null)\n const [editingRel, setEditingRel] = React.useState<EditingRelationship | null>(null)\n const [editingSlot, setEditingSlot] = React.useState<EditingSlot | null>(null)\n const [editingOptions, setEditingOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const [editingDtValues, setEditingDtValues] = React.useState<Record<string, unknown>>({})\n const [selectedOfferingIds, setSelectedOfferingIds] = React.useState<Set<string>>(new Set())\n const [offeringCharges, setOfferingCharges] = React.useState<Record<string, Charge[]>>({})\n const [chargeFormOpen, setChargeFormOpen] = React.useState(false)\n const [chargeForm, setChargeForm] = React.useState({ code: '', name: '', description: '', chargeType: 'mrc', pricingMethod: 'flat' })\n const [chargePrices, setChargePrices] = React.useState<Record<string, string>>({})\n const [chargePricingTableId, setChargePricingTableId] = React.useState<string | null>(null)\n const [chargePriceColumnKey, setChargePriceColumnKey] = React.useState<string | null>(null)\n const [chargeCurrency, setChargeCurrency] = React.useState('USD')\n const [pricingTables, setPricingTables] = React.useState<PricingTableRef[]>([])\n const [conditionJson, setConditionJson] = React.useState('null')\n const [dependsOnAttrCode, setDependsOnAttrCode] = React.useState('')\n const [dependsOnEffect, setDependsOnEffect] = React.useState<DependsOnEffect>('filter_options')\n const [dependsOnEnabled, setDependsOnEnabled] = React.useState(false)\n const [dependsOnRules, setDependsOnRules] = React.useState<DependsOnRule[]>([])\n // OM-standard detail page contract: existing records open in read-only\n // \"view\" mode and require an explicit Edit click to allow editing. New\n // records (`/specifications/new`) skip view mode since there's nothing\n // to display yet.\n const [generalMode, setGeneralMode] = React.useState<'view' | 'edit'>(isNew ? 'edit' : 'view')\n // Snapshot of the form taken when entering edit mode \u2014 used by Cancel to\n // revert local changes without re-fetching.\n const [formSnapshot, setFormSnapshot] = React.useState<typeof EMPTY_SPEC | null>(null)\n\n // \u2500\u2500\u2500 Load data \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n React.useEffect(() => {\n let cancelled = false\n\n async function load() {\n try {\n if (isNew) {\n return\n }\n\n // Load all specs for relationship target selector\n const specsRes = await fetch('/api/cpq/product-specifications?pageSize=200')\n if (specsRes.ok) {\n const d = await specsRes.json()\n if (!cancelled) setAllSpecs(d.items ?? [])\n }\n\n // Load spec detail with nested data\n const res = await fetch(`/api/cpq/product-specifications?id=${encodeURIComponent(specId)}`)\n if (!res.ok) {\n if (!cancelled) setError('Failed to load specification')\n return\n }\n\n const spec = await res.json()\n if (!cancelled) {\n setForm({\n code: spec.code,\n name: spec.name,\n description: spec.description ?? '',\n specType: spec.specType ?? 'simple',\n isAssetizable: spec.isAssetizable ?? false,\n lifecycleStatus: spec.lifecycleStatus,\n version: spec.version,\n effectiveFrom: spec.effectiveFrom,\n effectiveTo: spec.effectiveTo,\n isActive: spec.isActive,\n })\n setAttributes(spec.attributes ?? [])\n setOfferings(spec.offerings ?? [])\n setRelationships(spec.relationships ?? [])\n setBundleSlots(spec.slots ?? [])\n }\n } catch (err) {\n console.error('Failed to load', err)\n if (!cancelled) setError('Failed to load')\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n\n load()\n return () => { cancelled = true }\n }, [specId, isNew])\n\n // \u2500\u2500\u2500 Save specification \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveSpec = async () => {\n setSaving(true)\n setError(null)\n try {\n const { ...formData } = form\n const payload = isNew\n ? { ...formData, description: formData.description || null }\n : { id: specId, ...formData, description: formData.description || null }\n\n const res = await fetch('/api/cpq/product-specifications', {\n method: isNew ? 'POST' : 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save')\n return\n }\n\n const saved = await res.json()\n if (isNew) {\n router.push(`/backend/cpq/specifications/${saved.id}`)\n } else {\n setForm({\n code: saved.code,\n name: saved.name,\n description: saved.description ?? '',\n specType: saved.specType ?? form.specType,\n isAssetizable: saved.isAssetizable ?? form.isAssetizable,\n lifecycleStatus: saved.lifecycleStatus,\n version: saved.version,\n effectiveFrom: saved.effectiveFrom,\n effectiveTo: saved.effectiveTo,\n isActive: saved.isActive,\n })\n // Save succeeded \u2014 drop the snapshot and flip back to read-only.\n setFormSnapshot(null)\n setGeneralMode('view')\n }\n } catch {\n setError('Failed to save')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteSpec = async () => {\n if (!confirm(t('cpq.specifications.confirmDelete', 'Delete this specification and all its offerings, attributes and relationships?'))) return\n try {\n const res = await fetch('/api/cpq/product-specifications', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: specId }),\n })\n if (res.ok) {\n router.push('/backend/cpq/specifications')\n } else {\n const d = await res.json()\n setError(d.error ?? 'Failed to delete')\n }\n } catch {\n setError('Failed to delete')\n }\n }\n\n // \u2500\u2500\u2500 Attribute CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveAttribute = async () => {\n if (!editingAttr) return\n setSaving(true)\n setError(null)\n try {\n const options = (editingAttr.attributeType === 'select' || editingAttr.attributeType === 'multi-select')\n ? editingOptions.filter((o) => o.value.trim() !== '')\n : null\n\n const dependsOn: AttributeDependsOn | null =\n dependsOnEnabled && dependsOnAttrCode\n ? {\n attributeCode: dependsOnAttrCode,\n effect: dependsOnEffect,\n rules: dependsOnRules.filter((r) => r.when.trim().length > 0),\n }\n : null\n\n const isEdit = !!editingAttr.id\n const payload = {\n ...editingAttr,\n options,\n dependsOn,\n specId,\n }\n const res = await fetch('/api/cpq/product-attributes', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save attribute')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setAttributes((prev) => prev.map((a) => (a.id === saved.id ? saved : a)))\n } else {\n setAttributes((prev) => [...prev, saved])\n }\n setEditingAttr(null)\n } catch {\n setError('Failed to save attribute')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteAttribute = async (attrId: string) => {\n if (!confirm('Delete this attribute?')) return\n try {\n const res = await fetch('/api/cpq/product-attributes', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: attrId }),\n })\n if (res.ok) setAttributes((prev) => prev.filter((a) => a.id !== attrId))\n } catch {\n setError('Failed to delete attribute')\n }\n }\n\n const startEditAttr = (attr?: Attribute) => {\n const editing = attr ? { ...attr } : { ...EMPTY_ATTRIBUTE }\n // Normalize legacy 'enum' type to 'select' for the editor\n if (editing.attributeType === 'enum') editing.attributeType = 'select'\n setEditingAttr(editing)\n setEditingOptions(editing.options ? [...editing.options] : [])\n const dep = editing.dependsOn\n setDependsOnEnabled(!!dep)\n setDependsOnAttrCode(dep?.attributeCode ?? '')\n setDependsOnEffect((dep?.effect as DependsOnEffect) ?? 'filter_options')\n setDependsOnRules(Array.isArray(dep?.rules) ? dep.rules : [])\n }\n\n // \u2500\u2500\u2500 Offering CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveOffering = async () => {\n if (!editingOffering) return\n setSaving(true)\n setError(null)\n try {\n const isEdit = !!editingOffering.id\n const payload = {\n ...editingOffering,\n designTimeValues: editingDtValues,\n specId,\n }\n const res = await fetch('/api/cpq/product-offerings', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save offering')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setOfferings((prev) => prev.map((o) => (o.id === saved.id ? saved : o)))\n } else {\n setOfferings((prev) => [...prev, saved])\n }\n setEditingOffering(null)\n } catch {\n setError('Failed to save offering')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteOffering = async (offeringId: string) => {\n if (!confirm('Delete this offering?')) return\n try {\n const res = await fetch('/api/cpq/product-offerings', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: offeringId }),\n })\n if (res.ok) setOfferings((prev) => prev.filter((o) => o.id !== offeringId))\n } catch {\n setError('Failed to delete offering')\n }\n }\n\n const startEditOffering = (offering?: Offering) => {\n const editing = offering ? { ...offering } : { ...EMPTY_OFFERING }\n setEditingOffering(editing)\n setEditingDtValues(editing.designTimeValues ? { ...editing.designTimeValues } : {})\n }\n\n // \u2500\u2500\u2500 Charge management (multi-offering) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const loadAllOfferingCharges = async () => {\n try {\n const results = await Promise.all(\n offerings.map((o) => fetch(`/api/cpq/product-offerings?id=${encodeURIComponent(o.id)}`).then((r) => r.ok ? r.json() : null))\n )\n const chargeMap: Record<string, Charge[]> = {}\n results.forEach((data, idx) => {\n if (data) chargeMap[offerings[idx].id] = data.charges ?? []\n })\n setOfferingCharges(chargeMap)\n } catch {\n console.error('Failed to load charges')\n }\n }\n\n const loadPricingTables = async () => {\n if (pricingTables.length > 0) return\n const res = await fetch('/api/cpq/pricing-tables?pageSize=200')\n if (res.ok) {\n const data = await res.json()\n setPricingTables(data.items ?? [])\n }\n }\n\n const toggleOfferingSelection = (id: string) => {\n setSelectedOfferingIds((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id); else next.add(id)\n return next\n })\n }\n\n const toggleAllOfferings = () => {\n if (selectedOfferingIds.size === offerings.length) {\n setSelectedOfferingIds(new Set())\n } else {\n setSelectedOfferingIds(new Set(offerings.map((o) => o.id)))\n }\n }\n\n const openChargeForm = () => {\n setChargeForm({ code: '', name: '', description: '', chargeType: 'mrc', pricingMethod: 'flat' })\n setChargePrices({})\n setChargePricingTableId(null)\n setChargePriceColumnKey(null)\n setChargeCurrency('USD')\n setChargeFormOpen(true)\n loadPricingTables()\n }\n\n const saveChargesForSelected = async () => {\n const targets = offerings.filter((o) => selectedOfferingIds.has(o.id))\n if (!targets.length || !chargeForm.code || !chargeForm.name) return\n setSaving(true)\n setError(null)\n try {\n for (const offering of targets) {\n const chargeCode = targets.length > 1 ? `${offering.code}--${chargeForm.code}` : chargeForm.code\n const payload: Record<string, unknown> = {\n offeringId: offering.id,\n code: chargeCode,\n name: chargeForm.name,\n description: chargeForm.description || null,\n chargeType: chargeForm.chargeType,\n pricingMethod: chargeForm.pricingMethod === 'flat' ? 'flat' : chargeForm.pricingMethod,\n isActive: true,\n sortOrder: 0,\n }\n if (chargeForm.pricingMethod === 'flat') {\n payload.fixedPrice = chargePrices[offering.id] || null\n payload.currencyCode = chargeCurrency\n } else {\n payload.pricingTableId = chargePricingTableId\n payload.priceColumnKey = chargePriceColumnKey\n }\n const res = await fetch('/api/cpq/product-charges', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? `Failed to save charge for ${offering.name}`)\n break\n }\n }\n setChargeFormOpen(false)\n await loadAllOfferingCharges()\n } catch {\n setError('Failed to save charges')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteCharge = async (offeringId: string, chargeId: string) => {\n if (!confirm('Delete this charge?')) return\n try {\n const res = await fetch('/api/cpq/product-charges', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: chargeId }),\n })\n if (res.ok) {\n setOfferingCharges((prev) => ({\n ...prev,\n [offeringId]: (prev[offeringId] ?? []).filter((c) => c.id !== chargeId),\n }))\n }\n } catch {\n setError('Failed to delete charge')\n }\n }\n\n const selectedPricingTableRef = chargePricingTableId\n ? pricingTables.find((pt) => pt.id === chargePricingTableId)\n : null\n\n // \u2500\u2500\u2500 Relationship CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveRelationship = async () => {\n if (!editingRel) return\n setSaving(true)\n setError(null)\n try {\n let parsedCondition = editingRel.condition\n try { parsedCondition = conditionJson === 'null' ? null : JSON.parse(conditionJson) } catch { /* keep */ }\n\n const isEdit = !!editingRel.id\n const payload = {\n ...editingRel,\n condition: parsedCondition,\n sourceSpecId: editingRel.sourceSpecId || specId,\n }\n const res = await fetch('/api/cpq/product-relationships', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save relationship')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setRelationships((prev) => prev.map((r) => (r.id === saved.id ? saved : r)))\n } else {\n setRelationships((prev) => [...prev, saved])\n }\n setEditingRel(null)\n } catch {\n setError('Failed to save relationship')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteRelationship = async (relId: string) => {\n if (!confirm('Delete this relationship?')) return\n try {\n const res = await fetch('/api/cpq/product-relationships', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: relId }),\n })\n if (res.ok) setRelationships((prev) => prev.filter((r) => r.id !== relId))\n } catch {\n setError('Failed to delete relationship')\n }\n }\n\n const startEditRel = (rel?: Relationship) => {\n const editing = rel ? { ...rel } : { ...EMPTY_RELATIONSHIP, sourceSpecId: specId }\n setEditingRel(editing)\n setConditionJson(editing.condition ? JSON.stringify(editing.condition, null, 2) : 'null')\n }\n\n // \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const getSpecName = (id: string) => allSpecs.find((s) => s.id === id)?.name ?? id.slice(0, 8)\n\n // \u2500\u2500\u2500 Render \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (loading) {\n return <div className=\"text-sm text-muted-foreground\">{t('common.loading', 'Loading...')}</div>\n }\n\n const designTimeAttrs = attributes.filter((a) => a.resolutionTime === 'design_time')\n\n return (\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n onClick={() => router.push('/backend/cpq/specifications')}\n className=\"text-sm text-muted-foreground hover:text-foreground\"\n >\n \u2190 {t('common.back', 'Back')}\n </button>\n <h1 className=\"text-2xl font-bold\">\n {isNew ? t('cpq.specifications.new', 'New Specification') : form.name}\n </h1>\n {!isNew && (\n <Tag variant={specificationLifecycleStatusMap[form.lifecycleStatus as SpecificationLifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(form.lifecycleStatus)}\n </Tag>\n )}\n </div>\n {!isNew && (\n <div className=\"flex items-center gap-2\">\n {/* Edit lives in the page header next to Delete (OM standard\n detail-page layout). The inline Edit button inside the\n General card is removed in favour of this one. */}\n {generalMode === 'view' && tab === 'general' && (\n <Button\n type=\"button\"\n onClick={() => {\n setFormSnapshot(form)\n setGeneralMode('edit')\n }}\n >\n {t('common.edit', 'Edit')}\n </Button>\n )}\n <Button type=\"button\" variant=\"destructive\" onClick={deleteSpec}>\n {t('common.delete', 'Delete')}\n </Button>\n </div>\n )}\n </div>\n\n {error && (\n <Alert variant=\"destructive\">{error}</Alert>\n )}\n\n {/* Tabs */}\n {!isNew && (\n <div className=\"flex gap-1 border-b\">\n {([\n 'general',\n 'attributes',\n 'offerings',\n 'relationships',\n ...(form.specType === 'bundle' ? ['slots' as const] : []),\n ] as const).map((t_) => (\n <button\n key={t_}\n onClick={() => { setTab(t_ as typeof tab); if (t_ === 'offerings' && offerings.length > 0 && Object.keys(offeringCharges).length === 0) loadAllOfferingCharges() }}\n className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${\n tab === t_ ? 'border-primary text-primary' : 'border-transparent text-muted-foreground hover:text-foreground'\n }`}\n >\n {t_ === 'general' && 'General'}\n {t_ === 'attributes' && `Attributes (${attributes.length})`}\n {t_ === 'offerings' && `Offerings (${offerings.length})`}\n {t_ === 'relationships' && `Relationships (${relationships.length})`}\n {t_ === 'slots' && `Bundle Slots (${bundleSlots.length})`}\n </button>\n ))}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 General Tab / New Form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {(isNew || tab === 'general') && (() => {\n const isViewing = generalMode === 'view' && !isNew\n // Spec type can never be changed once anything depends on it. We\n // still surface the constraint in the read-only view so a user\n // doesn't toggle into edit mode and find a disabled field.\n const specTypeLocked = !isNew && (offerings.length > 0 || bundleSlots.length > 0)\n return (\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.code', 'Code')}</label>\n {isViewing ? (\n <p className=\"text-sm font-mono py-2\">{form.code || '\u2014'}</p>\n ) : (\n <input\n type=\"text\"\n value={form.code}\n onChange={(e) => setForm({ ...form, code: e.target.value })}\n placeholder=\"e.g. gix-access-port\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.name', 'Name')}</label>\n {isViewing ? (\n <p className=\"text-sm py-2\">{form.name || '\u2014'}</p>\n ) : (\n <input\n type=\"text\"\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.lifecycleStatus', 'Lifecycle Status')}</label>\n {isViewing ? (\n <div className=\"py-2\">\n <Tag variant={specificationLifecycleStatusMap[form.lifecycleStatus as SpecificationLifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(form.lifecycleStatus)}\n </Tag>\n </div>\n ) : (\n <select\n value={form.lifecycleStatus}\n onChange={(e) => setForm({ ...form, lifecycleStatus: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"draft\">Draft</option>\n <option value=\"active\">Active</option>\n <option value=\"deprecated\">Deprecated</option>\n </select>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.isActive', 'Is Active?')}</label>\n <div className=\"flex items-center h-[38px]\">\n {isViewing ? (\n <Tag variant={form.isActive ? 'success' : 'neutral'} dot>\n {form.isActive ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </Tag>\n ) : (\n <input\n type=\"checkbox\"\n checked={form.isActive}\n onChange={(e) => setForm({ ...form, isActive: e.target.checked })}\n className=\"rounded border\"\n />\n )}\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Spec Type</label>\n {isViewing ? (\n <p className=\"text-sm py-2\">{form.specType === 'bundle' ? 'Bundle' : 'Simple'}</p>\n ) : (\n <>\n <select\n value={form.specType}\n onChange={(e) => setForm({ ...form, specType: e.target.value })}\n disabled={specTypeLocked}\n className=\"w-full rounded-md border px-3 py-2 text-sm disabled:opacity-50\"\n >\n <option value=\"simple\">Simple</option>\n <option value=\"bundle\">Bundle</option>\n </select>\n {specTypeLocked && (\n <p className=\"text-xs text-muted-foreground mt-1\">Cannot change after offerings or slots exist</p>\n )}\n </>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Is Assetizable?</label>\n <div className=\"flex items-center h-[38px]\">\n {isViewing ? (\n <Tag variant={form.isAssetizable ? 'warning' : 'neutral'} dot>\n {form.isAssetizable ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </Tag>\n ) : (\n <>\n <input\n type=\"checkbox\"\n checked={form.isAssetizable}\n onChange={(e) => setForm({ ...form, isAssetizable: e.target.checked })}\n className=\"rounded border\"\n />\n <span className=\"ml-2 text-xs text-muted-foreground\">Creates asset records during fulfilment</span>\n </>\n )}\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.description', 'Description')}</label>\n {isViewing ? (\n <p className=\"text-sm text-muted-foreground py-2 whitespace-pre-wrap\">{form.description || '\u2014'}</p>\n ) : (\n <textarea\n value={form.description ?? ''}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n rows={3}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n {!isNew && (\n <span className=\"text-xs text-muted-foreground\">Version {form.version}</span>\n )}\n {/* In view mode the Edit button lives in the page header next to\n Delete (OM standard). Here we only render the Save/Cancel\n pair when actually editing. */}\n {!isViewing && (\n <div className=\"flex gap-3\">\n <Button\n type=\"button\"\n onClick={saveSpec}\n disabled={saving || !form.code || !form.name}\n >\n {saving ? t('common.saving', 'Saving...') : t('common.save', 'Save')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n if (isNew) {\n router.push('/backend/cpq/specifications')\n return\n }\n // Revert any in-flight edits and go back to read-only.\n if (formSnapshot) setForm(formSnapshot)\n setFormSnapshot(null)\n setGeneralMode('view')\n }}\n >\n {t('common.cancel', 'Cancel')}\n </Button>\n </div>\n )}\n </div>\n )\n })()}\n\n {/* \u2500\u2500\u2500 Attributes Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'attributes' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditAttr()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addAttribute', 'Add Attribute')}\n </button>\n </div>\n\n {editingAttr && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingAttr.id ? 'Edit Attribute' : 'New Attribute'}\n </h3>\n <div className=\"grid grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Code</label>\n <input type=\"text\" value={editingAttr.code} onChange={(e) => setEditingAttr({ ...editingAttr, code: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Name</label>\n <input type=\"text\" value={editingAttr.name} onChange={(e) => setEditingAttr({ ...editingAttr, name: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Type</label>\n <select value={editingAttr.attributeType} onChange={(e) => setEditingAttr({ ...editingAttr, attributeType: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"text\">Text</option>\n <option value=\"number\">Number</option>\n <option value=\"boolean\">Boolean</option>\n <option value=\"select\">Select</option>\n <option value=\"multi-select\">Multi-Select</option>\n <option value=\"reference\">Reference</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Resolution Time</label>\n <select value={editingAttr.resolutionTime} onChange={(e) => setEditingAttr({ ...editingAttr, resolutionTime: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"run_time\">Run-time (quoting)</option>\n <option value=\"design_time\">Design-time (offering)</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Sort Order</label>\n <NumberInput\n integer\n value={editingAttr.sortOrder}\n onChange={(n) => setEditingAttr({ ...editingAttr, sortOrder: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Help Text</label>\n <input type=\"text\" value={editingAttr.helpText ?? ''} onChange={(e) => setEditingAttr({ ...editingAttr, helpText: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n {editingAttr.attributeType === 'reference' && (\n <>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Reference Entity</label>\n <input type=\"text\" value={editingAttr.referenceEntity ?? ''} onChange={(e) => setEditingAttr({ ...editingAttr, referenceEntity: e.target.value || null })} placeholder=\"e.g. CatalogProduct\" className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n </>\n )}\n {(editingAttr.attributeType === 'select' || editingAttr.attributeType === 'multi-select') && (\n <div className=\"col-span-3 space-y-2\">\n <div className=\"flex items-center justify-between\">\n <label className=\"block text-xs font-medium\">Options</label>\n <button\n type=\"button\"\n onClick={() => setEditingOptions([...editingOptions, { value: '', label: '' }])}\n className=\"text-xs text-primary hover:underline\"\n >\n + Add option\n </button>\n </div>\n {editingOptions.length === 0 ? (\n <div className=\"text-xs text-muted-foreground py-2\">No options defined. Click "Add option" to start.</div>\n ) : (\n <div className=\"space-y-1.5\">\n {editingOptions.map((opt, idx) => (\n <div key={idx} className=\"flex items-center gap-2\">\n <input\n type=\"text\"\n value={opt.value}\n onChange={(e) => {\n const next = [...editingOptions]\n next[idx] = { ...next[idx], value: e.target.value }\n setEditingOptions(next)\n }}\n placeholder=\"Value (e.g. aws)\"\n className=\"flex-1 rounded-md border px-2 py-1.5 text-sm\"\n />\n <input\n type=\"text\"\n value={opt.label}\n onChange={(e) => {\n const next = [...editingOptions]\n next[idx] = { ...next[idx], label: e.target.value }\n setEditingOptions(next)\n }}\n placeholder=\"Label (e.g. Amazon Web Services)\"\n className=\"flex-1 rounded-md border px-2 py-1.5 text-sm\"\n />\n <button\n type=\"button\"\n onClick={() => setEditingOptions(editingOptions.filter((_, i) => i !== idx))}\n className=\"text-destructive hover:text-destructive/80 text-sm px-1\"\n title=\"Remove\"\n >\n \u00D7\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n <div className=\"col-span-3 space-y-2\">\n <label className=\"flex items-center gap-1.5 text-xs font-medium\">\n <input\n type=\"checkbox\"\n checked={dependsOnEnabled}\n onChange={(e) => setDependsOnEnabled(e.target.checked)}\n className=\"rounded border\"\n />\n Depends on another attribute\n </label>\n {dependsOnEnabled && (() => {\n const parentAttr = attributes.find((a) => a.code === dependsOnAttrCode)\n return (\n <div className=\"space-y-3\">\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Parent Attribute Code</label>\n <select\n value={dependsOnAttrCode}\n onChange={(e) => {\n setDependsOnAttrCode(e.target.value)\n // Parent changed \u2014 `when` values that referenced the old\n // parent's options no longer make sense, but clearing them\n // would silently destroy user work. Leave them as text; the\n // RuleRow will fall back to free-text input when the new\n // parent doesn't have enumerated options.\n }}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"\">Select attribute...</option>\n {attributes.filter((a) => editingAttr && a.code !== editingAttr.code).map((a) => (\n <option key={a.code} value={a.code}>{a.name} ({a.code})</option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Effect</label>\n <select\n value={dependsOnEffect}\n onChange={(e) => {\n const next = e.target.value as DependsOnEffect\n setDependsOnEffect(next)\n // `then` shape differs per effect \u2014 drop existing rules so\n // we never persist a mis-typed payload.\n setDependsOnRules([])\n }}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"filter_options\">Filter options</option>\n <option value=\"set_value\">Set value</option>\n <option value=\"toggle_required\">Toggle required</option>\n </select>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-2\">Rules</label>\n <DependsOnRulesEditor\n effect={dependsOnEffect}\n rules={dependsOnRules}\n onChange={setDependsOnRules}\n parentOptions={parentAttr?.options ?? null}\n childOptions={editingOptions.length > 0 ? editingOptions : null}\n />\n </div>\n </div>\n )\n })()}\n </div>\n <div className=\"flex items-end gap-4\">\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input type=\"checkbox\" checked={editingAttr.isRequired} onChange={(e) => setEditingAttr({ ...editingAttr, isRequired: e.target.checked })} className=\"rounded border\" />\n Required\n </label>\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input type=\"checkbox\" checked={editingAttr.isActive} onChange={(e) => setEditingAttr({ ...editingAttr, isActive: e.target.checked })} className=\"rounded border\" />\n Active\n </label>\n </div>\n </div>\n <div className=\"flex gap-2\">\n <button onClick={saveAttribute} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingAttr(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {attributes.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No attributes defined. Add design-time and run-time attributes for this specification.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Code</th>\n <th className=\"px-4 py-3 text-left font-medium\">Name</th>\n <th className=\"px-4 py-3 text-left font-medium\">Type</th>\n <th className=\"px-4 py-3 text-left font-medium\">Resolution</th>\n <th className=\"px-4 py-3 text-left font-medium\">Options</th>\n <th className=\"px-4 py-3 text-left font-medium\">Required</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {attributes.map((attr) => (\n <tr key={attr.id} className=\"border-b\">\n <td className=\"px-4 py-3 font-mono text-xs\">{attr.code}</td>\n <td className=\"px-4 py-3\">{attr.name}</td>\n <td className=\"px-4 py-3\">{attr.attributeType}</td>\n <td className=\"px-4 py-3\">\n <Tag variant={attr.resolutionTime === 'design_time' ? 'info' : 'neutral'} className=\"px-2 text-xs\">\n {attr.resolutionTime === 'design_time' ? 'design' : 'run'}\n </Tag>\n </td>\n <td className=\"px-4 py-3 text-muted-foreground\">{attr.options ? `${attr.options.length} options` : '\u2014'}</td>\n <td className=\"px-4 py-3\">{attr.isRequired ? 'Yes' : 'No'}</td>\n <td className=\"px-4 py-3 text-right\">\n <button onClick={() => startEditAttr(attr)} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={() => deleteAttribute(attr.id)} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Offerings Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'offerings' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditOffering()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addOffering', 'Add Offering')}\n </button>\n </div>\n\n {editingOffering && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingOffering.id ? 'Edit Offering' : 'New Offering'}\n </h3>\n <div className=\"grid grid-cols-4 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Code</label>\n <input type=\"text\" value={editingOffering.code} onChange={(e) => setEditingOffering({ ...editingOffering, code: e.target.value })} placeholder=\"e.g. gix-cloud-connect-aws\" className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Name</label>\n <input type=\"text\" value={editingOffering.name} onChange={(e) => setEditingOffering({ ...editingOffering, name: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Lifecycle Status</label>\n <select value={editingOffering.lifecycleStatus} onChange={(e) => setEditingOffering({ ...editingOffering, lifecycleStatus: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"draft\">Draft</option>\n <option value=\"active\">Active</option>\n <option value=\"deprecated\">Deprecated</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Is Active?</label>\n <div className=\"flex items-center h-[30px]\">\n <input type=\"checkbox\" checked={editingOffering.isActive} onChange={(e) => setEditingOffering({ ...editingOffering, isActive: e.target.checked })} className=\"rounded border\" />\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Description</label>\n <input type=\"text\" value={editingOffering.description ?? ''} onChange={(e) => setEditingOffering({ ...editingOffering, description: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n {designTimeAttrs.length > 0 ? (\n <div className=\"space-y-3\">\n <label className=\"block text-xs font-medium\">Design-Time Values</label>\n <div className=\"grid grid-cols-2 gap-3\">\n {designTimeAttrs.map((attr) => (\n <div key={attr.code}>\n <label className=\"block text-xs font-medium mb-1\">\n {attr.name}\n {attr.isRequired && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n {(attr.attributeType === 'select' || attr.attributeType === 'enum') && attr.options ? (\n <select\n value={String(editingDtValues[attr.code] ?? '')}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.value || null })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"\">Select {attr.name}...</option>\n {attr.options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n ) : attr.attributeType === 'number' ? (\n <NumberInput\n value={typeof editingDtValues[attr.code] === 'number' ? (editingDtValues[attr.code] as number) : null}\n onChange={(n) => setEditingDtValues({ ...editingDtValues, [attr.code]: n })}\n />\n ) : attr.attributeType === 'boolean' ? (\n <div className=\"pt-1\">\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input\n type=\"checkbox\"\n checked={!!editingDtValues[attr.code]}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.checked })}\n className=\"rounded border\"\n />\n {attr.name}\n </label>\n </div>\n ) : (\n <input\n type=\"text\"\n value={String(editingDtValues[attr.code] ?? '')}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.value || null })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n placeholder={attr.helpText ?? undefined}\n />\n )}\n {attr.helpText && <p className=\"text-xs text-muted-foreground mt-0.5\">{attr.helpText}</p>}\n </div>\n ))}\n </div>\n </div>\n ) : (\n <div className=\"text-xs text-muted-foreground py-1\">\n No design-time attributes defined on this specification. All attributes are run-time.\n </div>\n )}\n <div className=\"flex gap-2\">\n <button onClick={saveOffering} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingOffering(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {offerings.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No offerings created. An offering is a sellable instance of this specification with fixed design-time values and attached charges.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-3 py-3 text-left font-medium\">Code</th>\n <th className=\"px-3 py-3 text-left font-medium\">Name</th>\n <th className=\"px-3 py-3 text-left font-medium\">Status</th>\n <th className=\"px-3 py-3 text-left font-medium\">Design-Time Values</th>\n <th className=\"px-3 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {offerings.map((o) => (\n <tr\n key={o.id}\n onClick={() => router.push(`/backend/cpq/offerings/${o.id}`)}\n className=\"border-b cursor-pointer hover:bg-muted/30 transition-colors\"\n >\n <td className=\"px-3 py-3 font-mono text-xs\">{o.code}</td>\n <td className=\"px-3 py-3 font-medium\">{o.name}</td>\n <td className=\"px-3 py-3\">\n <Tag variant={lifecycleStatusMap[o.lifecycleStatus as LifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(o.lifecycleStatus)}\n </Tag>\n </td>\n <td className=\"px-3 py-3 text-muted-foreground text-xs\">\n {Object.keys(o.designTimeValues).length > 0\n ? Object.entries(o.designTimeValues).map(([k, v]) => `${k}=${v}`).join(', ')\n : '\u2014'}\n </td>\n <td className=\"px-3 py-3 text-right\">\n <button onClick={(e) => { e.stopPropagation(); startEditOffering(o) }} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={(e) => { e.stopPropagation(); deleteOffering(o.id) }} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Relationships Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'relationships' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditRel()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addRelationship', 'Add Relationship')}\n </button>\n </div>\n\n {editingRel && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingRel.id ? 'Edit Relationship' : 'New Relationship'}\n </h3>\n <div className=\"grid grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Type</label>\n <select value={editingRel.relationshipType} onChange={(e) => setEditingRel({ ...editingRel, relationshipType: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"parent_child\">Parent / Child</option>\n <option value=\"requires\">Requires</option>\n <option value=\"excludes\">Excludes</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Target Specification</label>\n <select value={editingRel.targetSpecId} onChange={(e) => setEditingRel({ ...editingRel, targetSpecId: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"\">Select...</option>\n {allSpecs.filter((s) => s.id !== specId).map((s) => (\n <option key={s.id} value={s.id}>{s.name} ({s.code})</option>\n ))}\n </select>\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Min</label>\n <NumberInput\n integer\n min={0}\n value={editingRel.cardinalityMin}\n onChange={(n) => setEditingRel({ ...editingRel, cardinalityMin: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Max</label>\n <NumberInput\n integer\n min={0}\n value={editingRel.cardinalityMax}\n onChange={(n) => setEditingRel({ ...editingRel, cardinalityMax: n })}\n placeholder=\"\u221E\"\n />\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Condition (JSON)</label>\n <textarea value={conditionJson} onChange={(e) => setConditionJson(e.target.value)} rows={3} className=\"w-full rounded-md border px-2 py-1.5 text-sm font-mono\" placeholder='null or {\"attribute\":\"direction\",\"operator\":\"in\",\"value\":[\"inbound\"]}' />\n </div>\n <div className=\"flex gap-2\">\n <button onClick={saveRelationship} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingRel(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {relationships.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No relationships defined. Declare parent/child, requires, or excludes relationships with other specifications.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Type</th>\n <th className=\"px-4 py-3 text-left font-medium\">Source</th>\n <th className=\"px-4 py-3 text-left font-medium\">Target</th>\n <th className=\"px-4 py-3 text-left font-medium\">Cardinality</th>\n <th className=\"px-4 py-3 text-left font-medium\">Condition</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {relationships.map((rel) => (\n <tr key={rel.id} className=\"border-b\">\n <td className=\"px-4 py-3\">\n <Tag\n variant={\n rel.relationshipType === 'parent_child' ? 'brand' :\n rel.relationshipType === 'requires' ? 'info' :\n 'error'\n }\n >\n {rel.relationshipType}\n </Tag>\n </td>\n <td className=\"px-4 py-3 text-sm\">{getSpecName(rel.sourceSpecId)}</td>\n <td className=\"px-4 py-3 text-sm\">{getSpecName(rel.targetSpecId)}</td>\n <td className=\"px-4 py-3 text-muted-foreground\">{rel.cardinalityMin}..{rel.cardinalityMax ?? '\u221E'}</td>\n <td className=\"px-4 py-3 text-muted-foreground text-xs\">{rel.condition ? JSON.stringify(rel.condition) : '\u2014'}</td>\n <td className=\"px-4 py-3 text-right\">\n <button onClick={() => startEditRel(rel)} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={() => deleteRelationship(rel.id)} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Bundle Slots Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'slots' && !isNew && form.specType === 'bundle' && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => setEditingSlot({ ...EMPTY_SLOT })}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n + Add Slot\n </button>\n </div>\n\n {editingSlot && (\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n <h3 className=\"text-sm font-semibold\">{editingSlot.id ? 'Edit Bundle Slot' : 'New Bundle Slot'}</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">Name</label>\n <input\n type=\"text\"\n value={editingSlot.name}\n onChange={(e) => setEditingSlot({ ...editingSlot, name: e.target.value })}\n placeholder=\"e.g. Internet Component\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Component Group</label>\n <input\n type=\"text\"\n value={editingSlot.componentGroup}\n onChange={(e) => setEditingSlot({ ...editingSlot, componentGroup: e.target.value })}\n placeholder=\"e.g. internet, tv, phone\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Target Specification</label>\n <select\n value={editingSlot.targetSpecId}\n onChange={(e) => setEditingSlot({ ...editingSlot, targetSpecId: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"\">\u2014 Select specification \u2014</option>\n {allSpecs.filter((s) => s.id !== specId).map((s) => (\n <option key={s.id} value={s.id}>{s.name} ({s.code})</option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Sort Order</label>\n <NumberInput\n integer\n value={editingSlot.sortOrder}\n onChange={(n) => setEditingSlot({ ...editingSlot, sortOrder: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Cardinality Min</label>\n <NumberInput\n integer\n min={0}\n value={editingSlot.cardinalityMin}\n onChange={(n) => setEditingSlot({ ...editingSlot, cardinalityMin: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Cardinality Max</label>\n <NumberInput\n integer\n min={0}\n placeholder=\"\u221E (unlimited)\"\n value={editingSlot.cardinalityMax}\n onChange={(n) => setEditingSlot({ ...editingSlot, cardinalityMax: n })}\n />\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Description</label>\n <textarea\n value={editingSlot.description ?? ''}\n onChange={(e) => setEditingSlot({ ...editingSlot, description: e.target.value })}\n rows={2}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div className=\"flex gap-3\">\n <button\n onClick={async () => {\n setSaving(true)\n setError(null)\n try {\n const isEdit = !!editingSlot.id\n const payload = isEdit\n ? { id: editingSlot.id, ...editingSlot, description: editingSlot.description || null }\n : { specId, ...editingSlot, description: editingSlot.description || null }\n const res = await fetch('/api/cpq/bundle-slots', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save slot')\n return\n }\n setEditingSlot(null)\n const slotsRes = await fetch(`/api/cpq/bundle-slots?specId=${specId}`)\n if (slotsRes.ok) {\n const d = await slotsRes.json()\n setBundleSlots(d.items ?? [])\n }\n } catch {\n setError('Failed to save slot')\n } finally {\n setSaving(false)\n }\n }}\n disabled={saving || !editingSlot.name || !editingSlot.componentGroup || !editingSlot.targetSpecId}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n >\n {saving ? 'Saving...' : (editingSlot.id ? 'Update' : 'Create')}\n </button>\n <button\n onClick={() => setEditingSlot(null)}\n className=\"inline-flex items-center justify-center rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Cancel\n </button>\n </div>\n </div>\n )}\n\n {bundleSlots.length === 0 && !editingSlot ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No bundle slots defined yet. Add slots to define what component specifications can fill this bundle.\n </div>\n ) : bundleSlots.length > 0 && (\n <div className=\"rounded-lg border overflow-hidden\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Name</th>\n <th className=\"px-4 py-3 text-left font-medium\">Group</th>\n <th className=\"px-4 py-3 text-left font-medium\">Target Spec</th>\n <th className=\"px-4 py-3 text-left font-medium\">Cardinality</th>\n <th className=\"px-4 py-3 text-left font-medium\">Order</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {bundleSlots.map((slot) => (\n <tr key={slot.id} className=\"border-b\">\n <td className=\"px-4 py-3 font-medium\">{slot.name}</td>\n <td className=\"px-4 py-3\">\n <Tag variant=\"info\">{slot.componentGroup}</Tag>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n {slot.targetSpec ? (\n <span>\n {slot.targetSpec.name}\n {slot.targetSpec.specType === 'bundle' && (\n <Tag variant=\"brand\" className=\"ml-1 px-1.5 text-[10px]\">bundle</Tag>\n )}\n </span>\n ) : (\n <span className=\"text-muted-foreground\">Unknown</span>\n )}\n </td>\n <td className=\"px-4 py-3 text-muted-foreground\">{slot.cardinalityMin}..{slot.cardinalityMax ?? '\u221E'}</td>\n <td className=\"px-4 py-3 text-muted-foreground\">{slot.sortOrder}</td>\n <td className=\"px-4 py-3 text-right\">\n <button\n onClick={() => setEditingSlot({\n id: slot.id,\n targetSpecId: slot.targetSpecId,\n componentGroup: slot.componentGroup,\n name: slot.name,\n description: slot.description ?? '',\n cardinalityMin: slot.cardinalityMin,\n cardinalityMax: slot.cardinalityMax,\n sortOrder: slot.sortOrder,\n })}\n className=\"text-xs text-primary hover:underline mr-2\"\n >\n Edit\n </button>\n <button\n onClick={async () => {\n if (!confirm('Delete this bundle slot?')) return\n try {\n const res = await fetch('/api/cpq/bundle-slots', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: slot.id }),\n })\n if (res.ok) {\n setBundleSlots((prev) => prev.filter((s) => s.id !== slot.id))\n } else {\n const d = await res.json()\n setError(d.error ?? 'Failed to delete slot')\n }\n } catch {\n setError('Failed to delete slot')\n }\n }}\n className=\"text-xs text-destructive hover:underline\"\n >\n Delete\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
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 { useRouter } from "next/navigation";
|
|
6
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
7
|
+
import { Checkbox } from "@open-mercato/ui/primitives/checkbox";
|
|
8
|
+
import { Tag } from "@open-mercato/ui/primitives/tag";
|
|
9
|
+
import { CpqListView, useCpqListData } from "../../../components/CpqListView.js";
|
|
10
|
+
import {
|
|
11
|
+
formatStatusLabel,
|
|
12
|
+
specificationLifecycleStatusMap
|
|
13
|
+
} from "../../../components/statusMaps.js";
|
|
14
|
+
const PAGE_SIZE = 50;
|
|
15
|
+
function buildFilterParams(values, params) {
|
|
16
|
+
if (typeof values.lifecycleStatus === "string" && values.lifecycleStatus) {
|
|
17
|
+
params.set("lifecycleStatus", values.lifecycleStatus);
|
|
18
|
+
}
|
|
19
|
+
if (typeof values.specType === "string" && values.specType) {
|
|
20
|
+
params.set("specType", values.specType);
|
|
21
|
+
}
|
|
22
|
+
if (values.isActive === true) params.set("isActive", "true");
|
|
23
|
+
if (values.isActive === false) params.set("isActive", "false");
|
|
24
|
+
if (values.isAssetizable === true) params.set("isAssetizable", "true");
|
|
25
|
+
if (values.isAssetizable === false) params.set("isAssetizable", "false");
|
|
26
|
+
}
|
|
27
|
+
function SpecificationsListPage() {
|
|
28
|
+
const t = useT();
|
|
29
|
+
const router = useRouter();
|
|
30
|
+
const data = useCpqListData({
|
|
31
|
+
endpoint: "/api/cpq/product-specifications",
|
|
32
|
+
pageSize: PAGE_SIZE,
|
|
33
|
+
buildFilterParams,
|
|
34
|
+
loadErrorMessage: t("cpq.specifications.list.error.load", "Failed to load specifications")
|
|
35
|
+
});
|
|
36
|
+
const lifecycleOptions = React.useMemo(
|
|
37
|
+
() => [
|
|
38
|
+
{ value: "draft", label: t("cpq.specifications.lifecycle.draft", "Draft") },
|
|
39
|
+
{ value: "active", label: t("cpq.specifications.lifecycle.active", "Active") },
|
|
40
|
+
{ value: "deprecated", label: t("cpq.specifications.lifecycle.deprecated", "Deprecated") }
|
|
41
|
+
],
|
|
42
|
+
[t]
|
|
43
|
+
);
|
|
44
|
+
const specTypeOptions = React.useMemo(
|
|
45
|
+
() => [
|
|
46
|
+
{ value: "simple", label: t("cpq.specifications.type.simple", "Simple") },
|
|
47
|
+
{ value: "bundle", label: t("cpq.specifications.type.bundle", "Bundle") }
|
|
48
|
+
],
|
|
49
|
+
[t]
|
|
50
|
+
);
|
|
51
|
+
const filters = React.useMemo(
|
|
52
|
+
() => [
|
|
53
|
+
{
|
|
54
|
+
id: "lifecycleStatus",
|
|
55
|
+
label: t("cpq.specifications.filters.lifecycleStatus", "Lifecycle Status"),
|
|
56
|
+
type: "select",
|
|
57
|
+
options: lifecycleOptions
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "specType",
|
|
61
|
+
label: t("cpq.specifications.filters.specType", "Type"),
|
|
62
|
+
type: "select",
|
|
63
|
+
options: specTypeOptions
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "isActive",
|
|
67
|
+
label: t("cpq.specifications.filters.isActive", "Active"),
|
|
68
|
+
type: "checkbox"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "isAssetizable",
|
|
72
|
+
label: t("cpq.specifications.filters.isAssetizable", "Assetizable"),
|
|
73
|
+
type: "checkbox"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
[lifecycleOptions, specTypeOptions, t]
|
|
77
|
+
);
|
|
78
|
+
const columns = React.useMemo(
|
|
79
|
+
() => [
|
|
80
|
+
{
|
|
81
|
+
accessorKey: "code",
|
|
82
|
+
header: t("cpq.specifications.code", "Code"),
|
|
83
|
+
cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: row.original.code })
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
accessorKey: "name",
|
|
87
|
+
header: t("cpq.specifications.name", "Name"),
|
|
88
|
+
cell: ({ row }) => /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
89
|
+
row.original.name,
|
|
90
|
+
row.original.specType === "bundle" && /* @__PURE__ */ jsx(Tag, { variant: "brand", className: "ml-2 px-2 text-[10px]", children: "bundle" }),
|
|
91
|
+
row.original.isAssetizable && /* @__PURE__ */ jsx(Tag, { variant: "warning", className: "ml-1 px-2 text-[10px]", children: "asset" })
|
|
92
|
+
] })
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
accessorKey: "isActive",
|
|
96
|
+
header: t("cpq.specifications.isActive", "Is Active?"),
|
|
97
|
+
cell: ({ row }) => /* @__PURE__ */ jsx(Checkbox, { checked: row.original.isActive, disabled: true })
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
accessorKey: "lifecycleStatus",
|
|
101
|
+
header: t("cpq.specifications.lifecycleStatus", "Lifecycle Status"),
|
|
102
|
+
cell: ({ row }) => /* @__PURE__ */ jsx(Tag, { variant: specificationLifecycleStatusMap[row.original.lifecycleStatus] ?? "neutral", dot: true, children: formatStatusLabel(row.original.lifecycleStatus) })
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
accessorKey: "version",
|
|
106
|
+
header: t("cpq.specifications.version", "Version"),
|
|
107
|
+
cell: ({ row }) => /* @__PURE__ */ jsxs("span", { children: [
|
|
108
|
+
"v",
|
|
109
|
+
row.original.version
|
|
110
|
+
] })
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
accessorKey: "description",
|
|
114
|
+
header: t("cpq.specifications.description", "Description"),
|
|
115
|
+
cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: row.original.description ?? "\u2014" }),
|
|
116
|
+
meta: { truncate: true, maxWidth: 320 }
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
[t]
|
|
120
|
+
);
|
|
121
|
+
return /* @__PURE__ */ jsx(
|
|
122
|
+
CpqListView,
|
|
123
|
+
{
|
|
124
|
+
title: t("cpq.specifications.list.title", "Product Specifications"),
|
|
125
|
+
tableId: "cpq.specifications.list",
|
|
126
|
+
data,
|
|
127
|
+
columns,
|
|
128
|
+
filters,
|
|
129
|
+
pageSize: PAGE_SIZE,
|
|
130
|
+
searchPlaceholder: t("cpq.specifications.search.placeholder", "Search specifications..."),
|
|
131
|
+
actions: /* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsx("a", { href: "/backend/cpq/specifications/new", children: t("cpq.specifications.add", "New Specification") }) }),
|
|
132
|
+
crud: {
|
|
133
|
+
endpoint: "/api/cpq/product-specifications",
|
|
134
|
+
entityName: t("cpq.specifications.entityName", "specification"),
|
|
135
|
+
editHref: (row) => `/backend/cpq/specifications/${row.id}`
|
|
136
|
+
},
|
|
137
|
+
onRowClick: (row) => router.push(`/backend/cpq/specifications/${row.id}`),
|
|
138
|
+
emptyState: /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground", children: t(
|
|
139
|
+
"cpq.specifications.empty",
|
|
140
|
+
"No product specifications found. Create one to define your product catalogue."
|
|
141
|
+
) })
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
export {
|
|
146
|
+
SpecificationsListPage as default
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/cpq/backend/cpq/specifications/page.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { CpqListView, useCpqListData } from '../../../components/CpqListView'\nimport {\n formatStatusLabel,\n specificationLifecycleStatusMap,\n type SpecificationLifecycleStatus,\n} from '../../../components/statusMaps'\n\ntype Specification = {\n id: string\n productId: string\n code: string\n name: string\n description: string | null\n specType: string\n isAssetizable: boolean\n lifecycleStatus: string\n version: number\n isActive: boolean\n createdAt: string\n}\n\nconst PAGE_SIZE = 50\n\nfunction buildFilterParams(values: FilterValues, params: URLSearchParams) {\n if (typeof values.lifecycleStatus === 'string' && values.lifecycleStatus) {\n params.set('lifecycleStatus', values.lifecycleStatus)\n }\n if (typeof values.specType === 'string' && values.specType) {\n params.set('specType', values.specType)\n }\n if (values.isActive === true) params.set('isActive', 'true')\n if (values.isActive === false) params.set('isActive', 'false')\n if (values.isAssetizable === true) params.set('isAssetizable', 'true')\n if (values.isAssetizable === false) params.set('isAssetizable', 'false')\n}\n\nexport default function SpecificationsListPage() {\n const t = useT()\n const router = useRouter()\n\n const data = useCpqListData<Specification>({\n endpoint: '/api/cpq/product-specifications',\n pageSize: PAGE_SIZE,\n buildFilterParams,\n loadErrorMessage: t('cpq.specifications.list.error.load', 'Failed to load specifications'),\n })\n\n const lifecycleOptions = React.useMemo(\n () => [\n { value: 'draft', label: t('cpq.specifications.lifecycle.draft', 'Draft') },\n { value: 'active', label: t('cpq.specifications.lifecycle.active', 'Active') },\n { value: 'deprecated', label: t('cpq.specifications.lifecycle.deprecated', 'Deprecated') },\n ],\n [t],\n )\n\n const specTypeOptions = React.useMemo(\n () => [\n { value: 'simple', label: t('cpq.specifications.type.simple', 'Simple') },\n { value: 'bundle', label: t('cpq.specifications.type.bundle', 'Bundle') },\n ],\n [t],\n )\n\n const filters = React.useMemo<FilterDef[]>(\n () => [\n {\n id: 'lifecycleStatus',\n label: t('cpq.specifications.filters.lifecycleStatus', 'Lifecycle Status'),\n type: 'select',\n options: lifecycleOptions,\n },\n {\n id: 'specType',\n label: t('cpq.specifications.filters.specType', 'Type'),\n type: 'select',\n options: specTypeOptions,\n },\n {\n id: 'isActive',\n label: t('cpq.specifications.filters.isActive', 'Active'),\n type: 'checkbox',\n },\n {\n id: 'isAssetizable',\n label: t('cpq.specifications.filters.isAssetizable', 'Assetizable'),\n type: 'checkbox',\n },\n ],\n [lifecycleOptions, specTypeOptions, t],\n )\n\n const columns = React.useMemo<ColumnDef<Specification>[]>(\n () => [\n {\n accessorKey: 'code',\n header: t('cpq.specifications.code', 'Code'),\n cell: ({ row }) => <span className=\"font-mono text-xs\">{row.original.code}</span>,\n },\n {\n accessorKey: 'name',\n header: t('cpq.specifications.name', 'Name'),\n cell: ({ row }) => (\n <span className=\"font-medium\">\n {row.original.name}\n {row.original.specType === 'bundle' && (\n <Tag variant=\"brand\" className=\"ml-2 px-2 text-[10px]\">\n bundle\n </Tag>\n )}\n {row.original.isAssetizable && (\n <Tag variant=\"warning\" className=\"ml-1 px-2 text-[10px]\">\n asset\n </Tag>\n )}\n </span>\n ),\n },\n {\n accessorKey: 'isActive',\n header: t('cpq.specifications.isActive', 'Is Active?'),\n cell: ({ row }) => <Checkbox checked={row.original.isActive} disabled />,\n },\n {\n accessorKey: 'lifecycleStatus',\n header: t('cpq.specifications.lifecycleStatus', 'Lifecycle Status'),\n cell: ({ row }) => (\n <Tag variant={specificationLifecycleStatusMap[row.original.lifecycleStatus as SpecificationLifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(row.original.lifecycleStatus)}\n </Tag>\n ),\n },\n {\n accessorKey: 'version',\n header: t('cpq.specifications.version', 'Version'),\n cell: ({ row }) => <span>v{row.original.version}</span>,\n },\n {\n accessorKey: 'description',\n header: t('cpq.specifications.description', 'Description'),\n cell: ({ row }) => (\n <span className=\"text-muted-foreground\">{row.original.description ?? '\u2014'}</span>\n ),\n meta: { truncate: true, maxWidth: 320 },\n },\n ],\n [t],\n )\n\n return (\n <CpqListView<Specification>\n title={t('cpq.specifications.list.title', 'Product Specifications')}\n tableId=\"cpq.specifications.list\"\n data={data}\n columns={columns}\n filters={filters}\n pageSize={PAGE_SIZE}\n searchPlaceholder={t('cpq.specifications.search.placeholder', 'Search specifications...')}\n actions={\n <Button asChild>\n <a href=\"/backend/cpq/specifications/new\">\n {t('cpq.specifications.add', 'New Specification')}\n </a>\n </Button>\n }\n crud={{\n endpoint: '/api/cpq/product-specifications',\n entityName: t('cpq.specifications.entityName', 'specification'),\n editHref: (row) => `/backend/cpq/specifications/${row.id}`,\n }}\n onRowClick={(row) => router.push(`/backend/cpq/specifications/${row.id}`)}\n emptyState={\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n {t(\n 'cpq.specifications.empty',\n 'No product specifications found. Create one to define your product catalogue.',\n )}\n </div>\n }\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box } from "lucide-react";
|
|
3
|
+
const specificationsIcon = React.createElement(Box, { size: 16 });
|
|
4
|
+
const metadata = {
|
|
5
|
+
requireAuth: true,
|
|
6
|
+
requireFeatures: ["cpq.specifications.view"],
|
|
7
|
+
pageTitle: "Product Specifications",
|
|
8
|
+
pageTitleKey: "cpq.specifications.list.title",
|
|
9
|
+
pageGroup: "CPQ",
|
|
10
|
+
pageGroupKey: "customers~sales~cpq.nav.group",
|
|
11
|
+
pageOrder: 12,
|
|
12
|
+
icon: specificationsIcon,
|
|
13
|
+
breadcrumb: [{ label: "Product Specifications", labelKey: "cpq.specifications.list.title" }]
|
|
14
|
+
};
|
|
15
|
+
export {
|
|
16
|
+
metadata
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=page.meta.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/cpq/backend/cpq/specifications/page.meta.ts"],
|
|
4
|
+
"sourcesContent": ["import React from 'react'\nimport { Box } from 'lucide-react'\n\nconst specificationsIcon = React.createElement(Box, { size: 16 })\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['cpq.specifications.view'],\n pageTitle: 'Product Specifications',\n pageTitleKey: 'cpq.specifications.list.title',\n pageGroup: 'CPQ',\n pageGroupKey: 'customers~sales~cpq.nav.group',\n pageOrder: 12,\n icon: specificationsIcon,\n breadcrumb: [{ label: 'Product Specifications', labelKey: 'cpq.specifications.list.title' }],\n} as const\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,WAAW;AAClB,SAAS,WAAW;AAEpB,MAAM,qBAAqB,MAAM,cAAc,KAAK,EAAE,MAAM,GAAG,CAAC;AAEzD,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,yBAAyB;AAAA,EAC3C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY,CAAC,EAAE,OAAO,0BAA0B,UAAU,gCAAgC,CAAC;AAC7F;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|