@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.
Files changed (504) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/LICENSE +21 -0
  3. package/MIGRATION.md +236 -0
  4. package/README.md +108 -0
  5. package/dist/modules/cpq/acl.js +30 -0
  6. package/dist/modules/cpq/acl.js.map +7 -0
  7. package/dist/modules/cpq/api/_helpers/handleArcError.js +37 -0
  8. package/dist/modules/cpq/api/_helpers/handleArcError.js.map +7 -0
  9. package/dist/modules/cpq/api/attribute-options/route.js +47 -0
  10. package/dist/modules/cpq/api/attribute-options/route.js.map +7 -0
  11. package/dist/modules/cpq/api/bundle-slots/route.js +101 -0
  12. package/dist/modules/cpq/api/bundle-slots/route.js.map +7 -0
  13. package/dist/modules/cpq/api/bundle-tree/route.js +28 -0
  14. package/dist/modules/cpq/api/bundle-tree/route.js.map +7 -0
  15. package/dist/modules/cpq/api/context.js +29 -0
  16. package/dist/modules/cpq/api/context.js.map +7 -0
  17. package/dist/modules/cpq/api/inventory/assets/route.js +113 -0
  18. package/dist/modules/cpq/api/inventory/assets/route.js.map +7 -0
  19. package/dist/modules/cpq/api/inventory/assets/status/route.js +35 -0
  20. package/dist/modules/cpq/api/inventory/assets/status/route.js.map +7 -0
  21. package/dist/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.js +30 -0
  22. package/dist/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.js.map +7 -0
  23. package/dist/modules/cpq/api/inventory/customer/[customerId]/route.js +31 -0
  24. package/dist/modules/cpq/api/inventory/customer/[customerId]/route.js.map +7 -0
  25. package/dist/modules/cpq/api/inventory/subscription-items/route.js +99 -0
  26. package/dist/modules/cpq/api/inventory/subscription-items/route.js.map +7 -0
  27. package/dist/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.js +57 -0
  28. package/dist/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.js.map +7 -0
  29. package/dist/modules/cpq/api/inventory/subscriptions/expiring/route.js +62 -0
  30. package/dist/modules/cpq/api/inventory/subscriptions/expiring/route.js.map +7 -0
  31. package/dist/modules/cpq/api/inventory/subscriptions/route.js +116 -0
  32. package/dist/modules/cpq/api/inventory/subscriptions/route.js.map +7 -0
  33. package/dist/modules/cpq/api/inventory/subscriptions/status/route.js +35 -0
  34. package/dist/modules/cpq/api/inventory/subscriptions/status/route.js.map +7 -0
  35. package/dist/modules/cpq/api/offering-components/route.js +91 -0
  36. package/dist/modules/cpq/api/offering-components/route.js.map +7 -0
  37. package/dist/modules/cpq/api/orders/[orderId]/activate/route.js +39 -0
  38. package/dist/modules/cpq/api/orders/[orderId]/activate/route.js.map +7 -0
  39. package/dist/modules/cpq/api/orders/[orderId]/route.js +28 -0
  40. package/dist/modules/cpq/api/orders/[orderId]/route.js.map +7 -0
  41. package/dist/modules/cpq/api/orders/[orderId]/status/route.js +38 -0
  42. package/dist/modules/cpq/api/orders/[orderId]/status/route.js.map +7 -0
  43. package/dist/modules/cpq/api/orders/route.js +71 -0
  44. package/dist/modules/cpq/api/orders/route.js.map +7 -0
  45. package/dist/modules/cpq/api/price-rules/route.js +180 -0
  46. package/dist/modules/cpq/api/price-rules/route.js.map +7 -0
  47. package/dist/modules/cpq/api/pricing-table-entries/route.js +142 -0
  48. package/dist/modules/cpq/api/pricing-table-entries/route.js.map +7 -0
  49. package/dist/modules/cpq/api/pricing-tables/route.js +179 -0
  50. package/dist/modules/cpq/api/pricing-tables/route.js.map +7 -0
  51. package/dist/modules/cpq/api/product-attributes/route.js +160 -0
  52. package/dist/modules/cpq/api/product-attributes/route.js.map +7 -0
  53. package/dist/modules/cpq/api/product-charges/route.js +166 -0
  54. package/dist/modules/cpq/api/product-charges/route.js.map +7 -0
  55. package/dist/modules/cpq/api/product-offerings/route.js +294 -0
  56. package/dist/modules/cpq/api/product-offerings/route.js.map +7 -0
  57. package/dist/modules/cpq/api/product-relationships/route.js +144 -0
  58. package/dist/modules/cpq/api/product-relationships/route.js.map +7 -0
  59. package/dist/modules/cpq/api/product-specifications/route.js +292 -0
  60. package/dist/modules/cpq/api/product-specifications/route.js.map +7 -0
  61. package/dist/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.js +71 -0
  62. package/dist/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.js.map +7 -0
  63. package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js +29 -0
  64. package/dist/modules/cpq/api/quotes/[quoteId]/clone/route.js.map +7 -0
  65. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js +54 -0
  66. package/dist/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.js.map +7 -0
  67. package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js +27 -0
  68. package/dist/modules/cpq/api/quotes/[quoteId]/items/route.js.map +7 -0
  69. package/dist/modules/cpq/api/quotes/[quoteId]/merge-meta/route.js +72 -0
  70. package/dist/modules/cpq/api/quotes/[quoteId]/merge-meta/route.js.map +7 -0
  71. package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js +35 -0
  72. package/dist/modules/cpq/api/quotes/[quoteId]/recalculate/route.js.map +7 -0
  73. package/dist/modules/cpq/api/quotes/[quoteId]/route.js +102 -0
  74. package/dist/modules/cpq/api/quotes/[quoteId]/route.js.map +7 -0
  75. package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js +27 -0
  76. package/dist/modules/cpq/api/quotes/[quoteId]/status/route.js.map +7 -0
  77. package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.js +79 -0
  78. package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.js.map +7 -0
  79. package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.js +95 -0
  80. package/dist/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.js.map +7 -0
  81. package/dist/modules/cpq/api/quotes/attributes/route.js +52 -0
  82. package/dist/modules/cpq/api/quotes/attributes/route.js.map +7 -0
  83. package/dist/modules/cpq/api/quotes/from-subscription/route.js +72 -0
  84. package/dist/modules/cpq/api/quotes/from-subscription/route.js.map +7 -0
  85. package/dist/modules/cpq/api/quotes/price/route.js +69 -0
  86. package/dist/modules/cpq/api/quotes/price/route.js.map +7 -0
  87. package/dist/modules/cpq/api/quotes/route.js +97 -0
  88. package/dist/modules/cpq/api/quotes/route.js.map +7 -0
  89. package/dist/modules/cpq/api/quotes/validate-relationships/route.js +86 -0
  90. package/dist/modules/cpq/api/quotes/validate-relationships/route.js.map +7 -0
  91. package/dist/modules/cpq/api/resolveQuotingService.js +7 -0
  92. package/dist/modules/cpq/api/resolveQuotingService.js.map +7 -0
  93. package/dist/modules/cpq/api/wizards/resolve/route.js +38 -0
  94. package/dist/modules/cpq/api/wizards/resolve/route.js.map +7 -0
  95. package/dist/modules/cpq/api/wizards/route.js +111 -0
  96. package/dist/modules/cpq/api/wizards/route.js.map +7 -0
  97. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js +136 -0
  98. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +7 -0
  99. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js +185 -0
  100. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +7 -0
  101. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js +343 -0
  102. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js.map +7 -0
  103. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js +13 -0
  104. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js.map +7 -0
  105. package/dist/modules/cpq/backend/cpq/inventory/page.js +35 -0
  106. package/dist/modules/cpq/backend/cpq/inventory/page.js.map +7 -0
  107. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +18 -0
  108. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +7 -0
  109. package/dist/modules/cpq/backend/cpq/inventory/shared.js +20 -0
  110. package/dist/modules/cpq/backend/cpq/inventory/shared.js.map +7 -0
  111. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +794 -0
  112. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +7 -0
  113. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js +13 -0
  114. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js.map +7 -0
  115. package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js +917 -0
  116. package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js.map +7 -0
  117. package/dist/modules/cpq/backend/cpq/offerings/page.js +405 -0
  118. package/dist/modules/cpq/backend/cpq/offerings/page.js.map +7 -0
  119. package/dist/modules/cpq/backend/cpq/offerings/page.meta.js +18 -0
  120. package/dist/modules/cpq/backend/cpq/offerings/page.meta.js.map +7 -0
  121. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +677 -0
  122. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +7 -0
  123. package/dist/modules/cpq/backend/cpq/orders/page.js +134 -0
  124. package/dist/modules/cpq/backend/cpq/orders/page.js.map +7 -0
  125. package/dist/modules/cpq/backend/cpq/orders/page.meta.js +18 -0
  126. package/dist/modules/cpq/backend/cpq/orders/page.meta.js.map +7 -0
  127. package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js +272 -0
  128. package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js.map +7 -0
  129. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js +407 -0
  130. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js.map +7 -0
  131. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js +13 -0
  132. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js.map +7 -0
  133. package/dist/modules/cpq/backend/cpq/price-rules/page.js +211 -0
  134. package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +7 -0
  135. package/dist/modules/cpq/backend/cpq/price-rules/page.meta.js +18 -0
  136. package/dist/modules/cpq/backend/cpq/price-rules/page.meta.js.map +7 -0
  137. package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js +275 -0
  138. package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js.map +7 -0
  139. package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js +112 -0
  140. package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js.map +7 -0
  141. package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js +492 -0
  142. package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js.map +7 -0
  143. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.js +50 -0
  144. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.js.map +7 -0
  145. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js +249 -0
  146. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js.map +7 -0
  147. package/dist/modules/cpq/backend/cpq/pricing/page.js +87 -0
  148. package/dist/modules/cpq/backend/cpq/pricing/page.js.map +7 -0
  149. package/dist/modules/cpq/backend/cpq/pricing/page.meta.js +18 -0
  150. package/dist/modules/cpq/backend/cpq/pricing/page.meta.js.map +7 -0
  151. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js +652 -0
  152. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js.map +7 -0
  153. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js +1289 -0
  154. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +7 -0
  155. package/dist/modules/cpq/backend/cpq/quotes/page.js +283 -0
  156. package/dist/modules/cpq/backend/cpq/quotes/page.js.map +7 -0
  157. package/dist/modules/cpq/backend/cpq/quotes/page.meta.js +18 -0
  158. package/dist/modules/cpq/backend/cpq/quotes/page.meta.js.map +7 -0
  159. package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js +214 -0
  160. package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js.map +7 -0
  161. package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js +1399 -0
  162. package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js.map +7 -0
  163. package/dist/modules/cpq/backend/cpq/specifications/page.js +148 -0
  164. package/dist/modules/cpq/backend/cpq/specifications/page.js.map +7 -0
  165. package/dist/modules/cpq/backend/cpq/specifications/page.meta.js +18 -0
  166. package/dist/modules/cpq/backend/cpq/specifications/page.meta.js.map +7 -0
  167. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js +204 -0
  168. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js.map +7 -0
  169. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js +191 -0
  170. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js.map +7 -0
  171. package/dist/modules/cpq/backend/cpq/wizards/page.js +119 -0
  172. package/dist/modules/cpq/backend/cpq/wizards/page.js.map +7 -0
  173. package/dist/modules/cpq/backend/cpq/wizards/page.meta.js +18 -0
  174. package/dist/modules/cpq/backend/cpq/wizards/page.meta.js.map +7 -0
  175. package/dist/modules/cpq/ce.js +151 -0
  176. package/dist/modules/cpq/ce.js.map +7 -0
  177. package/dist/modules/cpq/cli.js +11 -0
  178. package/dist/modules/cpq/cli.js.map +7 -0
  179. package/dist/modules/cpq/components/CpqListView.js +265 -0
  180. package/dist/modules/cpq/components/CpqListView.js.map +7 -0
  181. package/dist/modules/cpq/components/NumberInput.js +95 -0
  182. package/dist/modules/cpq/components/NumberInput.js.map +7 -0
  183. package/dist/modules/cpq/components/StatusPath.js +60 -0
  184. package/dist/modules/cpq/components/StatusPath.js.map +7 -0
  185. package/dist/modules/cpq/components/statusMaps.js +66 -0
  186. package/dist/modules/cpq/components/statusMaps.js.map +7 -0
  187. package/dist/modules/cpq/components/useCpqRowActions.js +125 -0
  188. package/dist/modules/cpq/components/useCpqRowActions.js.map +7 -0
  189. package/dist/modules/cpq/data/entities.js +1556 -0
  190. package/dist/modules/cpq/data/entities.js.map +7 -0
  191. package/dist/modules/cpq/data/validators.js +575 -0
  192. package/dist/modules/cpq/data/validators.js.map +7 -0
  193. package/dist/modules/cpq/di.js +57 -0
  194. package/dist/modules/cpq/di.js.map +7 -0
  195. package/dist/modules/cpq/events.js +50 -0
  196. package/dist/modules/cpq/events.js.map +7 -0
  197. package/dist/modules/cpq/index.js +16 -0
  198. package/dist/modules/cpq/index.js.map +7 -0
  199. package/dist/modules/cpq/lib/seeds/api.js +32 -0
  200. package/dist/modules/cpq/lib/seeds/api.js.map +7 -0
  201. package/dist/modules/cpq/lib/seeds/tenant-provisioning.js +158 -0
  202. package/dist/modules/cpq/lib/seeds/tenant-provisioning.js.map +7 -0
  203. package/dist/modules/cpq/lib/seeds.js +6 -0
  204. package/dist/modules/cpq/lib/seeds.js.map +7 -0
  205. package/dist/modules/cpq/migrations/Migration20260220220000_cpq.js +40 -0
  206. package/dist/modules/cpq/migrations/Migration20260220220000_cpq.js.map +7 -0
  207. package/dist/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.js +54 -0
  208. package/dist/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.js.map +7 -0
  209. package/dist/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.js +15 -0
  210. package/dist/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.js.map +7 -0
  211. package/dist/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.js +62 -0
  212. package/dist/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.js.map +7 -0
  213. package/dist/modules/cpq/migrations/Migration20260402000000_cpq_workflows.js +56 -0
  214. package/dist/modules/cpq/migrations/Migration20260402000000_cpq_workflows.js.map +7 -0
  215. package/dist/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.js +26 -0
  216. package/dist/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.js.map +7 -0
  217. package/dist/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.js +37 -0
  218. package/dist/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.js.map +7 -0
  219. package/dist/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.js +35 -0
  220. package/dist/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.js.map +7 -0
  221. package/dist/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.js +21 -0
  222. package/dist/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.js.map +7 -0
  223. package/dist/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.js +46 -0
  224. package/dist/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.js.map +7 -0
  225. package/dist/modules/cpq/migrations/Migration20260410100000_cpq_inventory.js +118 -0
  226. package/dist/modules/cpq/migrations/Migration20260410100000_cpq_inventory.js.map +7 -0
  227. package/dist/modules/cpq/migrations/Migration20260411000000_cpq_orders.js +63 -0
  228. package/dist/modules/cpq/migrations/Migration20260411000000_cpq_orders.js.map +7 -0
  229. package/dist/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.js +28 -0
  230. package/dist/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.js.map +7 -0
  231. package/dist/modules/cpq/migrations/Migration20260504064621_cpq_arc.js +36 -0
  232. package/dist/modules/cpq/migrations/Migration20260504064621_cpq_arc.js.map +7 -0
  233. package/dist/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.js +14 -0
  234. package/dist/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.js.map +7 -0
  235. package/dist/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.js +14 -0
  236. package/dist/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.js.map +7 -0
  237. package/dist/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.js +58 -0
  238. package/dist/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.js.map +7 -0
  239. package/dist/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.js +29 -0
  240. package/dist/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.js.map +7 -0
  241. package/dist/modules/cpq/services/cpqBundleService.js +447 -0
  242. package/dist/modules/cpq/services/cpqBundleService.js.map +7 -0
  243. package/dist/modules/cpq/services/cpqInventoryService.js +1371 -0
  244. package/dist/modules/cpq/services/cpqInventoryService.js.map +7 -0
  245. package/dist/modules/cpq/services/cpqOrderService.js +901 -0
  246. package/dist/modules/cpq/services/cpqOrderService.js.map +7 -0
  247. package/dist/modules/cpq/services/cpqPricingService.js +289 -0
  248. package/dist/modules/cpq/services/cpqPricingService.js.map +7 -0
  249. package/dist/modules/cpq/services/cpqProductService.js +204 -0
  250. package/dist/modules/cpq/services/cpqProductService.js.map +7 -0
  251. package/dist/modules/cpq/services/cpqQuotingService.js +1867 -0
  252. package/dist/modules/cpq/services/cpqQuotingService.js.map +7 -0
  253. package/dist/modules/cpq/services/cpqValidationService.js +234 -0
  254. package/dist/modules/cpq/services/cpqValidationService.js.map +7 -0
  255. package/dist/modules/cpq/services/cpqWizardService.js +137 -0
  256. package/dist/modules/cpq/services/cpqWizardService.js.map +7 -0
  257. package/dist/modules/cpq/services/types.js +114 -0
  258. package/dist/modules/cpq/services/types.js.map +7 -0
  259. package/dist/modules/cpq/setup.js +49 -0
  260. package/dist/modules/cpq/setup.js.map +7 -0
  261. package/dist/modules/cpq/subscribers/subscription-amended-log.js +18 -0
  262. package/dist/modules/cpq/subscribers/subscription-amended-log.js.map +7 -0
  263. package/dist/modules/cpq/subscribers/subscription-cancelled-log.js +19 -0
  264. package/dist/modules/cpq/subscribers/subscription-cancelled-log.js.map +7 -0
  265. package/dist/modules/cpq/subscribers/subscription-merged-log.js +20 -0
  266. package/dist/modules/cpq/subscribers/subscription-merged-log.js.map +7 -0
  267. package/dist/modules/cpq/subscribers/subscription-renewed-log.js +18 -0
  268. package/dist/modules/cpq/subscribers/subscription-renewed-log.js.map +7 -0
  269. package/dist/modules/cpq/subscribers/subscription-superseded-log.js +18 -0
  270. package/dist/modules/cpq/subscribers/subscription-superseded-log.js.map +7 -0
  271. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js +192 -0
  272. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js.map +7 -0
  273. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.js +17 -0
  274. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.js.map +7 -0
  275. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js +79 -0
  276. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js.map +7 -0
  277. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.js +17 -0
  278. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.js.map +7 -0
  279. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js +181 -0
  280. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js.map +7 -0
  281. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.js +17 -0
  282. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.js.map +7 -0
  283. package/dist/modules/cpq/widgets/injection-table.js +44 -0
  284. package/dist/modules/cpq/widgets/injection-table.js.map +7 -0
  285. package/dist/modules/cpq/workflows/WizardRunner.js +113 -0
  286. package/dist/modules/cpq/workflows/WizardRunner.js.map +7 -0
  287. package/dist/modules/cpq/workflows/WizardTrigger.js +116 -0
  288. package/dist/modules/cpq/workflows/WizardTrigger.js.map +7 -0
  289. package/dist/modules/cpq/workflows/engine.js +188 -0
  290. package/dist/modules/cpq/workflows/engine.js.map +7 -0
  291. package/dist/modules/cpq/workflows/registry.js +16 -0
  292. package/dist/modules/cpq/workflows/registry.js.map +7 -0
  293. package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js +119 -0
  294. package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js.map +7 -0
  295. package/dist/modules/cpq/workflows/steps/InventorySelectStep.js +24 -0
  296. package/dist/modules/cpq/workflows/steps/InventorySelectStep.js.map +7 -0
  297. package/dist/modules/cpq/workflows/steps/ItemListStep.js +115 -0
  298. package/dist/modules/cpq/workflows/steps/ItemListStep.js.map +7 -0
  299. package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js +327 -0
  300. package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js.map +7 -0
  301. package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js +231 -0
  302. package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js.map +7 -0
  303. package/dist/modules/cpq/workflows/steps/ReviewStep.js +152 -0
  304. package/dist/modules/cpq/workflows/steps/ReviewStep.js.map +7 -0
  305. package/dist/modules/cpq/workflows/steps/index.js +49 -0
  306. package/dist/modules/cpq/workflows/steps/index.js.map +7 -0
  307. package/dist/modules/cpq/workflows/types.js +1 -0
  308. package/dist/modules/cpq/workflows/types.js.map +7 -0
  309. package/package.json +150 -0
  310. package/src/modules/cpq/__integration__/TC-CPQ-001.spec.ts +177 -0
  311. package/src/modules/cpq/__integration__/TC-CPQ-002.spec.ts +123 -0
  312. package/src/modules/cpq/__integration__/TC-CPQ-003.spec.ts +115 -0
  313. package/src/modules/cpq/__integration__/TC-CPQ-004.spec.ts +184 -0
  314. package/src/modules/cpq/__integration__/TC-CPQ-005.spec.ts +43 -0
  315. package/src/modules/cpq/__integration__/TC-CPQ-006.spec.ts +87 -0
  316. package/src/modules/cpq/__integration__/TC-CPQ-007.spec.ts +79 -0
  317. package/src/modules/cpq/__integration__/TC-CPQ-008.spec.ts +55 -0
  318. package/src/modules/cpq/__integration__/TC-CPQ-009.spec.ts +45 -0
  319. package/src/modules/cpq/__integration__/TC-CPQ-010.spec.ts +54 -0
  320. package/src/modules/cpq/__integration__/TC-CPQ-011.spec.ts +24 -0
  321. package/src/modules/cpq/__integration__/TC-CPQ-012.spec.ts +62 -0
  322. package/src/modules/cpq/__integration__/TC-CPQ-ARC-001.spec.ts +52 -0
  323. package/src/modules/cpq/__integration__/TC-CPQ-ARC-002.spec.ts +65 -0
  324. package/src/modules/cpq/__integration__/TC-CPQ-ARC-003.spec.ts +107 -0
  325. package/src/modules/cpq/__integration__/TC-CPQ-ARC-004.spec.ts +74 -0
  326. package/src/modules/cpq/__integration__/TC-CPQ-ARC-005.spec.ts +86 -0
  327. package/src/modules/cpq/__integration__/TC-CPQ-ARC-006.spec.ts +79 -0
  328. package/src/modules/cpq/__integration__/TC-CPQ-ARC-007.spec.ts +63 -0
  329. package/src/modules/cpq/__integration__/TC-CPQ-ARC-008.spec.ts +62 -0
  330. package/src/modules/cpq/__integration__/TC-CPQ-ARC-009.spec.ts +62 -0
  331. package/src/modules/cpq/__integration__/TC-CPQ-ARC-010.spec.ts +59 -0
  332. package/src/modules/cpq/__integration__/TC-CPQ-ARC-011.spec.ts +128 -0
  333. package/src/modules/cpq/__integration__/_helpers/cpqArcFixtures.ts +208 -0
  334. package/src/modules/cpq/__tests__/package-isolation.test.ts +232 -0
  335. package/src/modules/cpq/acl.ts +26 -0
  336. package/src/modules/cpq/api/_helpers/__tests__/handleArcError.test.ts +117 -0
  337. package/src/modules/cpq/api/_helpers/handleArcError.ts +81 -0
  338. package/src/modules/cpq/api/attribute-options/route.ts +55 -0
  339. package/src/modules/cpq/api/bundle-slots/route.ts +112 -0
  340. package/src/modules/cpq/api/bundle-tree/route.ts +31 -0
  341. package/src/modules/cpq/api/context.ts +39 -0
  342. package/src/modules/cpq/api/inventory/assets/route.ts +123 -0
  343. package/src/modules/cpq/api/inventory/assets/status/route.ts +34 -0
  344. package/src/modules/cpq/api/inventory/customer/[customerId]/parent-items/route.ts +30 -0
  345. package/src/modules/cpq/api/inventory/customer/[customerId]/route.ts +31 -0
  346. package/src/modules/cpq/api/inventory/subscription-items/route.ts +107 -0
  347. package/src/modules/cpq/api/inventory/subscriptions/[subscriptionId]/change-log/route.ts +64 -0
  348. package/src/modules/cpq/api/inventory/subscriptions/expiring/route.ts +66 -0
  349. package/src/modules/cpq/api/inventory/subscriptions/route.ts +126 -0
  350. package/src/modules/cpq/api/inventory/subscriptions/status/route.ts +34 -0
  351. package/src/modules/cpq/api/offering-components/route.ts +103 -0
  352. package/src/modules/cpq/api/orders/[orderId]/activate/route.ts +48 -0
  353. package/src/modules/cpq/api/orders/[orderId]/route.ts +28 -0
  354. package/src/modules/cpq/api/orders/[orderId]/status/route.ts +38 -0
  355. package/src/modules/cpq/api/orders/route.ts +77 -0
  356. package/src/modules/cpq/api/price-rules/route.ts +210 -0
  357. package/src/modules/cpq/api/pricing-table-entries/route.ts +159 -0
  358. package/src/modules/cpq/api/pricing-tables/route.ts +202 -0
  359. package/src/modules/cpq/api/product-attributes/route.ts +175 -0
  360. package/src/modules/cpq/api/product-charges/route.ts +181 -0
  361. package/src/modules/cpq/api/product-offerings/route.ts +329 -0
  362. package/src/modules/cpq/api/product-relationships/route.ts +156 -0
  363. package/src/modules/cpq/api/product-specifications/route.ts +325 -0
  364. package/src/modules/cpq/api/quotes/[quoteId]/cancel-meta/route.ts +77 -0
  365. package/src/modules/cpq/api/quotes/[quoteId]/clone/route.ts +28 -0
  366. package/src/modules/cpq/api/quotes/[quoteId]/items/[lineId]/route.ts +55 -0
  367. package/src/modules/cpq/api/quotes/[quoteId]/items/route.ts +26 -0
  368. package/src/modules/cpq/api/quotes/[quoteId]/merge-meta/route.ts +78 -0
  369. package/src/modules/cpq/api/quotes/[quoteId]/recalculate/route.ts +34 -0
  370. package/src/modules/cpq/api/quotes/[quoteId]/route.ts +109 -0
  371. package/src/modules/cpq/api/quotes/[quoteId]/status/route.ts +26 -0
  372. package/src/modules/cpq/api/quotes/[quoteId]/target-subscriptions/[targetId]/route.ts +91 -0
  373. package/src/modules/cpq/api/quotes/[quoteId]/target-subscriptions/route.ts +107 -0
  374. package/src/modules/cpq/api/quotes/attributes/route.ts +61 -0
  375. package/src/modules/cpq/api/quotes/from-subscription/route.ts +85 -0
  376. package/src/modules/cpq/api/quotes/price/route.ts +81 -0
  377. package/src/modules/cpq/api/quotes/route.ts +114 -0
  378. package/src/modules/cpq/api/quotes/validate-relationships/route.ts +100 -0
  379. package/src/modules/cpq/api/resolveQuotingService.ts +11 -0
  380. package/src/modules/cpq/api/wizards/resolve/route.ts +39 -0
  381. package/src/modules/cpq/api/wizards/route.ts +127 -0
  382. package/src/modules/cpq/backend/cpq/inventory/AssetsTable.tsx +166 -0
  383. package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +251 -0
  384. package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.ts +9 -0
  385. package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.tsx +440 -0
  386. package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +16 -0
  387. package/src/modules/cpq/backend/cpq/inventory/page.tsx +49 -0
  388. package/src/modules/cpq/backend/cpq/inventory/shared.tsx +32 -0
  389. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.ts +9 -0
  390. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +1085 -0
  391. package/src/modules/cpq/backend/cpq/offerings/[id]/page.tsx +1165 -0
  392. package/src/modules/cpq/backend/cpq/offerings/page.meta.ts +16 -0
  393. package/src/modules/cpq/backend/cpq/offerings/page.tsx +468 -0
  394. package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +921 -0
  395. package/src/modules/cpq/backend/cpq/orders/page.meta.ts +16 -0
  396. package/src/modules/cpq/backend/cpq/orders/page.tsx +182 -0
  397. package/src/modules/cpq/backend/cpq/price-rules/PriceRuleForm.tsx +310 -0
  398. package/src/modules/cpq/backend/cpq/price-rules/[id]/page.meta.ts +9 -0
  399. package/src/modules/cpq/backend/cpq/price-rules/[id]/page.tsx +472 -0
  400. package/src/modules/cpq/backend/cpq/price-rules/page.meta.ts +16 -0
  401. package/src/modules/cpq/backend/cpq/price-rules/page.tsx +253 -0
  402. package/src/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.tsx +431 -0
  403. package/src/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.tsx +122 -0
  404. package/src/modules/cpq/backend/cpq/pricing/[id]/page.tsx +588 -0
  405. package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxExport.ts +90 -0
  406. package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.ts +338 -0
  407. package/src/modules/cpq/backend/cpq/pricing/page.meta.ts +16 -0
  408. package/src/modules/cpq/backend/cpq/pricing/page.tsx +111 -0
  409. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.tsx +737 -0
  410. package/src/modules/cpq/backend/cpq/quotes/[id]/page.tsx +1721 -0
  411. package/src/modules/cpq/backend/cpq/quotes/page.meta.ts +16 -0
  412. package/src/modules/cpq/backend/cpq/quotes/page.tsx +370 -0
  413. package/src/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.tsx +300 -0
  414. package/src/modules/cpq/backend/cpq/specifications/[id]/page.tsx +1722 -0
  415. package/src/modules/cpq/backend/cpq/specifications/page.meta.ts +16 -0
  416. package/src/modules/cpq/backend/cpq/specifications/page.tsx +191 -0
  417. package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.tsx +319 -0
  418. package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/page.tsx +234 -0
  419. package/src/modules/cpq/backend/cpq/wizards/page.meta.ts +16 -0
  420. package/src/modules/cpq/backend/cpq/wizards/page.tsx +141 -0
  421. package/src/modules/cpq/ce.ts +150 -0
  422. package/src/modules/cpq/cli.ts +10 -0
  423. package/src/modules/cpq/components/CpqListView.tsx +431 -0
  424. package/src/modules/cpq/components/NumberInput.tsx +166 -0
  425. package/src/modules/cpq/components/StatusPath.tsx +116 -0
  426. package/src/modules/cpq/components/statusMaps.ts +148 -0
  427. package/src/modules/cpq/components/useCpqRowActions.tsx +183 -0
  428. package/src/modules/cpq/data/__tests__/validators.arc.test.ts +271 -0
  429. package/src/modules/cpq/data/__tests__/validators.test.ts +782 -0
  430. package/src/modules/cpq/data/entities.ts +1467 -0
  431. package/src/modules/cpq/data/validators.ts +663 -0
  432. package/src/modules/cpq/di.ts +70 -0
  433. package/src/modules/cpq/events.ts +62 -0
  434. package/src/modules/cpq/index.ts +15 -0
  435. package/src/modules/cpq/lib/seeds/__tests__/api.test.ts +86 -0
  436. package/src/modules/cpq/lib/seeds/__tests__/tenant-provisioning.test.ts +349 -0
  437. package/src/modules/cpq/lib/seeds/api.ts +119 -0
  438. package/src/modules/cpq/lib/seeds/tenant-provisioning.ts +239 -0
  439. package/src/modules/cpq/lib/seeds.ts +18 -0
  440. package/src/modules/cpq/migrations/.snapshot-open-mercato.json +7473 -0
  441. package/src/modules/cpq/migrations/Migration20260220220000_cpq.ts +51 -0
  442. package/src/modules/cpq/migrations/Migration20260330000000_cpq_product_domain.ts +70 -0
  443. package/src/modules/cpq/migrations/Migration20260331000000_cpq_charge_unique_per_offering.ts +15 -0
  444. package/src/modules/cpq/migrations/Migration20260401000000_cpq_quoting_v2.ts +73 -0
  445. package/src/modules/cpq/migrations/Migration20260402000000_cpq_workflows.ts +59 -0
  446. package/src/modules/cpq/migrations/Migration20260407000000_cpq_pricing_tables_v2.ts +30 -0
  447. package/src/modules/cpq/migrations/Migration20260407100000_cpq_price_rules.ts +36 -0
  448. package/src/modules/cpq/migrations/Migration20260408000000_cpq_price_rules.ts +33 -0
  449. package/src/modules/cpq/migrations/Migration20260410000000_cpq_drop_datacentres_inventory.ts +22 -0
  450. package/src/modules/cpq/migrations/Migration20260410000000_cpq_wizard_rename.ts +56 -0
  451. package/src/modules/cpq/migrations/Migration20260410100000_cpq_inventory.ts +118 -0
  452. package/src/modules/cpq/migrations/Migration20260411000000_cpq_orders.ts +62 -0
  453. package/src/modules/cpq/migrations/Migration20260412000000_cpq_bundled_offerings.ts +33 -0
  454. package/src/modules/cpq/migrations/Migration20260504064621_cpq_arc.ts +68 -0
  455. package/src/modules/cpq/migrations/Migration20260514000000_cpq_spec_merge_retired_deprecated.ts +30 -0
  456. package/src/modules/cpq/migrations/Migration20260514100000_cpq_offering_merge_retired_deprecated.ts +27 -0
  457. package/src/modules/cpq/migrations/Migration20260514110000_cpq_list_search_indexes.ts +82 -0
  458. package/src/modules/cpq/migrations/Migration20260515000000_cpq_inventory_subscriptions_search_indexes.ts +52 -0
  459. package/src/modules/cpq/services/__tests__/_helpers/mockEm.ts +59 -0
  460. package/src/modules/cpq/services/__tests__/cpqBundleService.test.ts +661 -0
  461. package/src/modules/cpq/services/__tests__/cpqInventoryService.arc.test.ts +357 -0
  462. package/src/modules/cpq/services/__tests__/cpqInventoryService.test.ts +718 -0
  463. package/src/modules/cpq/services/__tests__/cpqOrderService.test.ts +603 -0
  464. package/src/modules/cpq/services/__tests__/cpqPricingService.test.ts +1012 -0
  465. package/src/modules/cpq/services/__tests__/cpqProductService.test.ts +603 -0
  466. package/src/modules/cpq/services/__tests__/cpqQuotingService.arc.test.ts +143 -0
  467. package/src/modules/cpq/services/__tests__/cpqQuotingService.test.ts +658 -0
  468. package/src/modules/cpq/services/__tests__/cpqValidationService.test.ts +811 -0
  469. package/src/modules/cpq/services/__tests__/cpqWizardService.test.ts +389 -0
  470. package/src/modules/cpq/services/__tests__/types.test.ts +359 -0
  471. package/src/modules/cpq/services/cpqBundleService.ts +671 -0
  472. package/src/modules/cpq/services/cpqInventoryService.ts +1929 -0
  473. package/src/modules/cpq/services/cpqOrderService.ts +1230 -0
  474. package/src/modules/cpq/services/cpqPricingService.ts +412 -0
  475. package/src/modules/cpq/services/cpqProductService.ts +311 -0
  476. package/src/modules/cpq/services/cpqQuotingService.ts +2638 -0
  477. package/src/modules/cpq/services/cpqValidationService.ts +323 -0
  478. package/src/modules/cpq/services/cpqWizardService.ts +204 -0
  479. package/src/modules/cpq/services/types.ts +303 -0
  480. package/src/modules/cpq/setup.ts +63 -0
  481. package/src/modules/cpq/subscribers/subscription-amended-log.ts +20 -0
  482. package/src/modules/cpq/subscribers/subscription-cancelled-log.ts +19 -0
  483. package/src/modules/cpq/subscribers/subscription-merged-log.ts +22 -0
  484. package/src/modules/cpq/subscribers/subscription-renewed-log.ts +18 -0
  485. package/src/modules/cpq/subscribers/subscription-superseded-log.ts +19 -0
  486. package/src/modules/cpq/widgets/injection/customer-inventory/widget.client.tsx +339 -0
  487. package/src/modules/cpq/widgets/injection/customer-inventory/widget.ts +16 -0
  488. package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.client.tsx +96 -0
  489. package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.ts +16 -0
  490. package/src/modules/cpq/widgets/injection/quote-configurator/widget.client.tsx +265 -0
  491. package/src/modules/cpq/widgets/injection/quote-configurator/widget.ts +16 -0
  492. package/src/modules/cpq/widgets/injection-table.ts +42 -0
  493. package/src/modules/cpq/workflows/WizardRunner.tsx +158 -0
  494. package/src/modules/cpq/workflows/WizardTrigger.tsx +142 -0
  495. package/src/modules/cpq/workflows/engine.tsx +278 -0
  496. package/src/modules/cpq/workflows/registry.ts +15 -0
  497. package/src/modules/cpq/workflows/steps/CustomerSelectStep.tsx +136 -0
  498. package/src/modules/cpq/workflows/steps/InventorySelectStep.tsx +34 -0
  499. package/src/modules/cpq/workflows/steps/ItemListStep.tsx +146 -0
  500. package/src/modules/cpq/workflows/steps/OfferingSelectStep.tsx +438 -0
  501. package/src/modules/cpq/workflows/steps/ProductConfigureStep.tsx +287 -0
  502. package/src/modules/cpq/workflows/steps/ReviewStep.tsx +219 -0
  503. package/src/modules/cpq/workflows/steps/index.ts +51 -0
  504. package/src/modules/cpq/workflows/types.ts +102 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/cpq/backend/cpq/quotes/%5Bid%5D/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter, useParams, useSearchParams } from 'next/navigation'\nimport ArcQuoteConfigurator, {\n type AttachedTarget,\n} from './_components/ArcQuoteConfigurator'\nimport { StatusPath } from '../../../../components/StatusPath'\nimport { ArrowRight, ExternalLink, Plus } from 'lucide-react'\nimport { Alert, AlertTitle, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport type { ActionItem } from '@open-mercato/ui/backend/forms/ActionsDropdown'\nimport { NumberInput } from '../../../../components/NumberInput'\nimport {\n formatStatusLabel,\n quoteCpqStatusMap,\n type QuoteCpqStatus,\n} from '../../../../components/statusMaps'\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\u2500\n\ntype ConstrainedAttribute = {\n code: string\n name: string\n attributeType: string\n isRequired: boolean\n options: Array<{ value: string; label: string }> | null\n constraints: Record<string, unknown> | null\n defaultValue: unknown | null\n helpText: string | null\n}\n\ntype TierBreakdownEntry = { tier: number; from: number; to: number; pricePerUnit: number; quantity: number; subtotal: number }\ntype RuleAdjustment = { ruleCode: string; ruleName: string; ruleType: string; value: number; unitPriceBefore: number; unitPriceAfter: number; delta: number }\n\ntype ResolvedCharge = {\n chargeCode: string\n chargeName: string\n chargeType: 'nrc' | 'mrc' | 'usage'\n pricingMethod?: 'flat' | 'tiered' | 'per_unit'\n unitPrice: number\n quantity: number | null\n totalPrice: number | null\n currencyCode: string\n breakdown?: { tiers: TierBreakdownEntry[] } | null\n note?: string | null\n adjustments?: RuleAdjustment[] | null\n}\n\ntype QuoteLineAction = 'add' | 'modify' | 'cancel'\n\ntype ArcLineSource = {\n subscriptionItemId: string\n name: string\n mrcAmount: number\n nrcAmount: number\n quantity: number\n}\n\ntype QuoteLine = {\n lineId: string\n offeringId: string | null\n offeringName: string\n offeringType: string | null\n parentLineId: string | null\n action: QuoteLineAction\n quantity: number\n configuration: Record<string, unknown>\n nrcTotal: number\n mrcTotal: number\n charges: ResolvedCharge[]\n isConfigured: boolean\n validationErrors: Array<{ message: string }> | null\n arcSource: ArcLineSource | null\n targetSubscriptionId: string | null\n}\n\ntype QuoteResult = {\n id: string\n quoteId: string\n quoteNumber: string\n customerId: string\n customerName: string | null\n cpqStatus: string\n version: number\n currencyCode: string\n convertedOrderId: string | null\n validationResult: { valid: boolean; errors: Array<{ message: string }> }\n pricingSummary: {\n nrcTotal: number\n mrcTotal: number\n usageCharges: Array<{ chargeCode: string; chargeName: string; unitPrice: number; note: string | null }>\n usageTotalEstimated: number | null\n currencyCode: string\n }\n lines: QuoteLine[]\n}\n\ntype Offering = {\n id: string\n code: string\n name: string\n description?: string | null\n specId: string\n lifecycleStatus: string\n}\n\ntype BundleTreeSlot = {\n slotId: string\n componentGroup: string\n name: string\n cardinalityMin: number\n cardinalityMax: number | null\n components: Array<{\n componentId: string\n childOffering: { offeringId: string; offeringCode: string; offeringName: string; offeringType: string }\n isDefault: boolean\n sortOrder: number\n }>\n}\n\ntype BundleTree = {\n offeringId: string\n offeringName: string\n offeringType: string\n slots: BundleTreeSlot[]\n}\n\n// \u2500\u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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// `ALLOWED_TRANSITIONS` used to mirror the backend state machine on the\n// client to gate the inline status menu. Per product decision the UI\n// now lets the operator jump between any pair of statuses; the backend\n// is the single source of truth, so the table is no longer needed here.\n\nfunction fmt(amount: number, currency: string): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)\n}\n\nconst RULE_TYPE_LABELS: Record<string, string> = {\n discount_percent: '% discount',\n discount_absolute: 'fixed discount',\n surcharge_percent: '% surcharge',\n surcharge_absolute: 'fixed surcharge',\n price_override: 'override',\n}\n\nfunction fmtRuleValue(adj: RuleAdjustment, currency?: string): string {\n if (adj.ruleType === 'discount_percent' || adj.ruleType === 'surcharge_percent') return `${adj.value}%`\n if (currency) return fmt(adj.value, currency)\n return String(adj.value)\n}\n\nasync function apiJson<T>(url: string, init?: RequestInit): Promise<T> {\n const res = await fetch(url, init)\n const json = await res.json()\n if (!res.ok) throw new Error(json?.error ?? `Request failed (${res.status})`)\n return json as T\n}\n\n// \u2500\u2500\u2500 Header sub-components \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nfunction MetaCard({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <div className=\"rounded-lg border bg-card p-4\">\n <div className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {label}\n </div>\n <div className=\"mt-1 text-sm\">{children}</div>\n </div>\n )\n}\n\nfunction MoreActionsDropdown({ items }: { items: ActionItem[] }) {\n // Local dropdown \u2014 `ActionsDropdown` inside FormHeader.actionsContent\n // would conflict with the inline button placement. This is a thin\n // <details>-style trigger; menuActions on FormHeader would render it\n // inside the header layout, but here we want it adjacent to other\n // primary buttons.\n const [open, setOpen] = React.useState(false)\n const ref = React.useRef<HTMLDivElement>(null)\n React.useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n if (items.length === 0) return null\n return (\n <div className=\"relative\" ref={ref}>\n <Button type=\"button\" variant=\"outline\" onClick={() => setOpen((v) => !v)}>\n Actions\n <svg className=\"h-3 w-3 ml-1\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 8.25l-7.5 7.5-7.5-7.5\" />\n </svg>\n </Button>\n {open && (\n <div className=\"absolute right-0 top-full mt-1 z-50 min-w-[200px] rounded-md border bg-popover shadow-md py-1\">\n {items.map((item) => {\n const isDelete = item.id === 'delete'\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => { setOpen(false); item.onSelect() }}\n disabled={item.disabled || item.loading}\n // Use bg-accent on hover (same token as Radix-style menu items in OM)\n // and tint delete with destructive colors so the affordance is obvious.\n className={\n 'w-full px-3 py-2 text-left text-sm flex items-center gap-2 transition-colors ' +\n 'disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent ' +\n (isDelete\n ? 'text-destructive hover:bg-destructive/10 focus:bg-destructive/10 focus:outline-none'\n : 'hover:bg-accent focus:bg-accent focus:outline-none')\n }\n >\n {item.icon ? <item.icon className=\"h-4 w-4 text-muted-foreground\" /> : null}\n <span>{item.label}</span>\n </button>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nfunction buildMoreActions({\n recalculate,\n submitting,\n deletable,\n onDelete,\n deleting,\n}: {\n recalculate: () => void\n submitting: boolean\n deletable: boolean\n onDelete: () => void\n deleting: boolean\n}): ActionItem[] {\n const items: ActionItem[] = [\n {\n id: 'recalculate',\n label: 'Recalculate',\n onSelect: recalculate,\n loading: submitting,\n disabled: submitting,\n },\n ]\n if (deletable) {\n items.push({\n id: 'delete',\n label: 'Delete',\n onSelect: onDelete,\n disabled: deleting,\n loading: deleting,\n })\n }\n return items\n}\n\n// \u2500\u2500\u2500 Main Page \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 CpqQuoteDetailPage(props: { params?: { id?: string } }) {\n const router = useRouter()\n const urlParams = useParams()\n const searchParams = useSearchParams()\n const cpqConfigId = (props.params?.id ?? urlParams?.id) as string\n const isNew = cpqConfigId === 'new'\n\n const [cpqQuote, setCpqQuote] = React.useState<QuoteResult | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [submitting, setSubmitting] = React.useState(false)\n\n // Configurator state\n const [view, setView] = React.useState<'summary' | 'add-offering' | 'configure' | 'edit'>('summary')\n const [offerings, setOfferings] = React.useState<Offering[]>([])\n const [offeringsLoading, setOfferingsLoading] = React.useState(false)\n const [offeringSearch, setOfferingSearch] = React.useState('')\n const [selectedOffering, setSelectedOffering] = React.useState<Offering | null>(null)\n const [attributes, setAttributes] = React.useState<ConstrainedAttribute[]>([])\n const [config, setConfig] = React.useState<Record<string, unknown>>({})\n const [quantity, setQuantity] = React.useState(1)\n const [editingLineId, setEditingLineId] = React.useState<string | null>(null)\n const [addingToParentLineId, setAddingToParentLineId] = React.useState<string | null>(null)\n // XD-250 multi-target ARC: when adding a top-level offering operator can\n // pick 1..N target subs (default = all) and we fire one POST per target.\n // For \"Add Component\" to a bundle, this is forced to a single id (the\n // parent line's target) since a bundle component must follow its bundle.\n const [addingTargetSubIds, setAddingTargetSubIds] = React.useState<string[]>([])\n const [expandedLines, setExpandedLines] = React.useState<Set<string>>(new Set())\n const [converting, setConverting] = React.useState(false)\n const [transitioning, setTransitioning] = React.useState(false)\n const [deleting, setDeleting] = React.useState(false)\n const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false)\n const [pricingDetail, setPricingDetail] = React.useState<{ lineIdx: number; chargeIdx: number } | null>(null)\n\n // \u2500\u2500\u2500 XD-250 ARC 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\n const [arcTargets, setArcTargets] = React.useState<AttachedTarget[]>([])\n const [arcQuoteType, setArcQuoteType] = React.useState<'new' | 'amend' | 'renew' | 'cancel'>('new')\n const [arcDrawerOpen, setArcDrawerOpen] = React.useState(false)\n\n const loadArcTargets = React.useCallback(async () => {\n try {\n const res = await fetch(`/api/cpq/quotes/${cpqConfigId}/target-subscriptions`)\n if (!res.ok) return\n const data = await res.json()\n const items: AttachedTarget[] = data.items ?? []\n setArcTargets(items)\n if (items.length > 0) {\n setArcQuoteType(items[0].quoteType as 'amend' | 'renew' | 'cancel')\n } else {\n setArcQuoteType('new')\n }\n } catch {\n // best-effort \u2014 non-ARC quotes have no targets, that's fine.\n }\n }, [cpqConfigId])\n\n React.useEffect(() => {\n if (!cpqConfigId || isNew) return\n void loadArcTargets()\n }, [cpqConfigId, isNew, loadArcTargets])\n\n // \u2500\u2500\u2500 Load or create \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 if (isNew) {\n // Create new CPQ quote from query params\n const quoteId = searchParams.get('quoteId')\n const customerId = searchParams.get('customerId')\n if (!customerId) {\n setError('customerId is required to create a CPQ quote')\n setLoading(false)\n return\n }\n async function create() {\n try {\n const body: Record<string, string> = { customerId: customerId! }\n if (quoteId) body.quoteId = quoteId\n const result = await apiJson<QuoteResult>('/api/cpq/quotes', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n router.replace(`/backend/cpq/quotes/${result.id}`)\n } catch (err) {\n setError((err as Error).message)\n setLoading(false)\n }\n }\n create()\n return\n }\n\n let cancelled = false\n async function load() {\n try {\n const result = await apiJson<QuoteResult>(`/api/cpq/quotes/${cpqConfigId}`)\n if (!cancelled) setCpqQuote(result)\n } catch (err) {\n if (!cancelled) setError((err as Error).message)\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [cpqConfigId, isNew, searchParams, router])\n\n // \u2500\u2500\u2500 Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 loadOfferings = async () => {\n setOfferingsLoading(true)\n try {\n const result = await apiJson<{ items: Offering[] }>('/api/cpq/product-offerings?pageSize=100&lifecycleStatus=active')\n setOfferings(result.items ?? [])\n } catch { setOfferings([]) }\n finally { setOfferingsLoading(false) }\n }\n\n const loadAttributes = async (offeringId: string, currentConfig: Record<string, unknown> = {}) => {\n try {\n const params = new URLSearchParams({ offeringId })\n if (Object.keys(currentConfig).length > 0) params.set('configuration', JSON.stringify(currentConfig))\n const result = await apiJson<{ attributes: ConstrainedAttribute[] }>(`/api/cpq/quotes/attributes?${params}`)\n setAttributes(result.attributes ?? [])\n } catch { setAttributes([]) }\n }\n\n const addItem = async () => {\n if (!cpqQuote || !selectedOffering) return\n try {\n setSubmitting(true); setError(null)\n // XD-250 multi-target ARC: when \u22652 targets selected, fire one POST per\n // target \u2014 backend creates one line per request, each tagged with its\n // own targetSubscriptionId. Single target / non-ARC quote: list is\n // empty or 1-elem, we just do one POST and let the server auto-inherit.\n const targetsToPost = addingTargetSubIds.length > 0 ? addingTargetSubIds : [null]\n let lastResult: QuoteResult | null = null\n for (const tid of targetsToPost) {\n const body: Record<string, unknown> = { offeringId: selectedOffering.id, configuration: config, quantity }\n if (addingToParentLineId) body.parentLineId = addingToParentLineId\n if (tid) body.targetSubscriptionId = tid\n lastResult = await apiJson<QuoteResult>(`/api/cpq/quotes/${cpqQuote.id}/items`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n }\n if (lastResult) setCpqQuote(lastResult)\n resetConfigState()\n setView('summary')\n } catch (err) { setError((err as Error).message) }\n finally { setSubmitting(false) }\n }\n\n const updateItem = async (lineId: string) => {\n if (!cpqQuote) return\n try {\n setSubmitting(true); setError(null)\n const result = await apiJson<QuoteResult>(`/api/cpq/quotes/${cpqQuote.id}/items/${lineId}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ configuration: config, quantity }),\n })\n setCpqQuote(result)\n resetConfigState()\n setView('summary')\n } catch (err) { setError((err as Error).message) }\n finally { setSubmitting(false) }\n }\n\n const removeItem = async (lineId: string) => {\n if (!cpqQuote) return\n try {\n setError(null)\n const result = await apiJson<QuoteResult>(`/api/cpq/quotes/${cpqQuote.id}/items/${lineId}`, { method: 'DELETE' })\n setCpqQuote(result)\n } catch (err) { setError((err as Error).message) }\n }\n\n const recalculate = async () => {\n if (!cpqQuote) return\n try {\n setSubmitting(true); setError(null)\n const result = await apiJson<QuoteResult>(`/api/cpq/quotes/${cpqQuote.id}/recalculate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ save: true }),\n })\n setCpqQuote(result)\n } catch (err) { setError((err as Error).message) }\n finally { setSubmitting(false) }\n }\n\n const convertToOrder = async () => {\n if (!cpqQuote) return\n try {\n setConverting(true); setError(null)\n const result = await apiJson<{ id: string }>('/api/cpq/orders', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ quoteId: cpqQuote.id }),\n })\n router.push(`/backend/cpq/orders/${result.id}`)\n } catch (err) { setError((err as Error).message) }\n finally { setConverting(false) }\n }\n\n const transitionStatus = async (targetStatus: string) => {\n if (!cpqQuote) return\n try {\n setTransitioning(true); setError(null)\n const result = await apiJson<QuoteResult>(`/api/cpq/quotes/${cpqQuote.id}/status`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ targetStatus }),\n })\n setCpqQuote(result)\n } catch (err) { setError((err as Error).message) }\n finally { setTransitioning(false) }\n }\n\n const deleteQuote = async () => {\n if (!cpqQuote) return\n try {\n setDeleting(true); setError(null); setShowDeleteConfirm(false)\n await apiJson<{ ok: boolean }>(`/api/cpq/quotes/${cpqQuote.id}`, { method: 'DELETE' })\n router.push('/backend/cpq/quotes')\n } catch (err) { setError((err as Error).message) }\n finally { setDeleting(false) }\n }\n\n const resetConfigState = () => {\n setSelectedOffering(null)\n setAttributes([])\n setConfig({})\n setQuantity(1)\n setEditingLineId(null)\n setAddingToParentLineId(null)\n }\n\n const startAddOffering = () => {\n resetConfigState()\n // Default: apply to all attached targets (operator can uncheck in the picker).\n setAddingTargetSubIds(arcTargets.map((t) => t.subscriptionId))\n loadOfferings()\n setView('add-offering')\n }\n\n const startAddComponent = async (parentLineId: string, offeringId?: string) => {\n setSelectedOffering(null)\n setAttributes([])\n setConfig({})\n setQuantity(1)\n setEditingLineId(null)\n setAddingToParentLineId(parentLineId)\n // Inherit the parent line's target so a bundle component lands on the\n // same subscription as its parent (XD-250 multi-target ARC). For\n // components there's no choice \u2014 bundle \u2194 component must agree.\n const parent = cpqQuote?.lines.find((l) => l.lineId === parentLineId)\n const inherited = parent?.targetSubscriptionId ?? arcTargets[0]?.subscriptionId\n setAddingTargetSubIds(inherited ? [inherited] : [])\n if (offeringId) {\n try {\n const result = await apiJson<{ items: Offering[] }>('/api/cpq/product-offerings?pageSize=100&lifecycleStatus=active')\n const match = (result.items ?? []).find((o) => o.id === offeringId)\n if (match) {\n selectOffering(match)\n return\n }\n } catch { /* fall through to browser */ }\n }\n loadOfferings()\n setView('add-offering')\n }\n\n const selectOffering = (o: Offering) => {\n setSelectedOffering(o); setConfig({}); setQuantity(1)\n loadAttributes(o.id)\n setView('configure')\n }\n\n const startEditLine = (line: QuoteLine) => {\n setEditingLineId(line.lineId)\n setConfig(line.configuration ?? {})\n setQuantity(line.quantity)\n if (line.offeringId) loadAttributes(line.offeringId, line.configuration ?? {})\n setView('edit')\n }\n\n const toggleLine = (id: string) => {\n setExpandedLines((prev) => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n })\n }\n\n // \u2500\u2500\u2500 Render: loading / error \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 (\n <div className=\"flex items-center gap-2 py-12 justify-center text-sm text-muted-foreground\">\n <Spinner /> Loading\u2026\n </div>\n )\n }\n\n if (!cpqQuote) {\n return (\n <div className=\"space-y-4\">\n <button onClick={() => router.push('/backend/cpq/quotes')} className=\"text-sm text-muted-foreground hover:text-foreground\">\u2190 Back to Quotes</button>\n {error && <ErrorBanner message={error} />}\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">Quote not found.</div>\n </div>\n )\n }\n\n // \u2500\u2500\u2500 Render: detail \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 { pricingSummary: summary, currencyCode: currency } = cpqQuote\n\n const arcEditable = ['new', 'incomplete', 'ready'].includes(cpqQuote.cpqStatus)\n const isMergeRenew =\n arcQuoteType === 'renew' &&\n arcTargets.length >= 2 &&\n arcTargets.every((t) => t.mergeAction === 'absorb')\n\n // XD-250 multi-target ARC: map subscriptionId \u2192 friendly code (e.g. SUB-...).\n // Used for the per-line target badge so the operator can see which sub each\n // line acts on; only meaningful when there are 2+ targets. Plain map (not\n // useMemo) because this whole block is after the loading / not-found early\n // returns \u2014 adding a hook here would violate Rules of Hooks. Tiny N (count\n // of attached ARC targets) so re-building per render is fine.\n const arcTargetCodeMap = new Map<string, string>()\n for (const t of arcTargets) {\n if (t.subscription?.code) arcTargetCodeMap.set(t.subscriptionId, t.subscription.code)\n }\n\n return (\n <div className=\"space-y-6\">\n {arcDrawerOpen && (\n <ArcQuoteConfigurator\n quoteId={cpqQuote.id}\n customerId={cpqQuote.customerId}\n customerName={cpqQuote.customerName}\n currencyCode={cpqQuote.currencyCode}\n initialType={arcQuoteType}\n initialTargets={arcTargets}\n editable={arcEditable}\n onClose={() => setArcDrawerOpen(false)}\n onChanged={async () => {\n await loadArcTargets()\n // Drawer attached / detached targets \u2014 backend may have mirrored\n // items from new targets (XD-250 multi-target ARC), so refetch\n // the full quote to pick up the new lines without a hard refresh.\n try {\n const fresh = await apiJson<QuoteResult>(`/api/cpq/quotes/${cpqQuote.id}`)\n setCpqQuote(fresh)\n } catch {\n /* ignore \u2014 loadArcTargets already surfaced any error */\n }\n }}\n />\n )}\n {/* Header \u2014 uses the standard Open Mercato `FormHeader mode=\"detail\"`\n so CPQ matches the rest of the admin. Title is just the quote\n number (no \"Quote \u2026\" prefix); badges sit underneath; secondary\n context (customer / version / currency) lives in dedicated meta\n cards below the header, not in a thin meta line. */}\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/cpq/quotes\"\n backLabel=\"Back to CPQ Quotes\"\n entityTypeLabel=\"CPQ Quote\"\n title={cpqQuote.quoteNumber || cpqQuote.customerName || 'Untitled'}\n statusBadge={\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Tag variant={quoteCpqStatusMap[cpqQuote.cpqStatus as QuoteCpqStatus] ?? 'neutral'} dot>\n {formatStatusLabel(cpqQuote.cpqStatus)}\n </Tag>\n {arcQuoteType !== 'new' && (\n <Tag variant=\"brand\" className=\"uppercase\">{arcQuoteType}</Tag>\n )}\n {cpqQuote.convertedOrderId && <Tag variant=\"success\" dot>Converted</Tag>}\n </div>\n }\n // FormHeader.detail ignores `utilityActions` whenever `actionsContent`\n // is set, so we render the \"View Sales Quote\" link inline alongside\n // the primary actions to keep it visible.\n actionsContent={\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/sales/quotes/${cpqQuote.quoteId}`)}\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n View Sales Quote\n </Button>\n {cpqQuote.convertedOrderId ? (\n <Button\n type=\"button\"\n onClick={() => router.push(`/backend/cpq/orders/${cpqQuote.convertedOrderId}`)}\n >\n <ArrowRight className=\"h-4 w-4\" />\n Go to order\n </Button>\n ) : view !== 'summary' ? (\n <Button type=\"button\" variant=\"outline\" onClick={() => { resetConfigState(); setView('summary') }}>\n Cancel\n </Button>\n ) : (\n <>\n <Button type=\"button\" onClick={startAddOffering}>\n <Plus className=\"h-4 w-4\" />\n Add Offering\n </Button>\n {arcEditable && (\n <Button type=\"button\" variant=\"outline\" onClick={() => setArcDrawerOpen(true)}>\n Modify Subscription\n </Button>\n )}\n {cpqQuote.cpqStatus === 'accepted' && (\n <Button type=\"button\" onClick={convertToOrder} disabled={converting}>\n {converting ? <Spinner /> : <ArrowRight className=\"h-4 w-4\" />}\n Convert to Order\n </Button>\n )}\n <MoreActionsDropdown\n items={buildMoreActions({\n recalculate,\n submitting,\n deletable: !['accepted', 'rejected', 'cancelled'].includes(cpqQuote.cpqStatus),\n onDelete: () => setShowDeleteConfirm(true),\n deleting,\n })}\n />\n </>\n )}\n </>\n }\n />\n\n {/* Per user feedback, order below the FormHeader is:\n 1. Status path (operator-facing lifecycle nav)\n 2. ARC info (amend/renew/cancel banner with targets)\n 3. Customer / Version / Currency meta cards\n 4. Pricing summary + line items (further down in the page)\n Status path and ARC info are higher because they describe what\n the user is *doing*; the meta cards are reference info. */}\n\n {/* Status path \u2014 every step is clickable so the operator can move\n between any pair of statuses. Backend enforces ARC-specific\n guards (validateArcQuote on submit-for-approval) but no longer\n gates simple transitions. */}\n <div className=\"flex items-center gap-3 flex-wrap\">\n <StatusPath\n // Per product decision the quote status path lets the operator\n // jump between any pair of statuses, so `allowedTransitions` is\n // omitted \u2014 backend validates ARC-specific guards.\n // `pre_approved` aliases into the `approved` slot for layout.\n current={cpqQuote.cpqStatus}\n path={\n cpqQuote.cpqStatus === 'pre_approved'\n ? ['new', 'incomplete', 'ready', 'in_approval', 'pre_approved', 'with_customer', 'accepted']\n : ['new', 'incomplete', 'ready', 'in_approval', 'approved', 'with_customer', 'accepted']\n }\n terminals={['rejected', 'cancelled']}\n statusMap={quoteCpqStatusMap}\n onTransition={transitionStatus}\n disabled={transitioning}\n ariaLabel=\"Quote status path\"\n />\n {transitioning && <Spinner />}\n </div>\n\n {error && <ErrorBanner message={error} onDismiss={() => setError(null)} />}\n\n {arcQuoteType !== 'new' && arcTargets.length > 0 && (\n <div className=\"rounded-md border border-brand-violet/30 bg-brand-violet/10 px-4 py-3 text-sm text-brand-violet\">\n <div className=\"flex items-center justify-between\">\n <div>\n <span className=\"font-medium uppercase\">{arcQuoteType}</span>\n {' \u2022 '}\n {arcTargets.length} target{arcTargets.length === 1 ? '' : 's'}:\n {' '}\n {arcTargets.map((t, i) => (\n <span key={t.id}>\n {i > 0 && ', '}\n <button\n onClick={() =>\n router.push(`/backend/cpq/inventory/subscriptions/${t.subscriptionId}`)\n }\n className=\"text-brand-violet hover:underline\"\n >\n {t.subscription?.code ?? t.subscriptionId.slice(0, 8)}\n </button>\n </span>\n ))}\n {isMergeRenew && (\n <span className=\"ml-2 text-status-warning-text font-medium\">\n \u2022 Merging into a new contract\n </span>\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* Meta cards \u2014 secondary reference info (customer, version,\n currency). Mirrors the sidebar tiles in the standard\n sales-document detail layout. */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n <MetaCard label=\"Customer\">\n {cpqQuote.customerName ? (\n <span className=\"font-medium\">{cpqQuote.customerName}</span>\n ) : (\n <span className=\"font-mono text-xs text-muted-foreground\">\n {cpqQuote.customerId.slice(0, 8)}\u2026\n </span>\n )}\n </MetaCard>\n <MetaCard label=\"Version\">\n <span className=\"font-medium\">v{cpqQuote.version}</span>\n </MetaCard>\n <MetaCard label=\"Currency\">\n <span className=\"font-medium\">{currency}</span>\n </MetaCard>\n </div>\n\n {showDeleteConfirm && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\" onClick={() => setShowDeleteConfirm(false)}>\n <div className=\"w-full max-w-sm rounded-lg border bg-card shadow-xl\" onClick={(e) => e.stopPropagation()}>\n <div className=\"px-4 py-3 border-b\">\n <h3 className=\"text-sm font-medium\">Delete Quote</h3>\n </div>\n <div className=\"p-4\">\n <p className=\"text-sm text-muted-foreground\">Are you sure you want to delete this quote? This will soft-delete the quote and all its line items.</p>\n </div>\n <div className=\"flex justify-end gap-2 px-4 py-3 border-t\">\n <Button type=\"button\" variant=\"outline\" onClick={() => setShowDeleteConfirm(false)}>\n Cancel\n </Button>\n <Button type=\"button\" variant=\"destructive\" onClick={deleteQuote} disabled={deleting}>\n {deleting ? <Spinner /> : null} Delete\n </Button>\n </div>\n </div>\n </div>\n )}\n\n {/* Summary view */}\n {view === 'summary' && (\n <>\n {/* Pricing Summary Card */}\n <div className=\"rounded-lg border bg-card p-4\">\n <h3 className=\"text-sm font-medium mb-3\">Pricing Summary</h3>\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground\">Non-Recurring (NRC)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(summary.nrcTotal, currency)}</p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground\">Monthly Recurring (MRC)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(summary.mrcTotal, currency)}</p>\n </div>\n {summary.usageTotalEstimated != null && (\n <div>\n <p className=\"text-xs text-muted-foreground\">Usage (est.)</p>\n <p className=\"text-lg font-semibold font-mono\">{fmt(summary.usageTotalEstimated, currency)}</p>\n </div>\n )}\n {summary.usageCharges.length > 0 && (\n <div>\n <p className=\"text-xs text-muted-foreground\">Usage Charges</p>\n {summary.usageCharges.map((uc, i) => (\n <p key={i} className=\"text-xs mt-0.5\">{uc.chargeName}: {fmt(uc.unitPrice, currency)}/unit</p>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Validation errors */}\n {!cpqQuote.validationResult.valid && (\n <Alert variant=\"warning\">\n <AlertTitle>Validation Issues</AlertTitle>\n <AlertDescription>\n {/* AlertDescription renders a <p>, so the error list MUST be\n stacked <span>s \u2014 `<ul>`/`<li>` inside `<p>` is invalid\n HTML and Next 16 surfaces it as a hydration error. */}\n <span className=\"text-xs space-y-0.5 block\">\n {cpqQuote.validationResult.errors.map((e, i) => (\n <span key={i} className=\"block\">\u2014 {e.message}</span>\n ))}\n </span>\n </AlertDescription>\n </Alert>\n )}\n\n {/* Quote Lines */}\n <QuoteLineTree\n lines={cpqQuote.lines}\n currency={currency}\n expandedLines={expandedLines}\n pricingDetail={pricingDetail}\n targetCodes={arcTargetCodeMap}\n onToggleLine={toggleLine}\n onEditLine={startEditLine}\n onRemoveLine={removeItem}\n onAddComponent={startAddComponent}\n onTogglePricingDetail={(lineIdx, chargeIdx) =>\n setPricingDetail(\n pricingDetail?.lineIdx === lineIdx && pricingDetail?.chargeIdx === chargeIdx\n ? null\n : { lineIdx, chargeIdx },\n )\n }\n />\n </>\n )}\n\n {/* Add offering \u2014 browse */}\n {view === 'add-offering' && (\n <>\n {addingToParentLineId && (\n <Alert variant=\"info\">\n Adding component to bundle: <span className=\"font-medium\">{cpqQuote.lines.find((l) => l.lineId === addingToParentLineId)?.offeringName ?? 'Bundle'}</span>\n </Alert>\n )}\n <OfferingBrowser\n offerings={offerings}\n loading={offeringsLoading}\n search={offeringSearch}\n onSearchChange={setOfferingSearch}\n onSelect={selectOffering}\n />\n </>\n )}\n\n {/* Configure new offering */}\n {view === 'configure' && selectedOffering && (\n <ConfigurePanel\n title={addingToParentLineId ? `Add Component: ${selectedOffering.name}` : `Configure: ${selectedOffering.name}`}\n attributes={attributes}\n config={config}\n quantity={quantity}\n arcTargetOptions={\n arcTargets.length >= 2 && !addingToParentLineId\n ? arcTargets.map((t) => ({\n subscriptionId: t.subscriptionId,\n code: t.subscription?.code ?? t.subscriptionId.slice(0, 8),\n name: t.subscription?.name ?? null,\n }))\n : null\n }\n arcSelectedTargetIds={addingTargetSubIds}\n onArcTargetToggle={(subId) => {\n setAddingTargetSubIds((prev) =>\n prev.includes(subId) ? prev.filter((id) => id !== subId) : [...prev, subId],\n )\n }}\n onConfigChange={(key, value) => {\n const next = { ...config, [key]: value }\n setConfig(next)\n if (selectedOffering) loadAttributes(selectedOffering.id, next)\n }}\n onQuantityChange={setQuantity}\n onSubmit={addItem}\n submitLabel=\"Add to Quote\"\n submitting={submitting}\n />\n )}\n\n {/* Edit existing line */}\n {view === 'edit' && editingLineId && (\n <ConfigurePanel\n title={`Edit: ${cpqQuote.lines.find((l) => l.lineId === editingLineId)?.offeringName ?? 'Line'}`}\n attributes={attributes}\n config={config}\n quantity={quantity}\n arcTargetOptions={null}\n arcSelectedTargetIds={[]}\n onArcTargetToggle={() => {}}\n onConfigChange={(key, value) => {\n const next = { ...config, [key]: value }\n setConfig(next)\n const line = cpqQuote.lines.find((l) => l.lineId === editingLineId)\n if (line?.offeringId) loadAttributes(line.offeringId, next)\n }}\n onQuantityChange={setQuantity}\n onSubmit={() => updateItem(editingLineId)}\n submitLabel=\"Update Line\"\n submitting={submitting}\n />\n )}\n </div>\n )\n}\n\n// \u2500\u2500\u2500 Sub-components \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nfunction QuoteLineTree({ lines, currency, expandedLines, pricingDetail, targetCodes, onToggleLine, onEditLine, onRemoveLine, onAddComponent, onTogglePricingDetail }: {\n lines: QuoteLine[]; currency: string; expandedLines: Set<string>\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n targetCodes: Map<string, string>\n onToggleLine: (id: string) => void; onEditLine: (line: QuoteLine) => void\n onRemoveLine: (lineId: string) => void; onAddComponent: (parentLineId: string, offeringId?: string) => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const [bundleTrees, setBundleTrees] = React.useState<Map<string, BundleTree>>(new Map())\n const [loadingTrees, setLoadingTrees] = React.useState<Set<string>>(new Set())\n\n const rootLines = lines.filter((l) => !l.parentLineId)\n const childrenByParent = new Map<string, QuoteLine[]>()\n for (const line of lines) {\n if (line.parentLineId) {\n const arr = childrenByParent.get(line.parentLineId) ?? []\n arr.push(line)\n childrenByParent.set(line.parentLineId, arr)\n }\n }\n\n const fetchBundleTree = React.useCallback(async (offeringId: string) => {\n if (bundleTrees.has(offeringId) || loadingTrees.has(offeringId)) return\n setLoadingTrees((prev) => new Set(prev).add(offeringId))\n try {\n const result = await apiJson<{ tree: BundleTree }>(`/api/cpq/bundle-tree?offeringId=${offeringId}`)\n setBundleTrees((prev) => new Map(prev).set(offeringId, result.tree))\n } catch { /* ignore \u2014 will just not show structure */ }\n finally { setLoadingTrees((prev) => { const n = new Set(prev); n.delete(offeringId); return n }) }\n }, [bundleTrees, loadingTrees])\n\n return (\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">Line Items</h3>\n {lines.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">\n No items configured yet. Click &quot;Add Offering&quot; to start.\n </div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {rootLines.map((line) => {\n const lineIdx = lines.indexOf(line)\n const isBundle = line.offeringType === 'bundle'\n const children = childrenByParent.get(line.lineId) ?? []\n const isExpanded = expandedLines.has(line.lineId)\n const bundleTree = isBundle && line.offeringId ? bundleTrees.get(line.offeringId) : undefined\n const treeLoading = isBundle && line.offeringId ? loadingTrees.has(line.offeringId) : false\n\n if (isBundle && isExpanded && line.offeringId && !bundleTree && !treeLoading) {\n fetchBundleTree(line.offeringId)\n }\n\n return (\n <div key={line.lineId}>\n <QuoteLineRow\n line={line} lineIdx={lineIdx} currency={currency}\n isExpanded={isExpanded}\n pricingDetail={pricingDetail} isBundle={isBundle}\n childCount={children.length} indent={0}\n targetCodes={targetCodes}\n onToggle={() => onToggleLine(line.lineId)}\n onEdit={() => onEditLine(line)}\n onRemove={() => onRemoveLine(line.lineId)}\n onAddComponent={isBundle ? () => onAddComponent(line.lineId) : undefined}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n {/* Bundle structure: slots and child lines */}\n {isBundle && isExpanded && (\n <BundleSlotPanel\n bundleTree={bundleTree}\n treeLoading={treeLoading}\n children={children}\n allLines={lines}\n currency={currency}\n expandedLines={expandedLines}\n pricingDetail={pricingDetail}\n parentLineId={line.lineId}\n targetCodes={targetCodes}\n onToggleLine={onToggleLine}\n onEditLine={onEditLine}\n onRemoveLine={onRemoveLine}\n onAddComponent={onAddComponent}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nfunction BundleSlotPanel({ bundleTree, treeLoading, children, allLines, currency, expandedLines, pricingDetail, parentLineId, targetCodes, onToggleLine, onEditLine, onRemoveLine, onAddComponent, onTogglePricingDetail }: {\n bundleTree: BundleTree | undefined; treeLoading: boolean\n children: QuoteLine[]; allLines: QuoteLine[]; currency: string\n expandedLines: Set<string>; pricingDetail: { lineIdx: number; chargeIdx: number } | null\n parentLineId: string\n targetCodes: Map<string, string>\n onToggleLine: (id: string) => void; onEditLine: (line: QuoteLine) => void\n onRemoveLine: (lineId: string) => void; onAddComponent: (parentLineId: string, offeringId?: string) => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n if (treeLoading) {\n return (\n <div className=\"border-t bg-muted/5 px-8 py-3\">\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\"><Spinner /> Loading bundle structure\u2026</div>\n </div>\n )\n }\n\n if (!bundleTree || bundleTree.slots.length === 0) {\n if (children.length === 0) return null\n return (\n <div className=\"border-t bg-muted/5\">\n {children.map((child) => {\n const childIdx = allLines.indexOf(child)\n return (\n <QuoteLineRow\n key={child.lineId}\n line={child} lineIdx={childIdx} currency={currency}\n isExpanded={expandedLines.has(child.lineId)}\n pricingDetail={pricingDetail} isBundle={false}\n childCount={0} indent={1}\n targetCodes={targetCodes}\n onToggle={() => onToggleLine(child.lineId)}\n onEdit={() => onEditLine(child)}\n onRemove={() => onRemoveLine(child.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n )\n })}\n </div>\n )\n }\n\n const childOfferingIds = new Set(children.map((c) => c.offeringId).filter(Boolean))\n\n return (\n <div className=\"border-t bg-muted/5\">\n {bundleTree.slots.map((slot) => {\n const filledChildren = children.filter((c) =>\n slot.components.some((comp) => comp.childOffering.offeringId === c.offeringId),\n )\n const filledCount = filledChildren.length\n const isRequired = slot.cardinalityMin > 0\n const isFull = slot.cardinalityMax != null && filledCount >= slot.cardinalityMax\n const canAdd = !isFull\n\n return (\n <div key={slot.slotId} className=\"border-b last:border-b-0\">\n {/* Slot header */}\n <div className=\"flex items-center gap-2 px-6 py-2 bg-muted/20\">\n <span className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">{slot.name}</span>\n {isRequired ? (\n <Tag variant=\"warning\" className=\"text-[10px] px-1.5\">required</Tag>\n ) : (\n <Tag variant=\"neutral\" className=\"text-[10px] px-1.5\">optional</Tag>\n )}\n <span className=\"text-[10px] text-muted-foreground\">\n {filledCount}/{slot.cardinalityMax ?? '\u221E'}\n {slot.cardinalityMin > 0 && ` (min ${slot.cardinalityMin})`}\n </span>\n <div className=\"flex-1\" />\n {/* Available offerings in this slot */}\n <div className=\"flex items-center gap-1\">\n {slot.components.map((comp) => {\n const isFilled = childOfferingIds.has(comp.childOffering.offeringId)\n return (\n <button\n key={comp.componentId}\n onClick={() => !isFilled && canAdd && onAddComponent(parentLineId, comp.childOffering.offeringId)}\n disabled={isFilled || !canAdd}\n className={`inline-flex items-center gap-1 rounded border px-2 py-1 text-[11px] font-medium transition-colors ${\n isFilled\n ? 'border-status-success-border bg-status-success-bg text-status-success-text cursor-default'\n : canAdd\n ? 'border-border hover:border-primary hover:bg-primary/5 hover:text-primary cursor-pointer'\n : 'border-border text-muted-foreground opacity-50 cursor-not-allowed'\n }`}\n title={isFilled ? 'Already added' : canAdd ? `Add ${comp.childOffering.offeringName}` : 'Slot is full'}\n >\n {isFilled ? (\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\" />\n </svg>\n ) : (\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" />\n </svg>\n )}\n {comp.childOffering.offeringName}\n </button>\n )\n })}\n </div>\n </div>\n {/* Filled child lines for this slot */}\n {filledChildren.map((child) => {\n const childIdx = allLines.indexOf(child)\n return (\n <QuoteLineRow\n key={child.lineId}\n line={child} lineIdx={childIdx} currency={currency}\n isExpanded={expandedLines.has(child.lineId)}\n pricingDetail={pricingDetail} isBundle={false}\n childCount={0} indent={1}\n targetCodes={targetCodes}\n onToggle={() => onToggleLine(child.lineId)}\n onEdit={() => onEditLine(child)}\n onRemove={() => onRemoveLine(child.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n )\n })}\n </div>\n )\n })}\n {/* Show any child lines not matching any slot */}\n {children.filter((c) => !bundleTree.slots.some((s) => s.components.some((comp) => comp.childOffering.offeringId === c.offeringId))).map((child) => {\n const childIdx = allLines.indexOf(child)\n return (\n <QuoteLineRow\n key={child.lineId}\n line={child} lineIdx={childIdx} currency={currency}\n isExpanded={expandedLines.has(child.lineId)}\n pricingDetail={pricingDetail} isBundle={false}\n childCount={0} indent={1}\n targetCodes={targetCodes}\n onToggle={() => onToggleLine(child.lineId)}\n onEdit={() => onEditLine(child)}\n onRemove={() => onRemoveLine(child.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n )\n })}\n </div>\n )\n}\n\nfunction QuoteLineRow({ line, lineIdx, currency, isExpanded, pricingDetail, isBundle, childCount, indent, targetCodes, onToggle, onEdit, onRemove, onAddComponent, onTogglePricingDetail }: {\n line: QuoteLine; lineIdx: number; currency: string; isExpanded: boolean\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n isBundle: boolean; childCount: number; indent: number\n targetCodes: Map<string, string>\n onToggle: () => void; onEdit: () => void; onRemove: () => void\n onAddComponent?: () => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const paddingLeft = indent > 0 ? `${indent * 2 + 1}rem` : undefined\n\n return (\n <div>\n <div className=\"flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors\" style={paddingLeft ? { paddingLeft } : undefined}>\n {/* Expand toggle */}\n <button onClick={onToggle} className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground\">\n <svg className={`h-4 w-4 transition-transform ${isExpanded ? 'rotate-90' : ''}`} fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n\n {/* Line info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {indent > 0 && (\n <span className=\"text-muted-foreground text-xs\">\u2514</span>\n )}\n {isBundle && (\n <Tag variant=\"brand\" className=\"px-1.5 text-xs\">bundle</Tag>\n )}\n <span className=\"font-medium text-sm\">{line.offeringName}</span>\n {line.quantity > 1 && <span className=\"rounded bg-muted px-1.5 py-0.5 text-xs font-medium\">\u00D7{line.quantity}</span>}\n <ActionBadge action={line.action} />\n {targetCodes.size >= 2 && line.targetSubscriptionId && targetCodes.get(line.targetSubscriptionId) && (\n <Tag\n variant=\"brand\"\n className=\"px-1.5 text-xs\"\n title={`Acts on subscription ${targetCodes.get(line.targetSubscriptionId)}`}\n >\n \u2192 {targetCodes.get(line.targetSubscriptionId)}\n </Tag>\n )}\n {line.isConfigured ? (\n <Tag variant=\"success\" className=\"px-1.5 text-xs\">configured</Tag>\n ) : (\n <Tag variant=\"warning\" className=\"px-1.5 text-xs\">incomplete</Tag>\n )}\n {isBundle && (\n <span className=\"text-xs text-muted-foreground\">{childCount} component{childCount !== 1 ? 's' : ''}</span>\n )}\n </div>\n {line.validationErrors && line.validationErrors.length > 0 && (\n <p className=\"text-xs text-destructive mt-0.5\">{line.validationErrors[0].message}</p>\n )}\n </div>\n\n {/* Pricing */}\n <div className=\"shrink-0 text-right text-xs space-y-0.5\">\n {line.nrcTotal > 0 && <div><span className=\"text-muted-foreground\">NRC </span><span className=\"font-mono font-medium\">{fmt(line.nrcTotal, currency)}</span></div>}\n {line.mrcTotal > 0 && <div><span className=\"text-muted-foreground\">MRC </span><span className=\"font-mono font-medium\">{fmt(line.mrcTotal, currency)}</span></div>}\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1 shrink-0\">\n {onAddComponent && (\n <button onClick={onAddComponent} className=\"rounded p-1.5 text-muted-foreground hover:text-primary hover:bg-primary/5 transition-colors\" title=\"Add Component\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"1.5\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" />\n </svg>\n </button>\n )}\n <button onClick={onEdit} className=\"rounded p-1.5 text-muted-foreground hover:text-foreground hover:bg-muted transition-colors\" title=\"Edit\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"1.5\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10\" />\n </svg>\n </button>\n <button onClick={onRemove} className=\"rounded p-1.5 text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors\" title=\"Remove\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"1.5\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0\" />\n </svg>\n </button>\n </div>\n </div>\n\n {/* XD-250 ARC: before/after preview when line mirrors a sub item */}\n {isExpanded && line.arcSource && (\n <ArcLineDiff line={line} currency={currency} />\n )}\n {/* Charge breakdown (non-bundle or any expanded line) */}\n {isExpanded && !isBundle && line.charges.length > 0 && (\n <ChargeBreakdown line={line} lineIdx={lineIdx} currency={currency} pricingDetail={pricingDetail} onTogglePricingDetail={onTogglePricingDetail} />\n )}\n {/* For bundles: show own charges first, then children are rendered by parent */}\n {isExpanded && isBundle && line.charges.length > 0 && (\n <ChargeBreakdown line={line} lineIdx={lineIdx} currency={currency} pricingDetail={pricingDetail} onTogglePricingDetail={onTogglePricingDetail} />\n )}\n {/* Fallback: line has no per-charge breakdown and no ARC diff (truly empty) */}\n {isExpanded && line.charges.length === 0 && !line.arcSource && (\n <LineSummaryFallback line={line} currency={currency} />\n )}\n </div>\n )\n}\n\nfunction ArcLineDiff({ line, currency }: { line: QuoteLine; currency: string }) {\n const src = line.arcSource\n if (!src) return null\n const isCancel = line.action === 'cancel'\n const beforeMrc = src.mrcAmount\n const beforeNrc = src.nrcAmount\n const beforeQty = src.quantity\n const afterMrc = isCancel ? 0 : line.mrcTotal\n const afterNrc = isCancel ? 0 : line.nrcTotal\n const afterQty = isCancel ? 0 : line.quantity\n const fmtVal = (v: number, asCurrency: boolean) =>\n asCurrency ? fmt(v, currency) : String(v)\n const rows: Array<{ label: string; before: number; after: number; asCurrency: boolean }> = [\n { label: 'Quantity', before: beforeQty, after: afterQty, asCurrency: false },\n { label: 'MRC', before: beforeMrc, after: afterMrc, asCurrency: true },\n { label: 'NRC', before: beforeNrc, after: afterNrc, asCurrency: true },\n ]\n\n return (\n <div className=\"border-t bg-muted/10 px-12 py-2 space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground\">Change Preview</p>\n <div className=\"rounded border bg-background overflow-hidden\">\n <table className=\"w-full text-xs\">\n <thead className=\"bg-muted/40\">\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left px-3 py-1.5 font-medium\" />\n <th className=\"text-right px-3 py-1.5 font-medium\">Before</th>\n <th className=\"text-right px-3 py-1.5 font-medium\">After</th>\n <th className=\"text-right px-3 py-1.5 font-medium\">\u0394</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((r) => {\n const delta = r.after - r.before\n const showDelta = delta !== 0\n return (\n <tr key={r.label} className=\"border-t border-dashed border-border/40\">\n <td className=\"px-3 py-1 text-muted-foreground\">{r.label}</td>\n <td className=\"px-3 py-1 text-right font-mono\">{fmtVal(r.before, r.asCurrency)}</td>\n <td className={`px-3 py-1 text-right font-mono ${isCancel ? 'text-muted-foreground line-through' : ''}`}>\n {fmtVal(r.after, r.asCurrency)}\n </td>\n <td className={`px-3 py-1 text-right font-mono font-medium ${showDelta ? (delta > 0 ? 'text-status-success-text' : 'text-destructive') : 'text-muted-foreground'}`}>\n {showDelta ? `${delta > 0 ? '+' : ''}${fmtVal(delta, r.asCurrency)}` : '\u2014'}\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n {isCancel && (\n <p className=\"text-xs text-destructive italic\">Cancellation \u2014 item will be terminated on activation.</p>\n )}\n </div>\n )\n}\n\nfunction ActionBadge({ action }: { action: QuoteLineAction }) {\n const variantByAction: Record<QuoteLineAction, 'info' | 'warning' | 'error'> = {\n add: 'info',\n modify: 'warning',\n cancel: 'error',\n }\n return (\n <Tag variant={variantByAction[action]} className=\"px-1.5 text-xs\">\n {action}\n </Tag>\n )\n}\n\nfunction LineSummaryFallback({ line, currency }: { line: QuoteLine; currency: string }) {\n const hasTotals = line.nrcTotal > 0 || line.mrcTotal > 0\n const mirroredFromItemId = (line.configuration?._arcMirroredFromItemId as string | undefined) ?? null\n return (\n <div className=\"border-t bg-muted/10 px-12 py-2 text-xs text-muted-foreground space-y-1\">\n <div>\n No detailed charge breakdown available for this line.\n {mirroredFromItemId && ' Mirrored from existing subscription item.'}\n </div>\n {hasTotals && (\n <div className=\"flex gap-4\">\n {line.nrcTotal > 0 && (\n <span>NRC <span className=\"font-mono font-medium text-foreground\">{fmt(line.nrcTotal, currency)}</span></span>\n )}\n {line.mrcTotal > 0 && (\n <span>MRC <span className=\"font-mono font-medium text-foreground\">{fmt(line.mrcTotal, currency)}</span></span>\n )}\n </div>\n )}\n </div>\n )\n}\n\nfunction ChargeBreakdown({ line, lineIdx, currency, pricingDetail, onTogglePricingDetail }: {\n line: QuoteLine; lineIdx: number; currency: string\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n return (\n <div className=\"border-t bg-muted/10 px-12 py-2\">\n <table className=\"w-full text-xs\">\n <thead>\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left py-1 font-medium\">Charge</th>\n <th className=\"text-left py-1 font-medium\">Type</th>\n <th className=\"text-right py-1 font-medium\">Unit Price</th>\n <th className=\"text-right py-1 font-medium\">Qty</th>\n <th className=\"text-right py-1 font-medium\">Total</th>\n <th className=\"w-8\" />\n </tr>\n </thead>\n <tbody>\n {line.charges.map((c, i) => {\n const hasDetail = !!(c.breakdown?.tiers?.length || c.adjustments?.length)\n const isDetailOpen = pricingDetail?.lineIdx === lineIdx && pricingDetail?.chargeIdx === i\n return (\n <React.Fragment key={i}>\n <tr className=\"border-t border-dashed border-border/50\">\n <td className=\"py-1\">{c.chargeName}</td>\n <td className=\"py-1 uppercase\">{c.chargeType}</td>\n <td className=\"py-1 text-right font-mono\">{fmt(c.unitPrice, currency)}</td>\n <td className=\"py-1 text-right font-mono\">{c.quantity ?? '\u2014'}</td>\n <td className=\"py-1 text-right font-mono\">{c.totalPrice != null ? fmt(c.totalPrice, currency) : c.note ?? '\u2014'}</td>\n <td className=\"py-1 text-center\">\n {hasDetail && (\n <button\n onClick={() => onTogglePricingDetail(lineIdx, i)}\n className=\"inline-flex items-center justify-center rounded p-0.5 hover:bg-accent text-muted-foreground hover:text-foreground transition-colors\"\n title=\"Show pricing breakdown\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" className=\"w-3.5 h-3.5\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\" />\n </svg>\n </button>\n )}\n </td>\n </tr>\n {isDetailOpen && (\n <tr>\n <td colSpan={6} className=\"pb-3 pt-1\">\n <div className=\"rounded border bg-background p-3 space-y-3 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-semibold text-sm\">Pricing Details \u2014 {c.chargeName}</span>\n <span className=\"text-muted-foreground\">{c.pricingMethod ?? 'flat'}</span>\n </div>\n\n {c.breakdown?.tiers && c.breakdown.tiers.length > 0 && (\n <div>\n <div className=\"font-medium text-muted-foreground mb-1\">Tier Breakdown</div>\n <table className=\"w-full\">\n <thead>\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left py-0.5 font-medium\">Tier</th>\n <th className=\"text-right py-0.5 font-medium\">Range</th>\n <th className=\"text-right py-0.5 font-medium\">Price/Unit</th>\n <th className=\"text-right py-0.5 font-medium\">Qty</th>\n <th className=\"text-right py-0.5 font-medium\">Subtotal</th>\n </tr>\n </thead>\n <tbody>\n {c.breakdown.tiers.map((t) => (\n <tr key={t.tier} className=\"border-t border-border/30\">\n <td className=\"py-0.5\">{t.tier}</td>\n <td className=\"py-0.5 text-right font-mono\">{t.from}\u2013{t.to}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmt(t.pricePerUnit, currency)}</td>\n <td className=\"py-0.5 text-right font-mono\">{t.quantity}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmt(t.subtotal, currency)}</td>\n </tr>\n ))}\n <tr className=\"border-t font-medium\">\n <td colSpan={4} className=\"py-0.5 text-right\">Tiered Total</td>\n <td className=\"py-0.5 text-right font-mono\">\n {fmt(c.breakdown.tiers.reduce((s, t) => s + t.subtotal, 0), currency)}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n )}\n\n {c.adjustments && c.adjustments.length > 0 && (\n <div>\n <div className=\"font-medium text-muted-foreground mb-1\">Applied Price Rules</div>\n <table className=\"w-full\">\n <thead>\n <tr className=\"text-muted-foreground\">\n <th className=\"text-left py-0.5 font-medium\">Rule</th>\n <th className=\"text-left py-0.5 font-medium\">Type</th>\n <th className=\"text-right py-0.5 font-medium\">Value</th>\n <th className=\"text-right py-0.5 font-medium\">Before</th>\n <th className=\"text-right py-0.5 font-medium\">After</th>\n <th className=\"text-right py-0.5 font-medium\">Delta</th>\n </tr>\n </thead>\n <tbody>\n {c.adjustments.map((adj, ai) => (\n <tr key={ai} className=\"border-t border-border/30\">\n <td className=\"py-0.5\">{adj.ruleName}</td>\n <td className=\"py-0.5\">{RULE_TYPE_LABELS[adj.ruleType] ?? adj.ruleType}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmtRuleValue(adj, currency)}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmt(adj.unitPriceBefore, currency)}</td>\n <td className=\"py-0.5 text-right font-mono\">{fmt(adj.unitPriceAfter, currency)}</td>\n <td className={`py-0.5 text-right font-mono ${adj.delta < 0 ? 'text-destructive' : adj.delta > 0 ? 'text-status-success-text' : ''}`}>\n {adj.delta > 0 ? '+' : ''}{fmt(adj.delta, currency)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n <div className=\"flex items-center justify-between pt-1 border-t text-sm font-semibold\">\n <span>Final Total</span>\n <span className=\"font-mono\">{c.totalPrice != null ? fmt(c.totalPrice, currency) : '\u2014'}</span>\n </div>\n </div>\n </td>\n </tr>\n )}\n </React.Fragment>\n )\n })}\n </tbody>\n </table>\n </div>\n )\n}\n\nfunction Spinner() {\n return (\n <svg className=\"h-4 w-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n )\n}\n\nfunction ErrorBanner({ message, onDismiss }: { message: string; onDismiss?: () => void }) {\n return (\n <Alert variant=\"destructive\" className=\"flex items-start gap-2\">\n <span className=\"flex-1\">{message}</span>\n {onDismiss && (\n <button\n onClick={onDismiss}\n className=\"text-destructive/70 hover:text-destructive text-sm font-bold\"\n aria-label=\"Dismiss\"\n >\n \u00D7\n </button>\n )}\n </Alert>\n )\n}\n\nfunction OfferingBrowser({ offerings, loading, search, onSearchChange, onSelect }: {\n offerings: Offering[]; loading: boolean; search: string; onSearchChange: (v: string) => void; onSelect: (o: Offering) => void\n}) {\n const filtered = offerings.filter((o) => {\n if (!search.trim()) return true\n const q = search.toLowerCase()\n return o.name.toLowerCase().includes(q) || o.code.toLowerCase().includes(q) || (o.description ?? '').toLowerCase().includes(q)\n })\n\n return (\n <div className=\"space-y-3\">\n <h3 className=\"text-sm font-medium px-1\">Select Product Offering</h3>\n <div className=\"relative\">\n <svg className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth=\"2\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z\" />\n </svg>\n <input type=\"text\" placeholder=\"Search offerings\u2026\" value={search} onChange={(e) => onSearchChange(e.target.value)}\n className=\"w-full rounded-md border bg-background pl-10 pr-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary/50\" />\n </div>\n {loading ? (\n <div className=\"flex items-center gap-2 py-8 justify-center text-sm text-muted-foreground\"><Spinner /> Loading offerings\u2026</div>\n ) : filtered.length === 0 ? (\n <div className=\"py-8 text-center text-sm text-muted-foreground\">{search ? 'No offerings match your search.' : 'No active offerings available.'}</div>\n ) : (\n <div className=\"grid gap-2 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((offering) => (\n <button key={offering.id} onClick={() => onSelect(offering)}\n className=\"rounded-lg border bg-card p-4 text-left hover:border-primary hover:bg-primary/5 transition-colors group\">\n <p className=\"text-sm font-medium group-hover:text-primary transition-colors\">{offering.name}</p>\n <p className=\"text-xs text-muted-foreground font-mono mt-0.5\">{offering.code}</p>\n {offering.description && <p className=\"text-xs text-muted-foreground mt-1 line-clamp-2\">{offering.description}</p>}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nfunction ConfigurePanel({ title, attributes, config, quantity, arcTargetOptions, arcSelectedTargetIds, onArcTargetToggle, onConfigChange, onQuantityChange, onSubmit, submitLabel, submitting }: {\n title: string; attributes: ConstrainedAttribute[]; config: Record<string, unknown>; quantity: number\n arcTargetOptions: Array<{ subscriptionId: string; code: string; name: string | null }> | null\n arcSelectedTargetIds: string[]\n onArcTargetToggle: (subId: string) => void\n onConfigChange: (key: string, value: unknown) => void; onQuantityChange: (q: number) => void\n onSubmit: () => void; submitLabel: string; submitting: boolean\n}) {\n const noTargetsPicked =\n arcTargetOptions !== null && arcTargetOptions.length > 0 && arcSelectedTargetIds.length === 0\n return (\n <div className=\"rounded-lg border bg-card\">\n <div className=\"border-b px-4 py-3\"><h3 className=\"text-sm font-medium\">{title}</h3></div>\n <div className=\"p-4 space-y-4\">\n {arcTargetOptions && arcTargetOptions.length > 0 && (\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n Apply to subscription(s)\n <span className=\"text-destructive ml-1\">*</span>\n </label>\n <div className=\"space-y-1.5 rounded-md border bg-background px-3 py-2\">\n {arcTargetOptions.map((opt) => {\n const checked = arcSelectedTargetIds.includes(opt.subscriptionId)\n return (\n <label\n key={opt.subscriptionId}\n className=\"flex items-center gap-2 text-sm cursor-pointer hover:bg-muted/40 rounded px-1 py-0.5\"\n >\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => onArcTargetToggle(opt.subscriptionId)}\n className=\"h-4 w-4 rounded border-border\"\n />\n <span className=\"font-mono font-medium\">{opt.code}</span>\n {opt.name && <span className=\"text-muted-foreground\">\u2014 {opt.name}</span>}\n </label>\n )\n })}\n </div>\n <p className=\"text-xs text-muted-foreground mt-1\">\n Pick one or more \u2014 a separate line will be created on each selected subscription.\n </p>\n {noTargetsPicked && (\n <p className=\"text-xs text-destructive mt-1\">Select at least one target.</p>\n )}\n </div>\n )}\n <div>\n <label className=\"block text-sm font-medium mb-1\">Quantity</label>\n <NumberInput\n integer\n min={1}\n value={quantity}\n onChange={(n) => onQuantityChange(Math.max(1, n ?? 1))}\n className=\"w-24\"\n />\n </div>\n {attributes.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">No configurable attributes for this offering.</p>\n ) : (\n attributes.map((attr) => <AttributeField key={attr.code} attribute={attr} value={config[attr.code]} onChange={(v) => onConfigChange(attr.code, v)} />)\n )}\n </div>\n <div className=\"border-t px-4 py-3 flex justify-end\">\n <button onClick={onSubmit} disabled={submitting || noTargetsPicked}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90 transition-colors disabled:opacity-50\">\n {submitting ? <Spinner /> : null} {submitLabel}\n </button>\n </div>\n </div>\n )\n}\n\nfunction AttributeField({ attribute, value, onChange }: { attribute: ConstrainedAttribute; value: unknown; onChange: (v: unknown) => void }) {\n const { code, name, attributeType, isRequired, options, constraints, helpText, defaultValue } = attribute\n const currentValue = value ?? defaultValue ?? ''\n\n return (\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {name}{isRequired && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n {(attributeType === 'select' || attributeType === 'enum') && options && options.length > 0 ? (\n <select value={String(currentValue)} onChange={(e) => onChange(e.target.value)}\n className=\"w-full rounded-md border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary/50\">\n <option value=\"\">\u2014 Select \u2014</option>\n {options.map((opt) => <option key={opt.value} value={opt.value}>{opt.label}</option>)}\n </select>\n ) : attributeType === 'boolean' ? (\n <label className=\"flex items-center gap-2\">\n <input type=\"checkbox\" checked={Boolean(currentValue)} onChange={(e) => onChange(e.target.checked)} className=\"rounded border-border\" />\n <span className=\"text-sm text-muted-foreground\">{helpText ?? 'Enable'}</span>\n </label>\n ) : attributeType === 'number' ? (\n <NumberInput\n value={\n typeof currentValue === 'number'\n ? currentValue\n : currentValue === '' || currentValue == null\n ? null\n : Number(currentValue)\n }\n min={(constraints as Record<string, unknown>)?.min as number | undefined}\n max={(constraints as Record<string, unknown>)?.max as number | undefined}\n onChange={(n) => onChange(n ?? '')}\n />\n ) : (\n <input type=\"text\" value={String(currentValue)} onChange={(e) => onChange(e.target.value)}\n className=\"w-full rounded-md border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary/50\" />\n )}\n {helpText && attributeType !== 'boolean' && <p className=\"text-xs text-muted-foreground mt-1\">{helpText}</p>}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,283 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useRouter } from "next/navigation";
5
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
6
+ import { Button } from "@open-mercato/ui/primitives/button";
7
+ import { Input } from "@open-mercato/ui/primitives/input";
8
+ import { Plus, Search as SearchIcon } from "lucide-react";
9
+ import { Alert } from "@open-mercato/ui/primitives/alert";
10
+ import { RowActions } from "@open-mercato/ui/backend/RowActions";
11
+ import { Tag } from "@open-mercato/ui/primitives/tag";
12
+ import { CpqListView, useCpqListData } from "../../../components/CpqListView.js";
13
+ import {
14
+ formatStatusLabel,
15
+ quoteCpqStatusMap
16
+ } from "../../../components/statusMaps.js";
17
+ const PAGE_SIZE = 50;
18
+ function fmt(amount, currency) {
19
+ if (amount == null || amount === 0) return "\u2014";
20
+ return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);
21
+ }
22
+ function buildFilterParams(values, params) {
23
+ if (typeof values.cpqStatus === "string" && values.cpqStatus) {
24
+ params.set("cpqStatus", values.cpqStatus);
25
+ }
26
+ if (typeof values.currencyCode === "string" && values.currencyCode.trim()) {
27
+ params.set("currencyCode", values.currencyCode.trim().toUpperCase());
28
+ }
29
+ }
30
+ function getCustomerLabel(c) {
31
+ return c.display_name || c.displayName || c.name || c.companyName || "Unnamed";
32
+ }
33
+ function getCustomerEmail(c) {
34
+ return c.primary_email || c.primaryEmail || "";
35
+ }
36
+ function CustomerPickerModal({ open, onClose, onSelect, creating, error }) {
37
+ const [customers, setCustomers] = React.useState([]);
38
+ const [customersLoading, setCustomersLoading] = React.useState(false);
39
+ const [search, setSearch] = React.useState("");
40
+ React.useEffect(() => {
41
+ if (!open) return;
42
+ let cancelled = false;
43
+ setSearch("");
44
+ setCustomersLoading(true);
45
+ fetch("/api/customers/companies?pageSize=100").then((r) => r.ok ? r.json() : { items: [] }).then((data) => {
46
+ if (!cancelled) setCustomers(data.items ?? data ?? []);
47
+ }).catch(() => {
48
+ if (!cancelled) setCustomers([]);
49
+ }).finally(() => {
50
+ if (!cancelled) setCustomersLoading(false);
51
+ });
52
+ return () => {
53
+ cancelled = true;
54
+ };
55
+ }, [open]);
56
+ if (!open) return null;
57
+ const filtered = customers.filter((c) => {
58
+ if (!search.trim()) return true;
59
+ const q = search.toLowerCase();
60
+ return getCustomerLabel(c).toLowerCase().includes(q) || getCustomerEmail(c).toLowerCase().includes(q) || c.id.toLowerCase().includes(q);
61
+ });
62
+ return /* @__PURE__ */ jsx(
63
+ "div",
64
+ {
65
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50",
66
+ onClick: () => !creating && onClose(),
67
+ children: /* @__PURE__ */ jsxs(
68
+ "div",
69
+ {
70
+ className: "w-full max-w-lg rounded-lg border bg-card shadow-xl",
71
+ onClick: (e) => e.stopPropagation(),
72
+ children: [
73
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [
74
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: "Select Customer for New Quote" }),
75
+ /* @__PURE__ */ jsx(
76
+ "button",
77
+ {
78
+ type: "button",
79
+ onClick: onClose,
80
+ disabled: creating,
81
+ className: "text-muted-foreground hover:text-foreground text-lg font-bold leading-none cursor-pointer disabled:cursor-not-allowed",
82
+ children: "\xD7"
83
+ }
84
+ )
85
+ ] }),
86
+ /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-3", children: [
87
+ error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: error }),
88
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
89
+ /* @__PURE__ */ jsx(SearchIcon, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
90
+ /* @__PURE__ */ jsx(
91
+ Input,
92
+ {
93
+ placeholder: "Search customers\u2026",
94
+ value: search,
95
+ onChange: (e) => setSearch(e.target.value),
96
+ autoFocus: true,
97
+ className: "pl-10"
98
+ }
99
+ )
100
+ ] }),
101
+ /* @__PURE__ */ jsx("div", { className: "max-h-72 overflow-y-auto space-y-1", children: customersLoading ? /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-sm text-muted-foreground", children: "Loading customers\u2026" }) : filtered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-sm text-muted-foreground", children: search ? "No customers match your search." : "No customers found." }) : filtered.map((c) => /* @__PURE__ */ jsxs(
102
+ "button",
103
+ {
104
+ type: "button",
105
+ onClick: () => onSelect(c),
106
+ disabled: creating,
107
+ className: "w-full rounded-md border px-3 py-2.5 text-left hover:border-primary hover:bg-primary/5 transition-colors disabled:opacity-50 cursor-pointer disabled:cursor-not-allowed",
108
+ children: [
109
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: getCustomerLabel(c) }),
110
+ getCustomerEmail(c) && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: getCustomerEmail(c) }),
111
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground font-mono mt-0.5", children: c.id })
112
+ ]
113
+ },
114
+ c.id
115
+ )) })
116
+ ] })
117
+ ]
118
+ }
119
+ )
120
+ }
121
+ );
122
+ }
123
+ function CpqQuotesListPage() {
124
+ const router = useRouter();
125
+ const t = useT();
126
+ const data = useCpqListData({
127
+ endpoint: "/api/cpq/quotes",
128
+ pageSize: PAGE_SIZE,
129
+ buildFilterParams,
130
+ loadErrorMessage: t("cpq.quotes.list.error.load", "Failed to load quotes")
131
+ });
132
+ const [showCustomerPicker, setShowCustomerPicker] = React.useState(false);
133
+ const [creating, setCreating] = React.useState(false);
134
+ const [createError, setCreateError] = React.useState(null);
135
+ const statusOptions = React.useMemo(
136
+ () => [
137
+ { value: "new", label: "New" },
138
+ { value: "incomplete", label: "Incomplete" },
139
+ { value: "ready", label: "Ready" },
140
+ { value: "in_approval", label: "In Approval" },
141
+ { value: "approved", label: "Approved" },
142
+ { value: "with_customer", label: "With Customer" },
143
+ { value: "accepted", label: "Accepted" },
144
+ { value: "rejected", label: "Rejected" },
145
+ { value: "cancelled", label: "Cancelled" }
146
+ ],
147
+ []
148
+ );
149
+ const filters = React.useMemo(
150
+ () => [
151
+ {
152
+ id: "cpqStatus",
153
+ label: t("cpq.quotes.filters.status", "Status"),
154
+ type: "select",
155
+ options: statusOptions
156
+ },
157
+ {
158
+ id: "currencyCode",
159
+ label: t("cpq.quotes.filters.currency", "Currency"),
160
+ type: "text"
161
+ }
162
+ ],
163
+ [statusOptions, t]
164
+ );
165
+ const selectCustomer = React.useCallback(
166
+ async (customer) => {
167
+ setCreating(true);
168
+ setCreateError(null);
169
+ try {
170
+ const res = await fetch("/api/cpq/quotes", {
171
+ method: "POST",
172
+ headers: { "Content-Type": "application/json" },
173
+ body: JSON.stringify({ customerId: customer.id })
174
+ });
175
+ const body = await res.json();
176
+ if (res.ok) {
177
+ setShowCustomerPicker(false);
178
+ router.push(`/backend/cpq/quotes/${body.id}`);
179
+ } else {
180
+ setCreateError(body.error ?? `Failed to create quote (${res.status})`);
181
+ }
182
+ } catch (err) {
183
+ setCreateError(err.message);
184
+ } finally {
185
+ setCreating(false);
186
+ }
187
+ },
188
+ [router]
189
+ );
190
+ const columns = React.useMemo(
191
+ () => [
192
+ {
193
+ accessorKey: "quoteNumber",
194
+ header: t("cpq.quotes.table.quoteNumber", "Quote Number"),
195
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-medium", children: row.original.quoteNumber ?? /* @__PURE__ */ jsxs("span", { className: "font-mono text-xs text-muted-foreground", children: [
196
+ (row.original.quoteId ?? row.original.id).slice(0, 8),
197
+ "\u2026"
198
+ ] }) })
199
+ },
200
+ {
201
+ accessorKey: "cpqStatus",
202
+ header: t("cpq.quotes.table.status", "Status"),
203
+ cell: ({ row }) => /* @__PURE__ */ jsx(Tag, { variant: quoteCpqStatusMap[row.original.cpqStatus] ?? "neutral", dot: true, children: formatStatusLabel(row.original.cpqStatus) })
204
+ },
205
+ {
206
+ accessorKey: "version",
207
+ header: t("cpq.quotes.table.version", "Version"),
208
+ cell: ({ row }) => /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
209
+ "v",
210
+ row.original.version
211
+ ] })
212
+ },
213
+ {
214
+ accessorKey: "currencyCode",
215
+ header: t("cpq.quotes.table.currency", "Currency"),
216
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: row.original.currencyCode })
217
+ },
218
+ {
219
+ id: "nrcTotal",
220
+ header: t("cpq.quotes.table.nrcTotal", "NRC Total"),
221
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: fmt(row.original.pricingSummary?.nrcTotal, row.original.currencyCode) })
222
+ },
223
+ {
224
+ id: "mrcTotal",
225
+ header: t("cpq.quotes.table.mrcTotal", "MRC Total"),
226
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: fmt(row.original.pricingSummary?.mrcTotal, row.original.currencyCode) })
227
+ },
228
+ {
229
+ accessorKey: "createdAt",
230
+ header: t("cpq.quotes.table.createdAt", "Created"),
231
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: new Date(row.original.createdAt).toLocaleDateString() })
232
+ }
233
+ ],
234
+ [t]
235
+ );
236
+ return /* @__PURE__ */ jsx(
237
+ CpqListView,
238
+ {
239
+ title: t("cpq.quotes.list.title", "CPQ Quotes"),
240
+ tableId: "cpq.quotes.list",
241
+ data,
242
+ columns,
243
+ filters,
244
+ pageSize: PAGE_SIZE,
245
+ searchPlaceholder: t("cpq.quotes.search.placeholder", "Search by quote / customer id..."),
246
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", onClick: () => setShowCustomerPicker(true), className: "gap-1.5", children: [
247
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
248
+ t("cpq.quotes.add", "New Quote")
249
+ ] }),
250
+ onRowClick: (row) => router.push(`/backend/cpq/quotes/${row.id}`),
251
+ rowActions: (row) => /* @__PURE__ */ jsx(
252
+ RowActions,
253
+ {
254
+ items: [
255
+ {
256
+ id: "open",
257
+ label: t("cpq.quotes.actions.open", "Open"),
258
+ href: `/backend/cpq/quotes/${row.id}`
259
+ }
260
+ ]
261
+ }
262
+ ),
263
+ toolbarContent: /* @__PURE__ */ jsx(
264
+ CustomerPickerModal,
265
+ {
266
+ open: showCustomerPicker,
267
+ onClose: () => setShowCustomerPicker(false),
268
+ onSelect: selectCustomer,
269
+ creating,
270
+ error: createError
271
+ }
272
+ ),
273
+ emptyState: /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground", children: t(
274
+ "cpq.quotes.empty",
275
+ "No CPQ quotes found. Create one to start configuring offerings for a customer."
276
+ ) })
277
+ }
278
+ );
279
+ }
280
+ export {
281
+ CpqQuotesListPage as default
282
+ };
283
+ //# sourceMappingURL=page.js.map