@dainamite/cpq 0.6.0 → 0.7.0

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 (164) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js +3 -9
  3. package/dist/modules/cpq/backend/cpq/inventory/AssetsTable.js.map +2 -2
  4. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js +21 -25
  5. package/dist/modules/cpq/backend/cpq/inventory/SubscriptionsTable.js.map +2 -2
  6. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js +48 -47
  7. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.js.map +2 -2
  8. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js +1 -1
  9. package/dist/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.js.map +2 -2
  10. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js +2 -2
  11. package/dist/modules/cpq/backend/cpq/inventory/page.meta.js.map +2 -2
  12. package/dist/modules/cpq/backend/cpq/inventory/shared.js +37 -2
  13. package/dist/modules/cpq/backend/cpq/inventory/shared.js.map +2 -2
  14. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js +154 -178
  15. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.js.map +2 -2
  16. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js +1 -1
  17. package/dist/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.js.map +2 -2
  18. package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js +168 -143
  19. package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js.map +2 -2
  20. package/dist/modules/cpq/backend/cpq/offerings/page.js +36 -34
  21. package/dist/modules/cpq/backend/cpq/offerings/page.js.map +2 -2
  22. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js +69 -66
  23. package/dist/modules/cpq/backend/cpq/orders/[id]/page.js.map +2 -2
  24. package/dist/modules/cpq/backend/cpq/orders/page.js +6 -6
  25. package/dist/modules/cpq/backend/cpq/orders/page.js.map +2 -2
  26. package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js +41 -36
  27. package/dist/modules/cpq/backend/cpq/price-rules/PriceRuleForm.js.map +2 -2
  28. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js +76 -72
  29. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.js.map +2 -2
  30. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js +1 -1
  31. package/dist/modules/cpq/backend/cpq/price-rules/[id]/page.meta.js.map +2 -2
  32. package/dist/modules/cpq/backend/cpq/price-rules/page.js +18 -15
  33. package/dist/modules/cpq/backend/cpq/price-rules/page.js.map +2 -2
  34. package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js +23 -21
  35. package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js.map +2 -2
  36. package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js +22 -50
  37. package/dist/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.js.map +2 -2
  38. package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js +74 -52
  39. package/dist/modules/cpq/backend/cpq/pricing/[id]/page.js.map +2 -2
  40. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js +20 -17
  41. package/dist/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.js.map +2 -2
  42. package/dist/modules/cpq/backend/cpq/pricing/page.js +1 -1
  43. package/dist/modules/cpq/backend/cpq/pricing/page.js.map +2 -2
  44. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js +115 -123
  45. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.js.map +2 -2
  46. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js +6 -3
  47. package/dist/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.js.map +2 -2
  48. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js +129 -94
  49. package/dist/modules/cpq/backend/cpq/quotes/[id]/page.js.map +2 -2
  50. package/dist/modules/cpq/backend/cpq/quotes/page.js +23 -19
  51. package/dist/modules/cpq/backend/cpq/quotes/page.js.map +2 -2
  52. package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js +19 -15
  53. package/dist/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.js.map +2 -2
  54. package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js +171 -178
  55. package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js.map +2 -2
  56. package/dist/modules/cpq/backend/cpq/specifications/page.js +2 -2
  57. package/dist/modules/cpq/backend/cpq/specifications/page.js.map +2 -2
  58. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js +60 -50
  59. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.js.map +2 -2
  60. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js +22 -18
  61. package/dist/modules/cpq/backend/cpq/wizards/[definitionCode]/page.js.map +2 -2
  62. package/dist/modules/cpq/backend/cpq/wizards/page.js +1 -1
  63. package/dist/modules/cpq/backend/cpq/wizards/page.js.map +2 -2
  64. package/dist/modules/cpq/components/ArcLineDiff.js +2 -2
  65. package/dist/modules/cpq/components/ArcLineDiff.js.map +2 -2
  66. package/dist/modules/cpq/components/ChargeBreakdownTable.js +4 -10
  67. package/dist/modules/cpq/components/ChargeBreakdownTable.js.map +2 -2
  68. package/dist/modules/cpq/components/PriceWaterfall.js +3 -1
  69. package/dist/modules/cpq/components/PriceWaterfall.js.map +2 -2
  70. package/dist/modules/cpq/components/PricingSummaryCard.js +1 -6
  71. package/dist/modules/cpq/components/PricingSummaryCard.js.map +2 -2
  72. package/dist/modules/cpq/components/StatusPath.js +5 -3
  73. package/dist/modules/cpq/components/StatusPath.js.map +2 -2
  74. package/dist/modules/cpq/components/useCpqRowActions.js +10 -22
  75. package/dist/modules/cpq/components/useCpqRowActions.js.map +2 -2
  76. package/dist/modules/cpq/i18n/de.json +1220 -0
  77. package/dist/modules/cpq/i18n/en.json +1220 -0
  78. package/dist/modules/cpq/i18n/es.json +1220 -0
  79. package/dist/modules/cpq/i18n/pl.json +1220 -0
  80. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js +39 -31
  81. package/dist/modules/cpq/widgets/injection/customer-inventory/widget.client.js.map +2 -2
  82. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js +13 -5
  83. package/dist/modules/cpq/widgets/injection/order-cpq-tab/widget.client.js.map +2 -2
  84. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js +41 -21
  85. package/dist/modules/cpq/widgets/injection/quote-configurator/widget.client.js.map +2 -2
  86. package/dist/modules/cpq/widgets/injection-table.js +2 -2
  87. package/dist/modules/cpq/widgets/injection-table.js.map +2 -2
  88. package/dist/modules/cpq/workflows/WizardRunner.js +10 -8
  89. package/dist/modules/cpq/workflows/WizardRunner.js.map +2 -2
  90. package/dist/modules/cpq/workflows/WizardTrigger.js +15 -9
  91. package/dist/modules/cpq/workflows/WizardTrigger.js.map +2 -2
  92. package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js +9 -7
  93. package/dist/modules/cpq/workflows/steps/CustomerSelectStep.js.map +2 -2
  94. package/dist/modules/cpq/workflows/steps/InventorySelectStep.js +9 -4
  95. package/dist/modules/cpq/workflows/steps/InventorySelectStep.js.map +2 -2
  96. package/dist/modules/cpq/workflows/steps/ItemListStep.js +16 -19
  97. package/dist/modules/cpq/workflows/steps/ItemListStep.js.map +2 -2
  98. package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js +19 -32
  99. package/dist/modules/cpq/workflows/steps/OfferingSelectStep.js.map +2 -2
  100. package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js +8 -6
  101. package/dist/modules/cpq/workflows/steps/ProductConfigureStep.js.map +2 -2
  102. package/dist/modules/cpq/workflows/steps/ReviewStep.js +32 -30
  103. package/dist/modules/cpq/workflows/steps/ReviewStep.js.map +2 -2
  104. package/dist/modules/cpq/workflows/steps/index.js +12 -0
  105. package/dist/modules/cpq/workflows/steps/index.js.map +2 -2
  106. package/package.json +1 -1
  107. package/src/modules/cpq/__tests__/i18n/dictionaries.test.ts +62 -0
  108. package/src/modules/cpq/__tests__/i18n/hardcodedStrings.test.ts +35 -0
  109. package/src/modules/cpq/__tests__/i18n/sourceScan.ts +109 -0
  110. package/src/modules/cpq/backend/cpq/inventory/AssetsTable.tsx +3 -9
  111. package/src/modules/cpq/backend/cpq/inventory/SubscriptionsTable.tsx +22 -26
  112. package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.meta.ts +1 -1
  113. package/src/modules/cpq/backend/cpq/inventory/assets/[id]/page.tsx +43 -46
  114. package/src/modules/cpq/backend/cpq/inventory/page.meta.ts +2 -2
  115. package/src/modules/cpq/backend/cpq/inventory/shared.tsx +37 -1
  116. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.meta.ts +1 -1
  117. package/src/modules/cpq/backend/cpq/inventory/subscriptions/[id]/page.tsx +134 -112
  118. package/src/modules/cpq/backend/cpq/offerings/[id]/page.tsx +169 -130
  119. package/src/modules/cpq/backend/cpq/offerings/page.tsx +34 -24
  120. package/src/modules/cpq/backend/cpq/orders/[id]/page.tsx +66 -43
  121. package/src/modules/cpq/backend/cpq/orders/page.tsx +6 -6
  122. package/src/modules/cpq/backend/cpq/price-rules/PriceRuleForm.tsx +48 -34
  123. package/src/modules/cpq/backend/cpq/price-rules/[id]/page.meta.ts +1 -1
  124. package/src/modules/cpq/backend/cpq/price-rules/[id]/page.tsx +76 -70
  125. package/src/modules/cpq/backend/cpq/price-rules/page.tsx +25 -16
  126. package/src/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.tsx +24 -18
  127. package/src/modules/cpq/backend/cpq/pricing/[id]/ImportPreview.tsx +29 -19
  128. package/src/modules/cpq/backend/cpq/pricing/[id]/page.tsx +95 -47
  129. package/src/modules/cpq/backend/cpq/pricing/[id]/xlsxImport.ts +23 -15
  130. package/src/modules/cpq/backend/cpq/pricing/page.tsx +1 -1
  131. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/ArcQuoteConfigurator.tsx +111 -88
  132. package/src/modules/cpq/backend/cpq/quotes/[id]/_components/PriceAdjustmentDialog.tsx +3 -3
  133. package/src/modules/cpq/backend/cpq/quotes/[id]/page.tsx +134 -89
  134. package/src/modules/cpq/backend/cpq/quotes/page.tsx +29 -21
  135. package/src/modules/cpq/backend/cpq/specifications/[id]/DependsOnRulesEditor.tsx +19 -15
  136. package/src/modules/cpq/backend/cpq/specifications/[id]/page.tsx +171 -171
  137. package/src/modules/cpq/backend/cpq/specifications/page.tsx +2 -2
  138. package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/detail/page.tsx +51 -41
  139. package/src/modules/cpq/backend/cpq/wizards/[definitionCode]/page.tsx +17 -13
  140. package/src/modules/cpq/backend/cpq/wizards/page.tsx +1 -1
  141. package/src/modules/cpq/components/ArcLineDiff.tsx +2 -2
  142. package/src/modules/cpq/components/ChargeBreakdownTable.tsx +4 -2
  143. package/src/modules/cpq/components/PriceWaterfall.tsx +4 -2
  144. package/src/modules/cpq/components/PricingSummaryCard.tsx +1 -1
  145. package/src/modules/cpq/components/StatusPath.tsx +7 -4
  146. package/src/modules/cpq/components/useCpqRowActions.tsx +17 -25
  147. package/src/modules/cpq/i18n/de.json +1220 -0
  148. package/src/modules/cpq/i18n/en.json +1220 -0
  149. package/src/modules/cpq/i18n/es.json +1220 -0
  150. package/src/modules/cpq/i18n/pl.json +1220 -0
  151. package/src/modules/cpq/widgets/injection/customer-inventory/widget.client.tsx +38 -31
  152. package/src/modules/cpq/widgets/injection/order-cpq-tab/widget.client.tsx +7 -5
  153. package/src/modules/cpq/widgets/injection/quote-configurator/widget.client.tsx +36 -21
  154. package/src/modules/cpq/widgets/injection-table.ts +8 -2
  155. package/src/modules/cpq/workflows/WizardRunner.tsx +8 -5
  156. package/src/modules/cpq/workflows/WizardTrigger.tsx +15 -9
  157. package/src/modules/cpq/workflows/steps/CustomerSelectStep.tsx +11 -7
  158. package/src/modules/cpq/workflows/steps/InventorySelectStep.tsx +9 -5
  159. package/src/modules/cpq/workflows/steps/ItemListStep.tsx +18 -12
  160. package/src/modules/cpq/workflows/steps/OfferingSelectStep.tsx +20 -16
  161. package/src/modules/cpq/workflows/steps/ProductConfigureStep.tsx +8 -6
  162. package/src/modules/cpq/workflows/steps/ReviewStep.tsx +33 -18
  163. package/src/modules/cpq/workflows/steps/index.ts +12 -0
  164. package/src/modules/cpq/workflows/types.ts +4 -0
@@ -26,17 +26,30 @@ const ARC_BADGE_VARIANTS = {
26
26
  renew: "success",
27
27
  cancel: "error"
28
28
  };
29
+ function quoteTypeLabel(t, quoteType) {
30
+ switch (quoteType) {
31
+ case "amend":
32
+ return t("cpq.quotes.type.amend", "amend");
33
+ case "renew":
34
+ return t("cpq.quotes.type.renew", "renew");
35
+ case "cancel":
36
+ return t("cpq.quotes.type.cancel", "cancel");
37
+ default:
38
+ return quoteType;
39
+ }
40
+ }
29
41
  function fmt(amount, currency) {
30
42
  return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);
31
43
  }
32
- async function apiJson(url, init) {
44
+ async function apiJson(t, url, init) {
33
45
  const res = await fetch(url, init);
34
46
  const json = await res.json();
35
- if (!res.ok) throw new Error(json?.error ?? `Request failed (${res.status})`);
47
+ if (!res.ok) throw new Error(json?.error ?? t("cpq.common.requestFailed", "Request failed ({status})", { status: res.status }));
36
48
  return json;
37
49
  }
38
50
  function CpqOrderDetailPage(props) {
39
51
  const router = useRouter();
52
+ const t = useT();
40
53
  const urlParams = useParams();
41
54
  const cpqOrderId = props.params?.id ?? urlParams?.id;
42
55
  const [order, setOrder] = React.useState(null);
@@ -56,7 +69,7 @@ function CpqOrderDetailPage(props) {
56
69
  const targets = d?.items ?? [];
57
70
  const fetched = await Promise.all(
58
71
  targets.map(
59
- (t) => fetch(`/api/cpq/inventory/subscriptions?id=${t.subscriptionId}`).then((r) => r.ok ? r.json() : null).catch(() => null)
72
+ (target) => fetch(`/api/cpq/inventory/subscriptions?id=${target.subscriptionId}`).then((r) => r.ok ? r.json() : null).catch(() => null)
60
73
  )
61
74
  );
62
75
  return fetched.filter(Boolean);
@@ -77,7 +90,7 @@ function CpqOrderDetailPage(props) {
77
90
  let cancelled = false;
78
91
  async function load() {
79
92
  try {
80
- const result = await apiJson(`/api/cpq/orders/${cpqOrderId}`);
93
+ const result = await apiJson(t, `/api/cpq/orders/${cpqOrderId}`);
81
94
  if (!cancelled) {
82
95
  setOrder(result);
83
96
  fetch(`/api/customers/companies?id=${result.customerId}&pageSize=1`).then((r) => r.json()).then((data) => {
@@ -100,13 +113,13 @@ function CpqOrderDetailPage(props) {
100
113
  return () => {
101
114
  cancelled = true;
102
115
  };
103
- }, [cpqOrderId, fetchLinkedSubscriptions]);
116
+ }, [cpqOrderId, fetchLinkedSubscriptions, t]);
104
117
  const activateOrder = async () => {
105
118
  if (!order) return;
106
119
  try {
107
120
  setActivating(true);
108
121
  setError(null);
109
- const result = await apiJson(`/api/cpq/orders/${order.id}/activate`, {
122
+ const result = await apiJson(t, `/api/cpq/orders/${order.id}/activate`, {
110
123
  method: "POST",
111
124
  headers: { "Content-Type": "application/json" },
112
125
  body: JSON.stringify({})
@@ -123,7 +136,7 @@ function CpqOrderDetailPage(props) {
123
136
  if (!order) return;
124
137
  try {
125
138
  setError(null);
126
- const result = await apiJson(`/api/cpq/orders/${order.id}/status`, {
139
+ const result = await apiJson(t, `/api/cpq/orders/${order.id}/status`, {
127
140
  method: "POST",
128
141
  headers: { "Content-Type": "application/json" },
129
142
  body: JSON.stringify({ targetStatus: "cancelled" })
@@ -143,14 +156,15 @@ function CpqOrderDetailPage(props) {
143
156
  if (loading) {
144
157
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-12 justify-center text-sm text-muted-foreground", children: [
145
158
  /* @__PURE__ */ jsx(Spinner, {}),
146
- " Loading\u2026"
159
+ " ",
160
+ t("cpq.orders.detail.loading", "Loading\u2026")
147
161
  ] });
148
162
  }
149
163
  if (!order) {
150
164
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
151
- /* @__PURE__ */ jsx("button", { onClick: () => router.push("/backend/cpq/orders"), className: "text-sm text-muted-foreground hover:text-foreground", children: "\u2190 Back to Orders" }),
165
+ /* @__PURE__ */ jsx("button", { onClick: () => router.push("/backend/cpq/orders"), className: "text-sm text-muted-foreground hover:text-foreground", children: t("cpq.orders.detail.backToOrders", "\u2190 Back to Orders") }),
152
166
  error && /* @__PURE__ */ jsx(ErrorBanner, { message: error }),
153
- /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground", children: "Order not found." })
167
+ /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground", children: t("cpq.orders.detail.notFound", "Order not found.") })
154
168
  ] });
155
169
  }
156
170
  const canActivate = order.cpqStatus === "draft" || order.cpqStatus === "pending_activation";
@@ -167,12 +181,12 @@ function CpqOrderDetailPage(props) {
167
181
  {
168
182
  mode: "detail",
169
183
  backHref: "/backend/cpq/orders",
170
- backLabel: "Back to CPQ Orders",
171
- entityTypeLabel: "CPQ Order",
184
+ backLabel: t("cpq.orders.detail.backLabel", "Back to CPQ Orders"),
185
+ entityTypeLabel: t("cpq.orders.detail.entityType", "CPQ Order"),
172
186
  title: order.orderNumber || order.orderId.slice(0, 8),
173
187
  statusBadge: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 pt-1", children: [
174
188
  /* @__PURE__ */ jsx(Tag, { variant: orderCpqStatusMap[order.cpqStatus] ?? "neutral", dot: true, children: formatStatusLabel(order.cpqStatus) }),
175
- order.quoteType && order.quoteType !== "new" && /* @__PURE__ */ jsx(Tag, { variant: ARC_BADGE_VARIANTS[order.quoteType] ?? "neutral", className: "uppercase", children: order.quoteType })
189
+ order.quoteType && order.quoteType !== "new" && /* @__PURE__ */ jsx(Tag, { variant: ARC_BADGE_VARIANTS[order.quoteType] ?? "neutral", className: "uppercase", children: quoteTypeLabel(t, order.quoteType) })
176
190
  ] }),
177
191
  actionsContent: /* @__PURE__ */ jsxs(Fragment, { children: [
178
192
  /* @__PURE__ */ jsxs(
@@ -183,7 +197,7 @@ function CpqOrderDetailPage(props) {
183
197
  onClick: () => router.push(`/backend/sales/orders/${order.orderId}`),
184
198
  children: [
185
199
  /* @__PURE__ */ jsx(ExternalLink, { className: "h-3.5 w-3.5" }),
186
- "View Sales Order"
200
+ t("cpq.orders.detail.viewSalesOrder", "View Sales Order")
187
201
  ]
188
202
  }
189
203
  ),
@@ -193,16 +207,16 @@ function CpqOrderDetailPage(props) {
193
207
  type: "button",
194
208
  variant: "outline",
195
209
  onClick: () => router.push(`/backend/cpq/quotes/${order.sourceQuoteId}`),
196
- children: "Source Quote"
210
+ children: t("cpq.orders.detail.sourceQuote", "Source Quote")
197
211
  }
198
212
  ),
199
213
  canActivate && /* @__PURE__ */ jsxs(Button, { type: "button", onClick: activateOrder, disabled: activating, children: [
200
214
  activating ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(Play, { className: "h-4 w-4" }),
201
- "Activate"
215
+ t("cpq.orders.detail.activate", "Activate")
202
216
  ] }),
203
217
  canCancel && /* @__PURE__ */ jsxs(Button, { type: "button", variant: "destructive-outline", onClick: cancelOrder, children: [
204
218
  /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
205
- "Cancel"
219
+ t("cpq.common.cancel", "Cancel")
206
220
  ] })
207
221
  ] })
208
222
  }
@@ -214,7 +228,7 @@ function CpqOrderDetailPage(props) {
214
228
  path: ["draft", "pending_activation", "active", "fulfilled"],
215
229
  terminals: ["cancelled"],
216
230
  statusMap: orderCpqStatusMap,
217
- ariaLabel: "Order status path"
231
+ ariaLabel: t("cpq.orders.detail.statusPath", "Order status path")
218
232
  }
219
233
  ) }),
220
234
  error && /* @__PURE__ */ jsx(ErrorBanner, { message: error, onDismiss: () => setError(null) }),
@@ -225,7 +239,7 @@ function CpqOrderDetailPage(props) {
225
239
  children: [
226
240
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 space-y-1", children: [
227
241
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
228
- /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Linked Subscription" }),
242
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: t("cpq.orders.detail.linkedSubscription", "Linked Subscription") }),
229
243
  /* @__PURE__ */ jsx(
230
244
  Tag,
231
245
  {
@@ -245,10 +259,7 @@ function CpqOrderDetailPage(props) {
245
259
  ")"
246
260
  ] })
247
261
  ] }),
248
- order.activatedAt && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
249
- "Activated on ",
250
- new Date(order.activatedAt).toLocaleString()
251
- ] })
262
+ order.activatedAt && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: t("cpq.orders.detail.activatedOn", "Activated on {date}", { date: new Date(order.activatedAt).toLocaleString() }) })
252
263
  ] }),
253
264
  /* @__PURE__ */ jsxs(
254
265
  Button,
@@ -258,7 +269,7 @@ function CpqOrderDetailPage(props) {
258
269
  onClick: () => router.push(`/backend/cpq/inventory/subscriptions/${sub.id}`),
259
270
  children: [
260
271
  /* @__PURE__ */ jsx(ArrowRight, { className: "h-3.5 w-3.5" }),
261
- "Open"
272
+ t("cpq.orders.actions.open", "Open")
262
273
  ]
263
274
  }
264
275
  )
@@ -267,12 +278,12 @@ function CpqOrderDetailPage(props) {
267
278
  sub.id
268
279
  )) }),
269
280
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3", children: [
270
- /* @__PURE__ */ jsx(MetaCard, { label: "Customer", children: customerName ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: customerName }) : /* @__PURE__ */ jsxs("span", { className: "font-mono text-xs text-muted-foreground", children: [
281
+ /* @__PURE__ */ jsx(MetaCard, { label: t("cpq.orders.detail.meta.customer", "Customer"), children: customerName ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: customerName }) : /* @__PURE__ */ jsxs("span", { className: "font-mono text-xs text-muted-foreground", children: [
271
282
  order.customerId.slice(0, 8),
272
283
  "\u2026"
273
284
  ] }) }),
274
- /* @__PURE__ */ jsx(MetaCard, { label: "Created", children: /* @__PURE__ */ jsx("span", { className: "font-medium", children: new Date(order.createdAt).toLocaleDateString() }) }),
275
- /* @__PURE__ */ jsx(MetaCard, { label: "Currency", children: /* @__PURE__ */ jsx("span", { className: "font-medium", children: currency }) })
285
+ /* @__PURE__ */ jsx(MetaCard, { label: t("cpq.orders.detail.meta.created", "Created"), children: /* @__PURE__ */ jsx("span", { className: "font-medium", children: new Date(order.createdAt).toLocaleDateString() }) }),
286
+ /* @__PURE__ */ jsx(MetaCard, { label: t("cpq.orders.detail.meta.currency", "Currency"), children: /* @__PURE__ */ jsx("span", { className: "font-medium", children: currency }) })
276
287
  ] }),
277
288
  /* @__PURE__ */ jsx(
278
289
  PricingSummaryCard,
@@ -311,6 +322,7 @@ function OrderLineTree({
311
322
  onToggleLine,
312
323
  onTogglePricingDetail
313
324
  }) {
325
+ const t = useT();
314
326
  const rootLines = lines.filter((l) => !l.parentLineId);
315
327
  const childrenByParent = /* @__PURE__ */ new Map();
316
328
  for (const line of lines) {
@@ -323,12 +335,8 @@ function OrderLineTree({
323
335
  const indexOf = /* @__PURE__ */ new Map();
324
336
  lines.forEach((l, i) => indexOf.set(l.lineId, i));
325
337
  return /* @__PURE__ */ jsxs("div", { children: [
326
- /* @__PURE__ */ jsxs("h3", { className: "text-sm font-medium mb-2 px-1", children: [
327
- "Line Items (",
328
- lines.length,
329
- ")"
330
- ] }),
331
- lines.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground", children: "No line items." }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card divide-y", children: rootLines.map((line) => {
338
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium mb-2 px-1", children: t("cpq.orders.detail.lineItems", "Line Items ({count})", { count: lines.length }) }),
339
+ lines.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground", children: t("cpq.orders.detail.noLineItems", "No line items.") }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card divide-y", children: rootLines.map((line) => {
332
340
  const isBundle = line.offeringType === "bundle";
333
341
  const children = childrenByParent.get(line.lineId) ?? [];
334
342
  const isExpanded = expandedLines.has(line.lineId);
@@ -351,11 +359,7 @@ function OrderLineTree({
351
359
  }
352
360
  ),
353
361
  isBundle && isExpanded && children.length > 0 && /* @__PURE__ */ jsxs("div", { className: "border-t border-dashed border-brand-violet/30 bg-brand-violet/5", children: [
354
- /* @__PURE__ */ jsx("div", { className: "px-6 py-1.5", children: /* @__PURE__ */ jsxs("span", { className: "text-[10px] font-medium text-brand-violet uppercase tracking-wider", children: [
355
- "Bundle Components (",
356
- children.length,
357
- ")"
358
- ] }) }),
362
+ /* @__PURE__ */ jsx("div", { className: "px-6 py-1.5", children: /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-brand-violet uppercase tracking-wider", children: t("cpq.lines.bundleComponents", "Bundle Components ({count})", { count: children.length }) }) }),
359
363
  children.map((child) => {
360
364
  const childIdx = indexOf.get(child.lineId) ?? 0;
361
365
  return /* @__PURE__ */ jsx(
@@ -398,7 +402,7 @@ function OrderLineRow({ line, lineIdx, quoteType, currency, isExpanded, isBundle
398
402
  /* @__PURE__ */ jsx("button", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx("svg", { className: `h-4 w-4 transition-transform ${isExpanded ? "rotate-90" : ""}`, fill: "none", viewBox: "0 0 24 24", strokeWidth: "2", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" }) }) }),
399
403
  /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
400
404
  indent > 0 && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: "\u2514" }),
401
- isBundle && /* @__PURE__ */ jsx(Tag, { variant: "brand", className: "px-1.5 text-xs", children: "bundle" }),
405
+ isBundle && /* @__PURE__ */ jsx(Tag, { variant: "brand", className: "px-1.5 text-xs", children: t("cpq.lines.bundle", "bundle") }),
402
406
  /* @__PURE__ */ jsx("span", { className: `font-medium text-sm ${isRemoved ? "text-muted-foreground line-through" : ""}`, children: line.offeringName }),
403
407
  line.quantity > 1 && /* @__PURE__ */ jsxs("span", { className: "rounded bg-muted px-1.5 py-0.5 text-xs font-medium", children: [
404
408
  "\xD7",
@@ -412,23 +416,28 @@ function OrderLineRow({ line, lineIdx, quoteType, currency, isExpanded, isBundle
412
416
  title: isRemoved ? t("cpq.quotes.arc.lineRemovedHint", "This item is cancelled on the subscription when the order is activated") : void 0
413
417
  }
414
418
  ),
415
- isBundle && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
416
- childCount,
417
- " component",
418
- childCount !== 1 ? "s" : ""
419
- ] })
419
+ isBundle && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: childCount !== 1 ? t("cpq.lines.componentCount.other", "{count} components", { count: childCount }) : t("cpq.lines.componentCount.one", "{count} component", { count: childCount }) })
420
420
  ] }) }),
421
421
  /* @__PURE__ */ jsxs("div", { className: "shrink-0 text-right text-xs space-y-0.5", children: [
422
422
  isRemoved && line.arcSource && line.arcSource.mrcAmount > 0 && /* @__PURE__ */ jsxs("div", { children: [
423
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "MRC " }),
423
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
424
+ t("cpq.lines.mrc", "MRC"),
425
+ " "
426
+ ] }),
424
427
  /* @__PURE__ */ jsx("span", { className: "font-mono text-muted-foreground line-through", children: fmt(line.arcSource.mrcAmount, currency) })
425
428
  ] }),
426
429
  line.nrcTotal > 0 && /* @__PURE__ */ jsxs("div", { children: [
427
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "NRC " }),
430
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
431
+ t("cpq.lines.nrc", "NRC"),
432
+ " "
433
+ ] }),
428
434
  /* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: fmt(line.nrcTotal, currency) })
429
435
  ] }),
430
436
  line.mrcTotal > 0 && /* @__PURE__ */ jsxs("div", { children: [
431
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "MRC " }),
437
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
438
+ t("cpq.lines.mrc", "MRC"),
439
+ " "
440
+ ] }),
432
441
  /* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: fmt(line.mrcTotal, currency) })
433
442
  ] })
434
443
  ] })
@@ -453,22 +462,25 @@ function OrderLineRow({ line, lineIdx, quoteType, currency, isExpanded, isBundle
453
462
  style: paddingLeft ? { paddingLeft: `calc(${paddingLeft} + 2rem)` } : void 0,
454
463
  children: isEmpty ? /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground space-y-1", children: [
455
464
  /* @__PURE__ */ jsxs("div", { children: [
456
- "No detailed breakdown for this line.",
457
- mirroredFromItemId && " Mirrored from existing subscription item."
465
+ t("cpq.orders.detail.noBreakdown", "No detailed breakdown for this line."),
466
+ mirroredFromItemId && " ",
467
+ mirroredFromItemId && t("cpq.orders.detail.mirroredItem", "Mirrored from existing subscription item.")
458
468
  ] }),
459
469
  (line.nrcTotal > 0 || line.mrcTotal > 0) && /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
460
470
  line.nrcTotal > 0 && /* @__PURE__ */ jsxs("span", { children: [
461
- "NRC ",
471
+ t("cpq.lines.nrc", "NRC"),
472
+ " ",
462
473
  /* @__PURE__ */ jsx("span", { className: "font-mono font-medium text-foreground", children: fmt(line.nrcTotal, currency) })
463
474
  ] }),
464
475
  line.mrcTotal > 0 && /* @__PURE__ */ jsxs("span", { children: [
465
- "MRC ",
476
+ t("cpq.lines.mrc", "MRC"),
477
+ " ",
466
478
  /* @__PURE__ */ jsx("span", { className: "font-mono font-medium text-foreground", children: fmt(line.mrcTotal, currency) })
467
479
  ] })
468
480
  ] })
469
481
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
470
482
  hasConfig && /* @__PURE__ */ jsxs("div", { children: [
471
- /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Configuration" }),
483
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: t("cpq.lines.configuration", "Configuration") }),
472
484
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1", children: visibleConfigEntries.map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "text-xs", children: [
473
485
  /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
474
486
  key,
@@ -487,19 +499,9 @@ function OrderLineRow({ line, lineIdx, quoteType, currency, isExpanded, isBundle
487
499
  }
488
500
  ),
489
501
  hasTerm && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 text-xs text-muted-foreground", children: [
490
- line.startDate && /* @__PURE__ */ jsxs("span", { children: [
491
- "Start: ",
492
- new Date(line.startDate).toLocaleDateString()
493
- ] }),
494
- line.termMonths && /* @__PURE__ */ jsxs("span", { children: [
495
- "Term: ",
496
- line.termMonths,
497
- "mo"
498
- ] }),
499
- line.endDate && /* @__PURE__ */ jsxs("span", { children: [
500
- "End: ",
501
- new Date(line.endDate).toLocaleDateString()
502
- ] })
502
+ line.startDate && /* @__PURE__ */ jsx("span", { children: t("cpq.lines.term.start", "Start: {date}", { date: new Date(line.startDate).toLocaleDateString() }) }),
503
+ line.termMonths && /* @__PURE__ */ jsx("span", { children: t("cpq.lines.term.months", "Term: {months}mo", { months: line.termMonths }) }),
504
+ line.endDate && /* @__PURE__ */ jsx("span", { children: t("cpq.lines.term.end", "End: {date}", { date: new Date(line.endDate).toLocaleDateString() }) })
503
505
  ] }),
504
506
  hasArcDiff && /* @__PURE__ */ jsx(ArcLineDiff, { line, currency })
505
507
  ] })
@@ -515,6 +517,7 @@ function Spinner() {
515
517
  ] });
516
518
  }
517
519
  function ErrorBanner({ message, onDismiss }) {
520
+ const t = useT();
518
521
  return /* @__PURE__ */ jsxs(Alert, { variant: "destructive", className: "flex items-start gap-2", children: [
519
522
  /* @__PURE__ */ jsx("span", { className: "flex-1", children: message }),
520
523
  onDismiss && /* @__PURE__ */ jsx(
@@ -522,7 +525,7 @@ function ErrorBanner({ message, onDismiss }) {
522
525
  {
523
526
  onClick: onDismiss,
524
527
  className: "text-destructive/70 hover:text-destructive text-sm font-bold",
525
- "aria-label": "Dismiss",
528
+ "aria-label": t("cpq.common.dismiss", "Dismiss"),
526
529
  children: "\xD7"
527
530
  }
528
531
  )
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/cpq/backend/cpq/orders/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter, useParams } from 'next/navigation'\nimport { ArrowRight, ExternalLink, Play, X } from 'lucide-react'\nimport { Alert } 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 {\n formatStatusLabel,\n orderCpqStatusMap,\n type OrderCpqStatus,\n} from '../../../../components/statusMaps'\nimport { StatusPath } from '../../../../components/StatusPath'\nimport { ChargeBreakdownTable, type ChargeRowView } from '../../../../components/ChargeBreakdownTable'\nimport { PricingSummaryCard, type PricingSummaryView } from '../../../../components/PricingSummaryCard'\nimport { ArcLineDiff, LineActionBadge } from '../../../../components/ArcLineDiff'\nimport { arcRecurringDelta } from '../../../../lib/quoteSummaryView'\nimport { isArcCancelledLine } from '../../../../services/arcLineRemoval'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\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 ArcLineSource = {\n subscriptionItemId: string\n name: string\n mrcAmount: number\n nrcAmount: number\n quantity: number\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; origin?: 'rule' | 'manual'; adjustmentId?: string; reasonCode?: string }\n\ntype ResolvedCharge = {\n chargeName?: string\n chargeType?: string\n pricingMethod?: 'flat' | 'tiered' | 'per_unit'\n unitPrice?: number\n quantity?: number | null\n totalPrice?: number | null\n note?: string | null\n breakdown?: { tiers: TierBreakdownEntry[] } | null\n adjustments?: RuleAdjustment[] | null\n listUnitPrice?: number\n listTotalPrice?: number | null\n standardUnitPrice?: number\n standardTotalPrice?: number | null\n}\n\n/** Order lines carry the quote's stored waterfall verbatim (no recalculation at conversion). */\nfunction toChargeRow(c: ResolvedCharge): ChargeRowView {\n return { ...c, chargeName: c.chargeName ?? '\u2014', chargeType: (c.chargeType ?? 'mrc') as 'nrc' | 'mrc' | 'usage', unitPrice: c.unitPrice ?? 0, totalPrice: c.totalPrice ?? null }\n}\n\ntype OrderLineResult = {\n lineId: string\n offeringId: string | null\n offeringName: string\n offeringType: string | null\n productId: string | null\n specId: string | null\n action: string\n parentLineId: string | null\n quantity: number\n configuration: Record<string, unknown>\n startDate: string | null\n termMonths: number | null\n endDate: string | null\n nrcTotal: number\n mrcTotal: number\n charges: ResolvedCharge[]\n sourceQuoteLineId: string | null\n arcSource: ArcLineSource | null\n}\n\ntype OrderResult = {\n id: string\n orderId: string\n orderNumber: string\n customerId: string\n cpqStatus: string\n sourceQuoteId: string | null\n quoteType: string\n currencyCode: string\n pricingSummary: PricingSummaryView & { currencyCode: string }\n activatedAt: string | null\n createdAt: string\n lines: OrderLineResult[]\n}\n\nconst ARC_BADGE_VARIANTS: Record<string, 'brand' | 'success' | 'error'> = {\n amend: 'brand',\n renew: 'success',\n cancel: 'error',\n}\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\nfunction fmt(amount: number, currency: string): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)\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 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 CpqOrderDetailPage(props: { params?: { id?: string } }) {\n const router = useRouter()\n const urlParams = useParams()\n const cpqOrderId = (props.params?.id ?? urlParams?.id) as string\n\n const [order, setOrder] = React.useState<OrderResult | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [activating, setActivating] = React.useState(false)\n const [expandedLines, setExpandedLines] = React.useState<Set<string>>(new Set())\n const [pricingDetail, setPricingDetail] = React.useState<{ lineIdx: number; chargeIdx: number } | null>(null)\n const [customerName, setCustomerName] = React.useState<string | null>(null)\n const [linkedSubscriptions, setLinkedSubscriptions] = React.useState<Array<{\n id: string\n name: string\n code: string\n status: string\n }>>([])\n\n // Find every subscription this order touches. NEW orders write\n // `sourceOrderId` on the freshly-created subscription, so a\n // `?sourceOrderId=\u2026` filter is enough there. ARC orders (amend /\n // renew / cancel) mutate existing subscriptions in place \u2014 the\n // subscription's `sourceOrderId` stays pinned to the original\n // order, so we also resolve targets via the source quote.\n const fetchLinkedSubscriptions = React.useCallback(\n async (orderConfigId: string, sourceQuoteId: string | null) => {\n const byOrderId = fetch(\n `/api/cpq/inventory/subscriptions?sourceOrderId=${orderConfigId}&pageSize=10`,\n )\n .then((r) => (r.ok ? r.json() : null))\n .then((d) => (d?.items ?? (Array.isArray(d) ? d : [])) as Array<{ id: string; name: string; code: string; status: string }>)\n .catch(() => [])\n\n const byTargets = sourceQuoteId\n ? fetch(`/api/cpq/quotes/${sourceQuoteId}/target-subscriptions`)\n .then((r) => (r.ok ? r.json() : null))\n .then(async (d) => {\n const targets: Array<{ subscriptionId: string }> = d?.items ?? []\n const fetched = await Promise.all(\n targets.map((t) =>\n fetch(`/api/cpq/inventory/subscriptions?id=${t.subscriptionId}`)\n .then((r) => (r.ok ? r.json() : null))\n .catch(() => null),\n ),\n )\n return fetched.filter(Boolean) as Array<{ id: string; name: string; code: string; status: string }>\n })\n .catch(() => [] as Array<{ id: string; name: string; code: string; status: string }>)\n : Promise.resolve([] as Array<{ id: string; name: string; code: string; status: string }>)\n\n const [a, b] = await Promise.all([byOrderId, byTargets])\n // Dedupe by id \u2014 a single subscription may appear in both lists\n // (e.g. a NEW order that was later amended into the same sub).\n const seen = new Set<string>()\n const merged: Array<{ id: string; name: string; code: string; status: string }> = []\n for (const sub of [...a, ...b]) {\n if (!sub || seen.has(sub.id)) continue\n seen.add(sub.id)\n merged.push({ id: sub.id, name: sub.name, code: sub.code, status: sub.status })\n }\n setLinkedSubscriptions(merged)\n },\n [],\n )\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n try {\n const result = await apiJson<OrderResult>(`/api/cpq/orders/${cpqOrderId}`)\n if (!cancelled) {\n setOrder(result)\n fetch(`/api/customers/companies?id=${result.customerId}&pageSize=1`)\n .then((r) => r.json())\n .then((data) => {\n const items = data.items ?? data ?? []\n const c = items[0]\n if (c && !cancelled) setCustomerName(c.display_name || c.displayName || c.name || null)\n })\n .catch(() => {})\n if (result.cpqStatus === 'active' || result.cpqStatus === 'fulfilled') {\n void fetchLinkedSubscriptions(result.id, result.sourceQuoteId)\n }\n }\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 }, [cpqOrderId, fetchLinkedSubscriptions])\n\n const activateOrder = async () => {\n if (!order) return\n try {\n setActivating(true)\n setError(null)\n const result = await apiJson<OrderResult>(`/api/cpq/orders/${order.id}/activate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({}),\n })\n setOrder(result)\n void fetchLinkedSubscriptions(result.id, result.sourceQuoteId)\n } catch (err) {\n setError((err as Error).message)\n } finally {\n setActivating(false)\n }\n }\n\n const cancelOrder = async () => {\n if (!order) return\n try {\n setError(null)\n const result = await apiJson<OrderResult>(`/api/cpq/orders/${order.id}/status`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ targetStatus: 'cancelled' }),\n })\n setOrder(result)\n } catch (err) {\n setError((err as Error).message)\n }\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 (!order) {\n return (\n <div className=\"space-y-4\">\n <button onClick={() => router.push('/backend/cpq/orders')} className=\"text-sm text-muted-foreground hover:text-foreground\">\u2190 Back to Orders</button>\n {error && <ErrorBanner message={error} />}\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">Order 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 canActivate = order.cpqStatus === 'draft' || order.cpqStatus === 'pending_activation'\n const canCancel = order.cpqStatus === 'draft' || order.cpqStatus === 'pending_activation' || order.cpqStatus === 'active'\n const currency = order.currencyCode\n\n const togglePricingDetail = (lineIdx: number, chargeIdx: number) => {\n setPricingDetail((prev) =>\n prev?.lineIdx === lineIdx && prev?.chargeIdx === chargeIdx ? null : { lineIdx, chargeIdx },\n )\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Header \u2014 standard FormHeader detail mode, mirrors the CPQ quote\n layout so order \u2194 quote stays consistent. Title is just the order\n number; status / ARC / converted tags sit underneath; primary\n actions (Activate, then Cancel) live on the right next to the\n View Sales Order / Source Quote utility links. */}\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/cpq/orders\"\n backLabel=\"Back to CPQ Orders\"\n entityTypeLabel=\"CPQ Order\"\n title={order.orderNumber || order.orderId.slice(0, 8)}\n statusBadge={\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Tag variant={orderCpqStatusMap[order.cpqStatus as OrderCpqStatus] ?? 'neutral'} dot>\n {formatStatusLabel(order.cpqStatus)}\n </Tag>\n {order.quoteType && order.quoteType !== 'new' && (\n <Tag variant={ARC_BADGE_VARIANTS[order.quoteType] ?? 'neutral'} className=\"uppercase\">\n {order.quoteType}\n </Tag>\n )}\n </div>\n }\n actionsContent={\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/sales/orders/${order.orderId}`)}\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n View Sales Order\n </Button>\n {order.sourceQuoteId && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/cpq/quotes/${order.sourceQuoteId}`)}\n >\n Source Quote\n </Button>\n )}\n {canActivate && (\n <Button type=\"button\" onClick={activateOrder} disabled={activating}>\n {activating ? <Spinner /> : <Play className=\"h-4 w-4\" />}\n Activate\n </Button>\n )}\n {canCancel && (\n <Button type=\"button\" variant=\"destructive-outline\" onClick={cancelOrder}>\n <X className=\"h-4 w-4\" />\n Cancel\n </Button>\n )}\n </>\n }\n />\n\n {/* Status path \u2014 visual progress only. Orders advance via the\n dedicated Activate / Cancel buttons because activation has\n backend side effects (subscription / asset creation). */}\n <div className=\"flex items-center gap-3 flex-wrap\">\n <StatusPath\n // Order path is read-only \u2014 activation has backend side effects\n // (subscription / asset creation) so transitions go through the\n // dedicated Activate / Cancel buttons.\n current={order.cpqStatus}\n path={['draft', 'pending_activation', 'active', 'fulfilled']}\n terminals={['cancelled']}\n statusMap={orderCpqStatusMap}\n ariaLabel=\"Order status path\"\n />\n </div>\n\n {error && <ErrorBanner message={error} onDismiss={() => setError(null)} />}\n\n {/* Linked subscriptions \u2014 one card per subscription this order\n touches. NEW orders write one fresh subscription; ARC orders\n (amend / renew / cancel) reach one or more existing\n subscriptions through the source quote's target list. */}\n {linkedSubscriptions.length > 0 && (\n <div className=\"space-y-2\">\n {linkedSubscriptions.map((sub) => (\n <div\n key={sub.id}\n className=\"rounded-lg border bg-card p-4 flex items-center gap-4\"\n >\n <div className=\"flex-1 min-w-0 space-y-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n Linked Subscription\n </span>\n <Tag\n variant={sub.status === 'active' ? 'success' : 'info'}\n dot\n className=\"text-[10px] px-1.5\"\n >\n {sub.status}\n </Tag>\n </div>\n <div className=\"text-sm font-medium\">\n {sub.name}{' '}\n <span className=\"text-muted-foreground font-mono text-xs\">({sub.code})</span>\n </div>\n {order.activatedAt && (\n <div className=\"text-xs text-muted-foreground\">\n Activated on {new Date(order.activatedAt).toLocaleString()}\n </div>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/cpq/inventory/subscriptions/${sub.id}`)}\n >\n <ArrowRight className=\"h-3.5 w-3.5\" />\n Open\n </Button>\n </div>\n ))}\n </div>\n )}\n\n {/* Meta cards \u2014 secondary reference info, matches the quote layout. */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n <MetaCard label=\"Customer\">\n {customerName ? (\n <span className=\"font-medium\">{customerName}</span>\n ) : (\n <span className=\"font-mono text-xs text-muted-foreground\">\n {order.customerId.slice(0, 8)}\u2026\n </span>\n )}\n </MetaCard>\n <MetaCard label=\"Created\">\n <span className=\"font-medium\">{new Date(order.createdAt).toLocaleDateString()}</span>\n </MetaCard>\n <MetaCard label=\"Currency\">\n <span className=\"font-medium\">{currency}</span>\n </MetaCard>\n </div>\n\n <PricingSummaryCard\n summary={order.pricingSummary}\n currency={currency}\n arcDelta={order.quoteType === 'amend' || order.quoteType === 'renew'\n ? arcRecurringDelta(order.lines.map((l) => ({ ...l, action: l.action as 'add' | 'modify' | 'cancel' })))\n : null}\n />\n\n {/* Order Lines */}\n <OrderLineTree\n lines={order.lines}\n quoteType={order.quoteType}\n currency={currency}\n expandedLines={expandedLines}\n pricingDetail={pricingDetail}\n onToggleLine={toggleLine}\n onTogglePricingDetail={togglePricingDetail}\n />\n </div>\n )\n}\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\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 OrderLineTree({\n lines,\n quoteType,\n currency,\n expandedLines,\n pricingDetail,\n onToggleLine,\n onTogglePricingDetail,\n}: {\n lines: OrderLineResult[]\n quoteType: string\n currency: string\n expandedLines: Set<string>\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onToggleLine: (id: string) => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const rootLines = lines.filter((l) => !l.parentLineId)\n const childrenByParent = new Map<string, OrderLineResult[]>()\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 // Stable index per visible line so the pricing-detail toggle can be\n // keyed by (lineIdx, chargeIdx) the same way the quote page does.\n const indexOf = new Map<string, number>()\n lines.forEach((l, i) => indexOf.set(l.lineId, i))\n\n return (\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">Line Items ({lines.length})</h3>\n {lines.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">\n No line items.\n </div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {rootLines.map((line) => {\n const isBundle = line.offeringType === 'bundle'\n const children = childrenByParent.get(line.lineId) ?? []\n const isExpanded = expandedLines.has(line.lineId)\n const lineIdx = indexOf.get(line.lineId) ?? 0\n return (\n <div key={line.lineId}>\n <OrderLineRow\n line={line}\n lineIdx={lineIdx}\n quoteType={quoteType}\n currency={currency}\n isExpanded={isExpanded}\n isBundle={isBundle}\n childCount={children.length}\n indent={0}\n pricingDetail={pricingDetail}\n onToggle={() => onToggleLine(line.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n {isBundle && isExpanded && children.length > 0 && (\n <div className=\"border-t border-dashed border-brand-violet/30 bg-brand-violet/5\">\n <div className=\"px-6 py-1.5\">\n <span className=\"text-[10px] font-medium text-brand-violet uppercase tracking-wider\">Bundle Components ({children.length})</span>\n </div>\n {children.map((child) => {\n const childIdx = indexOf.get(child.lineId) ?? 0\n return (\n <OrderLineRow\n key={child.lineId}\n line={child}\n lineIdx={childIdx}\n quoteType={quoteType}\n currency={currency}\n isExpanded={expandedLines.has(child.lineId)}\n isBundle={false}\n childCount={0}\n indent={1}\n pricingDetail={pricingDetail}\n onToggle={() => onToggleLine(child.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n )\n })}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nfunction OrderLineRow({ line, lineIdx, quoteType, currency, isExpanded, isBundle, childCount, indent, pricingDetail, onToggle, onTogglePricingDetail }: {\n line: OrderLineResult; lineIdx: number; quoteType: string; currency: string; isExpanded: boolean; isBundle: boolean; childCount: number; indent: number\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onToggle: () => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const t = useT()\n const paddingLeft = indent > 0 ? `${indent * 2 + 1}rem` : undefined\n // Same presentation as the quote page: an existing item removed on an\n // Amend / Renew quote reads as \"remove\", struck through.\n const isRemoved = isArcCancelledLine(line, quoteType)\n\n return (\n <div>\n <div\n className={`flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer ${isRemoved ? 'bg-muted/20' : ''}`}\n style={paddingLeft ? { paddingLeft } : undefined}\n onClick={onToggle}\n data-testid=\"cpq-order-line\"\n data-removed={isRemoved ? 'true' : undefined}\n >\n <button 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 <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {indent > 0 && <span className=\"text-muted-foreground text-xs\">\u2514</span>}\n {isBundle && (\n <Tag variant=\"brand\" className=\"px-1.5 text-xs\">bundle</Tag>\n )}\n <span className={`font-medium text-sm ${isRemoved ? 'text-muted-foreground line-through' : ''}`}>{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 <LineActionBadge\n action={line.action}\n label={isRemoved ? t('cpq.quotes.arc.lineRemoved', 'remove') : undefined}\n title={isRemoved ? t('cpq.quotes.arc.lineRemovedHint', 'This item is cancelled on the subscription when the order is activated') : undefined}\n />\n {isBundle && <span className=\"text-xs text-muted-foreground\">{childCount} component{childCount !== 1 ? 's' : ''}</span>}\n </div>\n </div>\n\n <div className=\"shrink-0 text-right text-xs space-y-0.5\">\n {isRemoved && line.arcSource && line.arcSource.mrcAmount > 0 && (\n <div>\n <span className=\"text-muted-foreground\">MRC </span>\n <span className=\"font-mono text-muted-foreground line-through\">{fmt(line.arcSource.mrcAmount, currency)}</span>\n </div>\n )}\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 </div>\n\n {isExpanded && (() => {\n const internalKeys = new Set(['_arcMirroredName', '_arcMirroredFromItemId', '_arcPriceFrozen', '_arcRepriced', 'offeringName'])\n const visibleConfigEntries = Object.entries(line.configuration).filter(\n ([key]) => !internalKeys.has(key),\n )\n const hasConfig = visibleConfigEntries.length > 0\n const hasCharges = line.charges.length > 0\n const hasTerm = !!(line.startDate || line.termMonths || line.endDate)\n const hasArcDiff = !!line.arcSource\n const mirroredFromItemId = (line.configuration?._arcMirroredFromItemId as string | undefined) ?? null\n const isEmpty = !hasConfig && !hasCharges && !hasTerm && !hasArcDiff\n\n return (\n <div\n className=\"border-t bg-muted/10 px-12 py-3 space-y-3\"\n style={paddingLeft ? { paddingLeft: `calc(${paddingLeft} + 2rem)` } : undefined}\n >\n {isEmpty ? (\n <div className=\"text-xs text-muted-foreground space-y-1\">\n <div>\n No detailed breakdown for this line.\n {mirroredFromItemId && ' Mirrored from existing subscription item.'}\n </div>\n {(line.nrcTotal > 0 || line.mrcTotal > 0) && (\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 {hasConfig && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Configuration</p>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {visibleConfigEntries.map(([key, value]) => (\n <div key={key} className=\"text-xs\">\n <span className=\"text-muted-foreground\">{key}: </span>\n <span className=\"font-medium\">{String(value)}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {hasCharges && (\n <ChargeBreakdownTable\n charges={line.charges.map(toChargeRow)}\n currency={currency}\n openDetailIndex={pricingDetail?.lineIdx === lineIdx ? pricingDetail.chargeIdx : null}\n onToggleDetail={(chargeIdx) => onTogglePricingDetail(lineIdx, chargeIdx)}\n />\n )}\n\n {hasTerm && (\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n {line.startDate && <span>Start: {new Date(line.startDate).toLocaleDateString()}</span>}\n {line.termMonths && <span>Term: {line.termMonths}mo</span>}\n {line.endDate && <span>End: {new Date(line.endDate).toLocaleDateString()}</span>}\n </div>\n )}\n\n {/* XD-250 ARC: before/after preview below the charges, as on the quote. */}\n {hasArcDiff && <ArcLineDiff line={line} currency={currency} />}\n </>\n )}\n </div>\n )\n })()}\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"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter, useParams } from 'next/navigation'\nimport { ArrowRight, ExternalLink, Play, X } from 'lucide-react'\nimport { Alert } 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 {\n formatStatusLabel,\n orderCpqStatusMap,\n type OrderCpqStatus,\n} from '../../../../components/statusMaps'\nimport { StatusPath } from '../../../../components/StatusPath'\nimport { ChargeBreakdownTable, type ChargeRowView } from '../../../../components/ChargeBreakdownTable'\nimport { PricingSummaryCard, type PricingSummaryView } from '../../../../components/PricingSummaryCard'\nimport { ArcLineDiff, LineActionBadge } from '../../../../components/ArcLineDiff'\nimport { arcRecurringDelta } from '../../../../lib/quoteSummaryView'\nimport { isArcCancelledLine } from '../../../../services/arcLineRemoval'\nimport { useT, type TranslateFn } from '@open-mercato/shared/lib/i18n/context'\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 ArcLineSource = {\n subscriptionItemId: string\n name: string\n mrcAmount: number\n nrcAmount: number\n quantity: number\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; origin?: 'rule' | 'manual'; adjustmentId?: string; reasonCode?: string }\n\ntype ResolvedCharge = {\n chargeName?: string\n chargeType?: string\n pricingMethod?: 'flat' | 'tiered' | 'per_unit'\n unitPrice?: number\n quantity?: number | null\n totalPrice?: number | null\n note?: string | null\n breakdown?: { tiers: TierBreakdownEntry[] } | null\n adjustments?: RuleAdjustment[] | null\n listUnitPrice?: number\n listTotalPrice?: number | null\n standardUnitPrice?: number\n standardTotalPrice?: number | null\n}\n\n/** Order lines carry the quote's stored waterfall verbatim (no recalculation at conversion). */\nfunction toChargeRow(c: ResolvedCharge): ChargeRowView {\n return { ...c, chargeName: c.chargeName ?? '\u2014', chargeType: (c.chargeType ?? 'mrc') as 'nrc' | 'mrc' | 'usage', unitPrice: c.unitPrice ?? 0, totalPrice: c.totalPrice ?? null }\n}\n\ntype OrderLineResult = {\n lineId: string\n offeringId: string | null\n offeringName: string\n offeringType: string | null\n productId: string | null\n specId: string | null\n action: string\n parentLineId: string | null\n quantity: number\n configuration: Record<string, unknown>\n startDate: string | null\n termMonths: number | null\n endDate: string | null\n nrcTotal: number\n mrcTotal: number\n charges: ResolvedCharge[]\n sourceQuoteLineId: string | null\n arcSource: ArcLineSource | null\n}\n\ntype OrderResult = {\n id: string\n orderId: string\n orderNumber: string\n customerId: string\n cpqStatus: string\n sourceQuoteId: string | null\n quoteType: string\n currencyCode: string\n pricingSummary: PricingSummaryView & { currencyCode: string }\n activatedAt: string | null\n createdAt: string\n lines: OrderLineResult[]\n}\n\nconst ARC_BADGE_VARIANTS: Record<string, 'brand' | 'success' | 'error'> = {\n amend: 'brand',\n renew: 'success',\n cancel: 'error',\n}\n\nfunction quoteTypeLabel(t: TranslateFn, quoteType: string): string {\n switch (quoteType) {\n case 'amend':\n return t('cpq.quotes.type.amend', 'amend')\n case 'renew':\n return t('cpq.quotes.type.renew', 'renew')\n case 'cancel':\n return t('cpq.quotes.type.cancel', 'cancel')\n default:\n return quoteType\n }\n}\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\nfunction fmt(amount: number, currency: string): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount)\n}\n\nasync function apiJson<T>(t: TranslateFn, 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 ?? t('cpq.common.requestFailed', 'Request failed ({status})', { status: res.status }))\n return json as T\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 CpqOrderDetailPage(props: { params?: { id?: string } }) {\n const router = useRouter()\n const t = useT()\n const urlParams = useParams()\n const cpqOrderId = (props.params?.id ?? urlParams?.id) as string\n\n const [order, setOrder] = React.useState<OrderResult | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [activating, setActivating] = React.useState(false)\n const [expandedLines, setExpandedLines] = React.useState<Set<string>>(new Set())\n const [pricingDetail, setPricingDetail] = React.useState<{ lineIdx: number; chargeIdx: number } | null>(null)\n const [customerName, setCustomerName] = React.useState<string | null>(null)\n const [linkedSubscriptions, setLinkedSubscriptions] = React.useState<Array<{\n id: string\n name: string\n code: string\n status: string\n }>>([])\n\n // Find every subscription this order touches. NEW orders write\n // `sourceOrderId` on the freshly-created subscription, so a\n // `?sourceOrderId=\u2026` filter is enough there. ARC orders (amend /\n // renew / cancel) mutate existing subscriptions in place \u2014 the\n // subscription's `sourceOrderId` stays pinned to the original\n // order, so we also resolve targets via the source quote.\n const fetchLinkedSubscriptions = React.useCallback(\n async (orderConfigId: string, sourceQuoteId: string | null) => {\n const byOrderId = fetch(\n `/api/cpq/inventory/subscriptions?sourceOrderId=${orderConfigId}&pageSize=10`,\n )\n .then((r) => (r.ok ? r.json() : null))\n .then((d) => (d?.items ?? (Array.isArray(d) ? d : [])) as Array<{ id: string; name: string; code: string; status: string }>)\n .catch(() => [])\n\n const byTargets = sourceQuoteId\n ? fetch(`/api/cpq/quotes/${sourceQuoteId}/target-subscriptions`)\n .then((r) => (r.ok ? r.json() : null))\n .then(async (d) => {\n const targets: Array<{ subscriptionId: string }> = d?.items ?? []\n const fetched = await Promise.all(\n targets.map((target) =>\n fetch(`/api/cpq/inventory/subscriptions?id=${target.subscriptionId}`)\n .then((r) => (r.ok ? r.json() : null))\n .catch(() => null),\n ),\n )\n return fetched.filter(Boolean) as Array<{ id: string; name: string; code: string; status: string }>\n })\n .catch(() => [] as Array<{ id: string; name: string; code: string; status: string }>)\n : Promise.resolve([] as Array<{ id: string; name: string; code: string; status: string }>)\n\n const [a, b] = await Promise.all([byOrderId, byTargets])\n // Dedupe by id \u2014 a single subscription may appear in both lists\n // (e.g. a NEW order that was later amended into the same sub).\n const seen = new Set<string>()\n const merged: Array<{ id: string; name: string; code: string; status: string }> = []\n for (const sub of [...a, ...b]) {\n if (!sub || seen.has(sub.id)) continue\n seen.add(sub.id)\n merged.push({ id: sub.id, name: sub.name, code: sub.code, status: sub.status })\n }\n setLinkedSubscriptions(merged)\n },\n [],\n )\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n try {\n const result = await apiJson<OrderResult>(t, `/api/cpq/orders/${cpqOrderId}`)\n if (!cancelled) {\n setOrder(result)\n fetch(`/api/customers/companies?id=${result.customerId}&pageSize=1`)\n .then((r) => r.json())\n .then((data) => {\n const items = data.items ?? data ?? []\n const c = items[0]\n if (c && !cancelled) setCustomerName(c.display_name || c.displayName || c.name || null)\n })\n .catch(() => {})\n if (result.cpqStatus === 'active' || result.cpqStatus === 'fulfilled') {\n void fetchLinkedSubscriptions(result.id, result.sourceQuoteId)\n }\n }\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 }, [cpqOrderId, fetchLinkedSubscriptions, t])\n\n const activateOrder = async () => {\n if (!order) return\n try {\n setActivating(true)\n setError(null)\n const result = await apiJson<OrderResult>(t, `/api/cpq/orders/${order.id}/activate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({}),\n })\n setOrder(result)\n void fetchLinkedSubscriptions(result.id, result.sourceQuoteId)\n } catch (err) {\n setError((err as Error).message)\n } finally {\n setActivating(false)\n }\n }\n\n const cancelOrder = async () => {\n if (!order) return\n try {\n setError(null)\n const result = await apiJson<OrderResult>(t, `/api/cpq/orders/${order.id}/status`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ targetStatus: 'cancelled' }),\n })\n setOrder(result)\n } catch (err) {\n setError((err as Error).message)\n }\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 /> {t('cpq.orders.detail.loading', 'Loading\u2026')}\n </div>\n )\n }\n\n if (!order) {\n return (\n <div className=\"space-y-4\">\n <button onClick={() => router.push('/backend/cpq/orders')} className=\"text-sm text-muted-foreground hover:text-foreground\">{t('cpq.orders.detail.backToOrders', '\u2190 Back to Orders')}</button>\n {error && <ErrorBanner message={error} />}\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">{t('cpq.orders.detail.notFound', 'Order 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 canActivate = order.cpqStatus === 'draft' || order.cpqStatus === 'pending_activation'\n const canCancel = order.cpqStatus === 'draft' || order.cpqStatus === 'pending_activation' || order.cpqStatus === 'active'\n const currency = order.currencyCode\n\n const togglePricingDetail = (lineIdx: number, chargeIdx: number) => {\n setPricingDetail((prev) =>\n prev?.lineIdx === lineIdx && prev?.chargeIdx === chargeIdx ? null : { lineIdx, chargeIdx },\n )\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Header \u2014 standard FormHeader detail mode, mirrors the CPQ quote\n layout so order \u2194 quote stays consistent. Title is just the order\n number; status / ARC / converted tags sit underneath; primary\n actions (Activate, then Cancel) live on the right next to the\n View Sales Order / Source Quote utility links. */}\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/cpq/orders\"\n backLabel={t('cpq.orders.detail.backLabel', 'Back to CPQ Orders')}\n entityTypeLabel={t('cpq.orders.detail.entityType', 'CPQ Order')}\n title={order.orderNumber || order.orderId.slice(0, 8)}\n statusBadge={\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Tag variant={orderCpqStatusMap[order.cpqStatus as OrderCpqStatus] ?? 'neutral'} dot>\n {formatStatusLabel(order.cpqStatus)}\n </Tag>\n {order.quoteType && order.quoteType !== 'new' && (\n <Tag variant={ARC_BADGE_VARIANTS[order.quoteType] ?? 'neutral'} className=\"uppercase\">\n {quoteTypeLabel(t, order.quoteType)}\n </Tag>\n )}\n </div>\n }\n actionsContent={\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/sales/orders/${order.orderId}`)}\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n {t('cpq.orders.detail.viewSalesOrder', 'View Sales Order')}\n </Button>\n {order.sourceQuoteId && (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/cpq/quotes/${order.sourceQuoteId}`)}\n >\n {t('cpq.orders.detail.sourceQuote', 'Source Quote')}\n </Button>\n )}\n {canActivate && (\n <Button type=\"button\" onClick={activateOrder} disabled={activating}>\n {activating ? <Spinner /> : <Play className=\"h-4 w-4\" />}\n {t('cpq.orders.detail.activate', 'Activate')}\n </Button>\n )}\n {canCancel && (\n <Button type=\"button\" variant=\"destructive-outline\" onClick={cancelOrder}>\n <X className=\"h-4 w-4\" />\n {t('cpq.common.cancel', 'Cancel')}\n </Button>\n )}\n </>\n }\n />\n\n {/* Status path \u2014 visual progress only. Orders advance via the\n dedicated Activate / Cancel buttons because activation has\n backend side effects (subscription / asset creation). */}\n <div className=\"flex items-center gap-3 flex-wrap\">\n <StatusPath\n // Order path is read-only \u2014 activation has backend side effects\n // (subscription / asset creation) so transitions go through the\n // dedicated Activate / Cancel buttons.\n current={order.cpqStatus}\n path={['draft', 'pending_activation', 'active', 'fulfilled']}\n terminals={['cancelled']}\n statusMap={orderCpqStatusMap}\n ariaLabel={t('cpq.orders.detail.statusPath', 'Order status path')}\n />\n </div>\n\n {error && <ErrorBanner message={error} onDismiss={() => setError(null)} />}\n\n {/* Linked subscriptions \u2014 one card per subscription this order\n touches. NEW orders write one fresh subscription; ARC orders\n (amend / renew / cancel) reach one or more existing\n subscriptions through the source quote's target list. */}\n {linkedSubscriptions.length > 0 && (\n <div className=\"space-y-2\">\n {linkedSubscriptions.map((sub) => (\n <div\n key={sub.id}\n className=\"rounded-lg border bg-card p-4 flex items-center gap-4\"\n >\n <div className=\"flex-1 min-w-0 space-y-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {t('cpq.orders.detail.linkedSubscription', 'Linked Subscription')}\n </span>\n <Tag\n variant={sub.status === 'active' ? 'success' : 'info'}\n dot\n className=\"text-[10px] px-1.5\"\n >\n {sub.status}\n </Tag>\n </div>\n <div className=\"text-sm font-medium\">\n {sub.name}{' '}\n <span className=\"text-muted-foreground font-mono text-xs\">({sub.code})</span>\n </div>\n {order.activatedAt && (\n <div className=\"text-xs text-muted-foreground\">\n {t('cpq.orders.detail.activatedOn', 'Activated on {date}', { date: new Date(order.activatedAt).toLocaleString() })}\n </div>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push(`/backend/cpq/inventory/subscriptions/${sub.id}`)}\n >\n <ArrowRight className=\"h-3.5 w-3.5\" />\n {t('cpq.orders.actions.open', 'Open')}\n </Button>\n </div>\n ))}\n </div>\n )}\n\n {/* Meta cards \u2014 secondary reference info, matches the quote layout. */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n <MetaCard label={t('cpq.orders.detail.meta.customer', 'Customer')}>\n {customerName ? (\n <span className=\"font-medium\">{customerName}</span>\n ) : (\n <span className=\"font-mono text-xs text-muted-foreground\">\n {order.customerId.slice(0, 8)}\u2026\n </span>\n )}\n </MetaCard>\n <MetaCard label={t('cpq.orders.detail.meta.created', 'Created')}>\n <span className=\"font-medium\">{new Date(order.createdAt).toLocaleDateString()}</span>\n </MetaCard>\n <MetaCard label={t('cpq.orders.detail.meta.currency', 'Currency')}>\n <span className=\"font-medium\">{currency}</span>\n </MetaCard>\n </div>\n\n <PricingSummaryCard\n summary={order.pricingSummary}\n currency={currency}\n arcDelta={order.quoteType === 'amend' || order.quoteType === 'renew'\n ? arcRecurringDelta(order.lines.map((l) => ({ ...l, action: l.action as 'add' | 'modify' | 'cancel' })))\n : null}\n />\n\n {/* Order Lines */}\n <OrderLineTree\n lines={order.lines}\n quoteType={order.quoteType}\n currency={currency}\n expandedLines={expandedLines}\n pricingDetail={pricingDetail}\n onToggleLine={toggleLine}\n onTogglePricingDetail={togglePricingDetail}\n />\n </div>\n )\n}\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\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 OrderLineTree({\n lines,\n quoteType,\n currency,\n expandedLines,\n pricingDetail,\n onToggleLine,\n onTogglePricingDetail,\n}: {\n lines: OrderLineResult[]\n quoteType: string\n currency: string\n expandedLines: Set<string>\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onToggleLine: (id: string) => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const t = useT()\n const rootLines = lines.filter((l) => !l.parentLineId)\n const childrenByParent = new Map<string, OrderLineResult[]>()\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 // Stable index per visible line so the pricing-detail toggle can be\n // keyed by (lineIdx, chargeIdx) the same way the quote page does.\n const indexOf = new Map<string, number>()\n lines.forEach((l, i) => indexOf.set(l.lineId, i))\n\n return (\n <div>\n <h3 className=\"text-sm font-medium mb-2 px-1\">{t('cpq.orders.detail.lineItems', 'Line Items ({count})', { count: lines.length })}</h3>\n {lines.length === 0 ? (\n <div className=\"rounded-lg border bg-card py-8 text-center text-sm text-muted-foreground\">\n {t('cpq.orders.detail.noLineItems', 'No line items.')}\n </div>\n ) : (\n <div className=\"rounded-lg border bg-card divide-y\">\n {rootLines.map((line) => {\n const isBundle = line.offeringType === 'bundle'\n const children = childrenByParent.get(line.lineId) ?? []\n const isExpanded = expandedLines.has(line.lineId)\n const lineIdx = indexOf.get(line.lineId) ?? 0\n return (\n <div key={line.lineId}>\n <OrderLineRow\n line={line}\n lineIdx={lineIdx}\n quoteType={quoteType}\n currency={currency}\n isExpanded={isExpanded}\n isBundle={isBundle}\n childCount={children.length}\n indent={0}\n pricingDetail={pricingDetail}\n onToggle={() => onToggleLine(line.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n {isBundle && isExpanded && children.length > 0 && (\n <div className=\"border-t border-dashed border-brand-violet/30 bg-brand-violet/5\">\n <div className=\"px-6 py-1.5\">\n <span className=\"text-[10px] font-medium text-brand-violet uppercase tracking-wider\">{t('cpq.lines.bundleComponents', 'Bundle Components ({count})', { count: children.length })}</span>\n </div>\n {children.map((child) => {\n const childIdx = indexOf.get(child.lineId) ?? 0\n return (\n <OrderLineRow\n key={child.lineId}\n line={child}\n lineIdx={childIdx}\n quoteType={quoteType}\n currency={currency}\n isExpanded={expandedLines.has(child.lineId)}\n isBundle={false}\n childCount={0}\n indent={1}\n pricingDetail={pricingDetail}\n onToggle={() => onToggleLine(child.lineId)}\n onTogglePricingDetail={onTogglePricingDetail}\n />\n )\n })}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nfunction OrderLineRow({ line, lineIdx, quoteType, currency, isExpanded, isBundle, childCount, indent, pricingDetail, onToggle, onTogglePricingDetail }: {\n line: OrderLineResult; lineIdx: number; quoteType: string; currency: string; isExpanded: boolean; isBundle: boolean; childCount: number; indent: number\n pricingDetail: { lineIdx: number; chargeIdx: number } | null\n onToggle: () => void\n onTogglePricingDetail: (lineIdx: number, chargeIdx: number) => void\n}) {\n const t = useT()\n const paddingLeft = indent > 0 ? `${indent * 2 + 1}rem` : undefined\n // Same presentation as the quote page: an existing item removed on an\n // Amend / Renew quote reads as \"remove\", struck through.\n const isRemoved = isArcCancelledLine(line, quoteType)\n\n return (\n <div>\n <div\n className={`flex items-center gap-3 px-4 py-3 hover:bg-muted/30 transition-colors cursor-pointer ${isRemoved ? 'bg-muted/20' : ''}`}\n style={paddingLeft ? { paddingLeft } : undefined}\n onClick={onToggle}\n data-testid=\"cpq-order-line\"\n data-removed={isRemoved ? 'true' : undefined}\n >\n <button 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 <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {indent > 0 && <span className=\"text-muted-foreground text-xs\">\u2514</span>}\n {isBundle && (\n <Tag variant=\"brand\" className=\"px-1.5 text-xs\">{t('cpq.lines.bundle', 'bundle')}</Tag>\n )}\n <span className={`font-medium text-sm ${isRemoved ? 'text-muted-foreground line-through' : ''}`}>{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 <LineActionBadge\n action={line.action}\n label={isRemoved ? t('cpq.quotes.arc.lineRemoved', 'remove') : undefined}\n title={isRemoved ? t('cpq.quotes.arc.lineRemovedHint', 'This item is cancelled on the subscription when the order is activated') : undefined}\n />\n {isBundle && (\n <span className=\"text-xs text-muted-foreground\">\n {childCount !== 1\n ? t('cpq.lines.componentCount.other', '{count} components', { count: childCount })\n : t('cpq.lines.componentCount.one', '{count} component', { count: childCount })}\n </span>\n )}\n </div>\n </div>\n\n <div className=\"shrink-0 text-right text-xs space-y-0.5\">\n {isRemoved && line.arcSource && line.arcSource.mrcAmount > 0 && (\n <div>\n <span className=\"text-muted-foreground\">{t('cpq.lines.mrc', 'MRC')} </span>\n <span className=\"font-mono text-muted-foreground line-through\">{fmt(line.arcSource.mrcAmount, currency)}</span>\n </div>\n )}\n {line.nrcTotal > 0 && <div><span className=\"text-muted-foreground\">{t('cpq.lines.nrc', 'NRC')} </span><span className=\"font-mono font-medium\">{fmt(line.nrcTotal, currency)}</span></div>}\n {line.mrcTotal > 0 && <div><span className=\"text-muted-foreground\">{t('cpq.lines.mrc', 'MRC')} </span><span className=\"font-mono font-medium\">{fmt(line.mrcTotal, currency)}</span></div>}\n </div>\n </div>\n\n {isExpanded && (() => {\n const internalKeys = new Set(['_arcMirroredName', '_arcMirroredFromItemId', '_arcPriceFrozen', '_arcRepriced', 'offeringName'])\n const visibleConfigEntries = Object.entries(line.configuration).filter(\n ([key]) => !internalKeys.has(key),\n )\n const hasConfig = visibleConfigEntries.length > 0\n const hasCharges = line.charges.length > 0\n const hasTerm = !!(line.startDate || line.termMonths || line.endDate)\n const hasArcDiff = !!line.arcSource\n const mirroredFromItemId = (line.configuration?._arcMirroredFromItemId as string | undefined) ?? null\n const isEmpty = !hasConfig && !hasCharges && !hasTerm && !hasArcDiff\n\n return (\n <div\n className=\"border-t bg-muted/10 px-12 py-3 space-y-3\"\n style={paddingLeft ? { paddingLeft: `calc(${paddingLeft} + 2rem)` } : undefined}\n >\n {isEmpty ? (\n <div className=\"text-xs text-muted-foreground space-y-1\">\n <div>\n {t('cpq.orders.detail.noBreakdown', 'No detailed breakdown for this line.')}\n {mirroredFromItemId && ' '}\n {mirroredFromItemId && t('cpq.orders.detail.mirroredItem', 'Mirrored from existing subscription item.')}\n </div>\n {(line.nrcTotal > 0 || line.mrcTotal > 0) && (\n <div className=\"flex gap-4\">\n {line.nrcTotal > 0 && (\n <span>{t('cpq.lines.nrc', 'NRC')} <span className=\"font-mono font-medium text-foreground\">{fmt(line.nrcTotal, currency)}</span></span>\n )}\n {line.mrcTotal > 0 && (\n <span>{t('cpq.lines.mrc', 'MRC')} <span className=\"font-mono font-medium text-foreground\">{fmt(line.mrcTotal, currency)}</span></span>\n )}\n </div>\n )}\n </div>\n ) : (\n <>\n {hasConfig && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">{t('cpq.lines.configuration', 'Configuration')}</p>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-1\">\n {visibleConfigEntries.map(([key, value]) => (\n <div key={key} className=\"text-xs\">\n <span className=\"text-muted-foreground\">{key}: </span>\n <span className=\"font-medium\">{String(value)}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {hasCharges && (\n <ChargeBreakdownTable\n charges={line.charges.map(toChargeRow)}\n currency={currency}\n openDetailIndex={pricingDetail?.lineIdx === lineIdx ? pricingDetail.chargeIdx : null}\n onToggleDetail={(chargeIdx) => onTogglePricingDetail(lineIdx, chargeIdx)}\n />\n )}\n\n {hasTerm && (\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n {line.startDate && <span>{t('cpq.lines.term.start', 'Start: {date}', { date: new Date(line.startDate).toLocaleDateString() })}</span>}\n {line.termMonths && <span>{t('cpq.lines.term.months', 'Term: {months}mo', { months: line.termMonths })}</span>}\n {line.endDate && <span>{t('cpq.lines.term.end', 'End: {date}', { date: new Date(line.endDate).toLocaleDateString() })}</span>}\n </div>\n )}\n\n {/* XD-250 ARC: before/after preview below the charges, as on the quote. */}\n {hasArcDiff && <ArcLineDiff line={line} currency={currency} />}\n </>\n )}\n </div>\n )\n })()}\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 const t = useT()\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={t('cpq.common.dismiss', 'Dismiss')}\n >\n \u00D7\n </button>\n )}\n </Alert>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -34,13 +34,13 @@ function CpqOrdersListPage() {
34
34
  });
35
35
  const statusOptions = React.useMemo(
36
36
  () => [
37
- { value: "draft", label: "Draft" },
38
- { value: "pending_activation", label: "Pending Activation" },
39
- { value: "active", label: "Active" },
40
- { value: "fulfilled", label: "Fulfilled" },
41
- { value: "cancelled", label: "Cancelled" }
37
+ { value: "draft", label: t("cpq.orders.status.draft", "Draft") },
38
+ { value: "pending_activation", label: t("cpq.orders.status.pending_activation", "Pending Activation") },
39
+ { value: "active", label: t("cpq.orders.status.active", "Active") },
40
+ { value: "fulfilled", label: t("cpq.orders.status.fulfilled", "Fulfilled") },
41
+ { value: "cancelled", label: t("cpq.orders.status.cancelled", "Cancelled") }
42
42
  ],
43
- []
43
+ [t]
44
44
  );
45
45
  const filters = React.useMemo(
46
46
  () => [