@openrails/billing-ui 0.249.0 → 0.250.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 (148) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +13 -13
  3. package/dist/account/account-billing.d.ts +2 -2
  4. package/dist/account/cancel-dialog.d.ts +2 -2
  5. package/dist/account/change-card-dialog.d.ts +2 -2
  6. package/dist/account/payment-history.d.ts +2 -2
  7. package/dist/account/payment-methods-panel.d.ts +2 -2
  8. package/dist/account/section.d.ts +2 -2
  9. package/dist/account/subscriptions-panel.d.ts +2 -2
  10. package/dist/admin/context.d.ts +2 -2
  11. package/dist/admin/lib/queries.d.ts +1 -1
  12. package/dist/admin/messages.d.ts +3 -3
  13. package/dist/admin/pages/catalog/psp-links.d.ts +1 -1
  14. package/dist/admin/theme.d.ts +2 -2
  15. package/dist/admin/types.d.ts +2 -2
  16. package/dist/{admin-attempts-lAoW-Urd.js → admin-attempts-DxRHTODq.js} +8 -8
  17. package/dist/{admin-attempts-lAoW-Urd.js.map → admin-attempts-DxRHTODq.js.map} +1 -1
  18. package/dist/{admin-auth-DQGHtt0j.js → admin-auth-CiuZ-Hlm.js} +2 -2
  19. package/dist/{admin-auth-DQGHtt0j.js.map → admin-auth-CiuZ-Hlm.js.map} +1 -1
  20. package/dist/{admin-badge-DR5-1qd8.js → admin-badge-VCGbnfiN.js} +2 -2
  21. package/dist/{admin-badge-DR5-1qd8.js.map → admin-badge-VCGbnfiN.js.map} +1 -1
  22. package/dist/{admin-button-CTL3DgOt.js → admin-button-Oip73Plq.js} +2 -2
  23. package/dist/{admin-button-CTL3DgOt.js.map → admin-button-Oip73Plq.js.map} +1 -1
  24. package/dist/{admin-capabilities-BuigAgtm.js → admin-capabilities-BGv7oG8v.js} +2 -2
  25. package/dist/{admin-capabilities-BuigAgtm.js.map → admin-capabilities-BGv7oG8v.js.map} +1 -1
  26. package/dist/{admin-card-bzAks3-3.js → admin-card-DGbi6ZHZ.js} +2 -2
  27. package/dist/{admin-card-bzAks3-3.js.map → admin-card-DGbi6ZHZ.js.map} +1 -1
  28. package/dist/{admin-catalog-CK6CM9I2.js → admin-catalog-3pPEAuDY.js} +19 -19
  29. package/dist/{admin-catalog-CK6CM9I2.js.map → admin-catalog-3pPEAuDY.js.map} +1 -1
  30. package/dist/{admin-customers-D8u5gq3M.js → admin-customers-cnKMEV4q.js} +6 -6
  31. package/dist/{admin-customers-D8u5gq3M.js.map → admin-customers-cnKMEV4q.js.map} +1 -1
  32. package/dist/{admin-dashboard-DqqFjOzq.js → admin-dashboard-DfSsUyo-.js} +14 -14
  33. package/dist/{admin-dashboard-DqqFjOzq.js.map → admin-dashboard-DfSsUyo-.js.map} +1 -1
  34. package/dist/{admin-data-table-qfXLOFmN.js → admin-data-table-CgeWv__T.js} +6 -6
  35. package/dist/{admin-data-table-qfXLOFmN.js.map → admin-data-table-CgeWv__T.js.map} +1 -1
  36. package/dist/{admin-detail-X82kR2f7.js → admin-detail-BATuJjVs.js} +12 -12
  37. package/dist/{admin-detail-X82kR2f7.js.map → admin-detail-BATuJjVs.js.map} +1 -1
  38. package/dist/{admin-detail-DUAJQg8G.js → admin-detail-Cq59e14B.js} +15 -15
  39. package/dist/{admin-detail-DUAJQg8G.js.map → admin-detail-Cq59e14B.js.map} +1 -1
  40. package/dist/{admin-detail-BHe51ma9.js → admin-detail-DG-YaHhS.js} +11 -11
  41. package/dist/{admin-detail-BHe51ma9.js.map → admin-detail-DG-YaHhS.js.map} +1 -1
  42. package/dist/{admin-detail-CGOyqs7s.js → admin-detail-Dc7rU4mM.js} +15 -15
  43. package/dist/{admin-detail-CGOyqs7s.js.map → admin-detail-Dc7rU4mM.js.map} +1 -1
  44. package/dist/{admin-dialog-BjuKI5Hp.js → admin-dialog-Ffx95AIT.js} +3 -3
  45. package/dist/{admin-dialog-BjuKI5Hp.js.map → admin-dialog-Ffx95AIT.js.map} +1 -1
  46. package/dist/{admin-dom-uMmZzRvU.js → admin-dom-lnNSQ7ke.js} +4 -4
  47. package/dist/{admin-dom-uMmZzRvU.js.map → admin-dom-lnNSQ7ke.js.map} +1 -1
  48. package/dist/{admin-dropdown-menu-BW1D_h6s.js → admin-dropdown-menu-CCiW4-oz.js} +2 -2
  49. package/dist/{admin-dropdown-menu-BW1D_h6s.js.map → admin-dropdown-menu-CCiW4-oz.js.map} +1 -1
  50. package/dist/{admin-fact-card-DO_fHosg.js → admin-fact-card-D6mZgxpN.js} +2 -2
  51. package/dist/{admin-fact-card-DO_fHosg.js.map → admin-fact-card-D6mZgxpN.js.map} +1 -1
  52. package/dist/{admin-health-B4jN2LwR.js → admin-health-CvJX9prw.js} +13 -13
  53. package/dist/{admin-health-B4jN2LwR.js.map → admin-health-CvJX9prw.js.map} +1 -1
  54. package/dist/{admin-input-CcfQfJFN.js → admin-input-DO5lvCLL.js} +2 -2
  55. package/dist/{admin-input-CcfQfJFN.js.map → admin-input-DO5lvCLL.js.map} +1 -1
  56. package/dist/{admin-label-BiEN5cjb.js → admin-label-BzJpr3lg.js} +2 -2
  57. package/dist/{admin-label-BiEN5cjb.js.map → admin-label-BzJpr3lg.js.map} +1 -1
  58. package/dist/{admin-linked-table-row-BsaUruCN.js → admin-linked-table-row-5vFb6rXY.js} +4 -4
  59. package/dist/{admin-linked-table-row-BsaUruCN.js.map → admin-linked-table-row-5vFb6rXY.js.map} +1 -1
  60. package/dist/{admin-metering-COFcSPQy.js → admin-metering-BksTFRRP.js} +14 -14
  61. package/dist/{admin-metering-COFcSPQy.js.map → admin-metering-BksTFRRP.js.map} +1 -1
  62. package/dist/{admin-ops-B3mcr76u.js → admin-ops-Ch2-BmUp.js} +11 -11
  63. package/dist/{admin-ops-B3mcr76u.js.map → admin-ops-Ch2-BmUp.js.map} +1 -1
  64. package/dist/{admin-orders-dxC99Idl.js → admin-orders-8XzHf7b-.js} +8 -8
  65. package/dist/{admin-orders-dxC99Idl.js.map → admin-orders-8XzHf7b-.js.map} +1 -1
  66. package/dist/{admin-payments-Bs7HSfP0.js → admin-payments-pNLNIU0X.js} +9 -9
  67. package/dist/{admin-payments-Bs7HSfP0.js.map → admin-payments-pNLNIU0X.js.map} +1 -1
  68. package/dist/{admin-price-detail-DRquxpA9.js → admin-price-detail-BeGDPxKX.js} +11 -11
  69. package/dist/admin-price-detail-BeGDPxKX.js.map +1 -0
  70. package/dist/{admin-price-wizard-CI7K-2Nz.js → admin-price-wizard-ferZSTfO.js} +7 -7
  71. package/dist/{admin-price-wizard-CI7K-2Nz.js.map → admin-price-wizard-ferZSTfO.js.map} +1 -1
  72. package/dist/{admin-range-picker-Dr2M1EZr.js → admin-range-picker-DaIvC1oC.js} +5 -5
  73. package/dist/{admin-range-picker-Dr2M1EZr.js.map → admin-range-picker-DaIvC1oC.js.map} +1 -1
  74. package/dist/{admin-reports-CywKLiSA.js → admin-reports-CA-cnNur.js} +8 -8
  75. package/dist/{admin-reports-CywKLiSA.js.map → admin-reports-CA-cnNur.js.map} +1 -1
  76. package/dist/{admin-select-DBgprVW6.js → admin-select-CUXvh6j1.js} +2 -2
  77. package/dist/{admin-select-DBgprVW6.js.map → admin-select-CUXvh6j1.js.map} +1 -1
  78. package/dist/{admin-settings-Bmoy95uO.js → admin-settings-C6eWFkDn.js} +16 -16
  79. package/dist/{admin-settings-Bmoy95uO.js.map → admin-settings-C6eWFkDn.js.map} +1 -1
  80. package/dist/{admin-skeleton-DsM7crYi.js → admin-skeleton-DEY3Q8Dg.js} +2 -2
  81. package/dist/{admin-skeleton-DsM7crYi.js.map → admin-skeleton-DEY3Q8Dg.js.map} +1 -1
  82. package/dist/{admin-status-badge-BFPgo71d.js → admin-status-badge-CwqIU8tK.js} +2 -2
  83. package/dist/{admin-status-badge-BFPgo71d.js.map → admin-status-badge-CwqIU8tK.js.map} +1 -1
  84. package/dist/{admin-subscriptions-CLYc_HEV.js → admin-subscriptions-lJG_EzMe.js} +9 -9
  85. package/dist/{admin-subscriptions-CLYc_HEV.js.map → admin-subscriptions-lJG_EzMe.js.map} +1 -1
  86. package/dist/{admin-switch-BJUxLCsa.js → admin-switch-S4g_ppaU.js} +2 -2
  87. package/dist/{admin-switch-BJUxLCsa.js.map → admin-switch-S4g_ppaU.js.map} +1 -1
  88. package/dist/{admin-table-CH9TrXJf.js → admin-table-CWhiCb9d.js} +2 -2
  89. package/dist/{admin-table-CH9TrXJf.js.map → admin-table-CWhiCb9d.js.map} +1 -1
  90. package/dist/{admin-tabs-528FJMjt.js → admin-tabs-Cjm5a6UJ.js} +2 -2
  91. package/dist/{admin-tabs-528FJMjt.js.map → admin-tabs-Cjm5a6UJ.js.map} +1 -1
  92. package/dist/{admin-textarea-DEz38RaI.js → admin-textarea-DK1Fq31x.js} +2 -2
  93. package/dist/{admin-textarea-DEz38RaI.js.map → admin-textarea-DK1Fq31x.js.map} +1 -1
  94. package/dist/{admin-typed-confirm-dialog-DU7m9-O7.js → admin-typed-confirm-dialog-BloZvFPA.js} +6 -6
  95. package/dist/{admin-typed-confirm-dialog-DU7m9-O7.js.map → admin-typed-confirm-dialog-BloZvFPA.js.map} +1 -1
  96. package/dist/{admin-utils-BK4Vh1o_.js → admin-utils-DnVY5fYd.js} +3 -3
  97. package/dist/admin-utils-DnVY5fYd.js.map +1 -0
  98. package/dist/{admin-widget-viz-Da48c-Zf.js → admin-widget-viz-RCkxUspL.js} +8 -8
  99. package/dist/{admin-widget-viz-Da48c-Zf.js.map → admin-widget-viz-RCkxUspL.js.map} +1 -1
  100. package/dist/admin.js +31 -31
  101. package/dist/admin.js.map +1 -1
  102. package/dist/appearance.d.ts +7 -7
  103. package/dist/buy-button.d.ts +3 -3
  104. package/dist/cart.d.ts +4 -4
  105. package/dist/client/client.d.ts +4 -4
  106. package/dist/client/generated/error-codes.d.ts +1 -1
  107. package/dist/client/generated/routes.d.ts +4 -4
  108. package/dist/client/generated/wire.d.ts +37 -40
  109. package/dist/client/types.d.ts +12 -17
  110. package/dist/{client-rFrCMrkn.js → client-HWr09qpX.js} +11 -13
  111. package/dist/client-HWr09qpX.js.map +1 -0
  112. package/dist/client.js +1 -1
  113. package/dist/embedded-payment.d.ts +25 -0
  114. package/dist/{hooks-B1TffejB.js → hooks-D9MR20BY.js} +2 -2
  115. package/dist/hooks-D9MR20BY.js.map +1 -0
  116. package/dist/index.d.ts +4 -4
  117. package/dist/index.js +69 -69
  118. package/dist/index.js.map +1 -1
  119. package/dist/locales/de.js +1 -1
  120. package/dist/locales/de.js.map +1 -1
  121. package/dist/locales/en.d.ts +1 -1
  122. package/dist/locales/en.js +1 -1
  123. package/dist/locales/en.js.map +1 -1
  124. package/dist/locales/es.js +1 -1
  125. package/dist/locales/es.js.map +1 -1
  126. package/dist/locales/ja.js +1 -1
  127. package/dist/locales/ja.js.map +1 -1
  128. package/dist/locales/ko.js +1 -1
  129. package/dist/locales/ko.js.map +1 -1
  130. package/dist/locales/zh.js +1 -1
  131. package/dist/locales/zh.js.map +1 -1
  132. package/dist/modal.d.ts +8 -8
  133. package/dist/{order-checkout.d.ts → order-payment.d.ts} +4 -4
  134. package/dist/product-list.d.ts +3 -3
  135. package/dist/psp.d.ts +2 -2
  136. package/dist/react/provider.d.ts +3 -3
  137. package/dist/react.js +1 -1
  138. package/dist/save-payment-method.d.ts +2 -2
  139. package/dist/scope-context.d.ts +4 -4
  140. package/dist/scope.d.ts +2 -2
  141. package/dist/tokenized-card-form.d.ts +2 -2
  142. package/docs/payment-form-contract.md +3 -3
  143. package/package.json +2 -2
  144. package/dist/admin-price-detail-DRquxpA9.js.map +0 -1
  145. package/dist/admin-utils-BK4Vh1o_.js.map +0 -1
  146. package/dist/client-rFrCMrkn.js.map +0 -1
  147. package/dist/embedded-checkout.d.ts +0 -25
  148. package/dist/hooks-B1TffejB.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"admin-detail-DUAJQg8G.js","names":[],"sources":["../src/admin/pages/subscriptions/subscription-change-options.ts","../src/admin/pages/subscriptions/change-subscription-dialog.tsx","../src/admin/pages/subscriptions/detail.tsx"],"sourcesContent":["import type { Rail, SubscriptionStatus } from \"#orck/admin/lib/api/types\"\nimport type {\n Price,\n Product,\n ScheduledChange,\n} from \"#orck/client/generated/wire\"\nimport { formatNativeAmount } from \"#orck/admin/lib/format\"\nimport { priceIntervalLabel } from \"#orck/admin/pages/catalog/price-format\"\n\nexport interface SubscriptionChangeOption {\n direction: \"current\" | \"upgrade\" | \"downgrade\"\n price: Price\n product: Product\n}\n\nexport function subscriptionChangeOptionLabel(\n option: SubscriptionChangeOption\n): string {\n const price = option.price\n const amount = `${formatNativeAmount(price.unit_amount, price.currency)}${price.quantity ? \" per seat\" : \"\"}`\n return [\n option.product.display_name,\n option.direction,\n `${amount} ${priceIntervalLabel(price)}`,\n price.key,\n ].join(\" · \")\n}\n\n// The seats a change starts from: the subscription's when the price allows\n// them, otherwise the price's minimum.\nexport function initialSeats(\n price: Price,\n current: number | null\n): number | null {\n const bounds = price.quantity\n if (!bounds) return null\n if (current !== null && current >= bounds.min && current <= bounds.max) {\n return current\n }\n return bounds.min\n}\n\nexport function adminSubscriptionChangeBlockReason({\n rail,\n status,\n collectionPolicy,\n scheduledChange,\n}: {\n rail: Rail\n status: SubscriptionStatus\n collectionPolicy?: string\n scheduledChange?: Pick<ScheduledChange, \"source\"> | null\n}): string | undefined {\n if (status !== \"active\" && status !== \"past_due\") {\n return \"Only active or past-due subscriptions can change\"\n }\n // OpenRails changes back only the scheduled change it bills itself.\n if (scheduledChange && collectionPolicy !== \"engine\") {\n return \"Its provider already bills a scheduled change\"\n }\n if (rail === \"ccbill\") return \"CCBill changes require customer self-service\"\n if (rail === \"solana\") {\n return \"Solana changes require the customer's wallet signature\"\n }\n return undefined\n}\n\n// The changes the console offers: the current price, for its seats or to\n// change back from a scheduled change, then, unless a price migration is\n// pending, live recurring prices of the tier group in the same currency.\nexport function subscriptionChangeOptions({\n currentProduct,\n currentPrice,\n currentCurrency,\n products,\n prices,\n scheduledChange,\n}: {\n currentProduct?: Product\n currentPrice?: Price\n currentCurrency?: string\n products: Product[]\n prices: Price[]\n scheduledChange?: Pick<ScheduledChange, \"source\"> | null\n}): SubscriptionChangeOption[] {\n const current: SubscriptionChangeOption[] =\n currentProduct && currentPrice && (currentPrice.quantity || scheduledChange)\n ? [{ direction: \"current\", price: currentPrice, product: currentProduct }]\n : []\n const tierGroup = currentProduct?.tier_group?.trim()\n const currency = currentCurrency?.trim().toLowerCase()\n if (\n !currentProduct ||\n !tierGroup ||\n !currency ||\n scheduledChange?.source === \"migration\"\n ) {\n return current\n }\n\n const productsByID = new Map(\n products\n .filter(\n (product) =>\n !product.archived &&\n product.id !== currentProduct.id &&\n product.tier_group?.trim() === tierGroup\n )\n .map((product) => [product.id, product])\n )\n\n return current.concat(\n prices\n .flatMap((price): SubscriptionChangeOption[] => {\n const product = productsByID.get(price.product_id)\n if (\n !product ||\n price.archived ||\n !price.billing_interval_hours ||\n price.currency.trim().toLowerCase() !== currency\n ) {\n return []\n }\n return [\n {\n direction:\n product.tier_rank < currentProduct.tier_rank\n ? \"downgrade\"\n : \"upgrade\",\n price,\n product,\n },\n ]\n })\n .sort(\n (left, right) =>\n left.product.tier_rank - right.product.tier_rank ||\n left.product.display_name.localeCompare(right.product.display_name) ||\n left.price.id.localeCompare(right.price.id)\n )\n )\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport * as React from \"react\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"#orck/admin/components/ui/dialog\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"#orck/admin/components/ui/select\"\nimport type {\n ChangeSubscriptionParams,\n Rail,\n ScheduledChange,\n SubscriptionStatus,\n} from \"#orck/admin/lib/api/types\"\nimport { ApiError } from \"#orck/admin/lib/api/client\"\nimport { DIALOG_WIDE } from \"#orck/admin/lib/dialog-width\"\nimport { formatDate, formatNativeAmount } from \"#orck/admin/lib/format\"\n\nimport {\n adminSubscriptionChangeBlockReason,\n initialSeats,\n subscriptionChangeOptionLabel,\n subscriptionChangeOptions,\n} from \"#orck/admin/pages/subscriptions/subscription-change-options\"\n\ninterface ChangeSubscriptionDialogProps {\n subscriptionId: string\n customerId?: string\n productId: string\n priceId: string\n quantity: number | null\n currency?: string\n collectionPolicy?: string\n scheduledChange?: ScheduledChange | null\n rail: Rail\n status: SubscriptionStatus\n}\n\nexport function ChangeSubscriptionDialog(props: ChangeSubscriptionDialogProps) {\n const { selectedMerchant } = useAdminServices()\n\n return (\n <ChangeSubscriptionForm\n key={`${selectedMerchant() ?? \"\"}:${props.subscriptionId}`}\n {...props}\n />\n )\n}\n\nfunction ChangeSubscriptionForm({\n subscriptionId,\n customerId,\n productId,\n priceId,\n quantity,\n currency,\n collectionPolicy,\n scheduledChange,\n rail,\n status,\n}: ChangeSubscriptionDialogProps) {\n const { toast, toastApiError, adminMutations, adminQueries } =\n useAdminServices()\n\n const { id: adminId, text: adminText } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const [selectedPriceId, setSelectedPriceId] = React.useState(\"\")\n const [seats, setSeats] = React.useState(\"\")\n const [reason, setReason] = React.useState(\"\")\n const [reviewedKey, setReviewedKey] = React.useState(\"\")\n // A dismissed dialog or another preview cannot establish non-execution.\n // Retain each submitted request's key until its outcome is definitive.\n const attempts = React.useRef(new Map<string, string>())\n const view = React.useRef(0)\n React.useEffect(\n () => () => {\n view.current++\n },\n []\n )\n const queryClient = useQueryClient()\n const preview = useMutation(\n adminMutations.previewSubscriptionChange(subscriptionId)\n )\n const change = useMutation(\n adminMutations.changeSubscription(queryClient, subscriptionId, customerId)\n )\n const productsQuery = useQuery({\n ...adminQueries.allProducts({ errorAction: \"Load subscription plans\" }),\n enabled: open,\n })\n const pricesQuery = useQuery({\n ...adminQueries.allPrices({ errorAction: \"Load subscription prices\" }),\n enabled: open,\n })\n\n const products = productsQuery.data?.data ?? []\n const prices = pricesQuery.data?.data ?? []\n const currentProduct = products.find((product) => product.id === productId)\n const currentPrice = prices.find((price) => price.id === priceId)\n const options = subscriptionChangeOptions({\n currentProduct,\n currentPrice,\n currentCurrency: currency ?? currentPrice?.currency,\n products,\n prices,\n scheduledChange,\n })\n const selected = options.find((option) => option.price.id === selectedPriceId)\n const bounds = selected?.price.quantity\n const seatCount = Number(seats)\n const seatsValid =\n !bounds ||\n (Number.isInteger(seatCount) &&\n seatCount >= bounds.min &&\n seatCount <= bounds.max)\n // The current price with its seats changes back from a scheduled change.\n const request: ChangeSubscriptionParams | undefined =\n selected && seatsValid\n ? {\n price_id: selected.price.id,\n ...(bounds ? { quantity: seatCount } : {}),\n }\n : undefined\n const unchanged =\n selected?.direction === \"current\" &&\n !scheduledChange &&\n (!bounds || seatCount === quantity)\n const requestKey = request ? JSON.stringify(request) : \"\"\n const reviewed =\n requestKey && reviewedKey === requestKey ? preview.data : undefined\n const blockReason = adminSubscriptionChangeBlockReason({\n rail,\n status,\n collectionPolicy,\n scheduledChange,\n })\n\n const handleOpenChange = (next: boolean) => {\n view.current++\n setOpen(next)\n }\n\n const handleSelect = (value: string | null) => {\n view.current++\n const price = options.find((option) => option.price.id === value)?.price\n setSelectedPriceId(value ?? \"\")\n setSeats(String(price ? (initialSeats(price, quantity) ?? \"\") : \"\"))\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n\n const handleSeats = (value: string) => {\n view.current++\n setSeats(value)\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n\n const previewError =\n preview.error instanceof Error ? preview.error.message : \"\"\n const changeError = change.error instanceof Error ? change.error.message : \"\"\n const responseMessage = change.data?.message\n const responseURL = change.data?.next_action?.url ?? undefined\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogTrigger\n render={\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={Boolean(blockReason) && !change.variables}\n title={blockReason}\n >\n <AdminMessage id={\"Change subscription\"} />\n </Button>\n }\n />\n <DialogContent className={DIALOG_WIDE}>\n <DialogHeader>\n <DialogTitle>\n <AdminMessage id={\"Change subscription\"} />\n </DialogTitle>\n <DialogDescription>\n <AdminMessage\n id={\"Schedule the customer's plan or seats for the next renewal. No card is charged now. Choosing the current plan and seats clears a pending change. The customer is told.\"}\n />\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"grid gap-5\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-tier\")}>\n <AdminMessage id={\"New plan\"} />\n </Label>\n <Select value={selectedPriceId} onValueChange={handleSelect}>\n <SelectTrigger\n id={adminId(\"subscription-tier\")}\n className=\"w-full\"\n disabled={productsQuery.isPending || pricesQuery.isPending}\n >\n <SelectValue\n placeholder={\n productsQuery.isPending || pricesQuery.isPending\n ? \"Loading plans…\"\n : \"Choose a plan\"\n }\n />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.price.id} value={option.price.id}>\n {subscriptionChangeOptionLabel(option)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {!productsQuery.isPending &&\n !pricesQuery.isPending &&\n !productsQuery.isError &&\n !pricesQuery.isError &&\n options.length === 0 && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n \"No eligible recurring plans share this tier group and currency.\"\n }\n />\n </p>\n )}\n {(productsQuery.isError || pricesQuery.isError) && (\n <p className=\"text-xs text-destructive\" role=\"alert\">\n <AdminMessage id={\"Could not load the available plans.\"} />\n </p>\n )}\n </div>\n\n {bounds && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-seats\")}>\n <AdminMessage id={\"Seats\"} />\n </Label>\n <Input\n id={adminId(\"subscription-seats\")}\n type=\"number\"\n inputMode=\"numeric\"\n min={bounds.min}\n max={bounds.max}\n value={seats}\n onChange={(event) => handleSeats(event.target.value)}\n />\n <p className=\"text-xs text-muted-foreground\">\n {bounds.min}\n <AdminMessage id={\" to \"} />\n {bounds.max}\n <AdminMessage id={\" seats.\"} />\n </p>\n </div>\n )}\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-change-reason\")}>\n <AdminMessage id={\"Reason\"} />\n </Label>\n <Input\n id={adminId(\"subscription-change-reason\")}\n value={reason}\n maxLength={500}\n placeholder={adminText(\"What the customer asked for\")}\n onChange={(event) => setReason(event.target.value)}\n />\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Kept with the scheduled change.\"} />\n </p>\n </div>\n\n {reviewed && selected && (\n <div className=\"grid gap-3\" aria-live=\"polite\">\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-sm font-medium\">\n <AdminMessage id={\"Review\"} />\n </span>\n <Badge variant=\"secondary\">\n {reviewed.effective === \"now\" ? \"Immediate\" : \"At renewal\"}\n </Badge>\n </div>\n <dl className=\"grid grid-cols-2 gap-x-8 gap-y-3 border-y py-4 text-sm\">\n {reviewed.quantity !== null && (\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Seats\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {reviewed.quantity}\n </dd>\n </div>\n )}\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Due now\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatNativeAmount(\n reviewed.amount_due_now,\n reviewed.currency\n )}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Next charge\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatNativeAmount(\n reviewed.next_charge_amount,\n reviewed.currency\n )}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Effective\"} />\n </dt>\n <dd className=\"font-medium\">\n {reviewed.effective === \"now\"\n ? \"Immediately\"\n : formatDate(reviewed.next_charge_date)}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Next billing date\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatDate(reviewed.next_charge_date)}\n </dd>\n </div>\n </dl>\n {reviewed.is_estimate && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n \"The payment provider calculates the final prorated amount.\"\n }\n />\n </p>\n )}\n </div>\n )}\n\n {(previewError || changeError) && (\n <p className=\"text-sm text-destructive\" role=\"alert\">\n {changeError || previewError}\n </p>\n )}\n\n {change.data && change.data.status !== \"succeeded\" && (\n <div\n className=\"grid gap-2 rounded-lg bg-muted px-3 py-2.5 text-sm\"\n aria-live=\"polite\"\n >\n <p>{responseMessage ?? \"This change needs another step.\"}</p>\n {responseURL && (\n <a\n href={responseURL}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"w-fit font-medium text-primary underline underline-offset-4\"\n >\n <AdminMessage id={\"Continue with payment provider\"} />\n </a>\n )}\n </div>\n )}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => handleOpenChange(false)}\n >\n <AdminMessage id={\"Cancel\"} />\n </Button>\n {!reviewed ? (\n <Button\n type=\"button\"\n disabled={!request || unchanged || preview.isPending}\n onClick={async () => {\n if (!request) return\n const currentView = view.current\n try {\n await preview.mutateAsync(request)\n if (view.current !== currentView) return\n setReviewedKey(requestKey)\n } catch (error) {\n if (view.current === currentView) {\n toastApiError(error, \"Preview subscription change\")\n }\n }\n }}\n >\n {preview.isPending ? \"Reviewing…\" : \"Review change\"}\n </Button>\n ) : (\n <Button\n type=\"button\"\n disabled={\n change.isPending ||\n !reason.trim() ||\n (Boolean(change.data) && change.data?.status !== \"processing\")\n }\n onClick={async () => {\n if (!request) return\n const currentView = view.current\n const changeKey =\n attempts.current.get(requestKey) ?? crypto.randomUUID()\n attempts.current.set(requestKey, changeKey)\n const completeAttempt = () => {\n if (attempts.current.get(requestKey) === changeKey) {\n attempts.current.delete(requestKey)\n }\n }\n try {\n const result = await change.mutateAsync({\n change: { ...request, reason: reason.trim() },\n idempotencyKey: changeKey,\n })\n if (\n result.status === \"succeeded\" ||\n result.status === \"blocked\"\n ) {\n completeAttempt()\n }\n if (view.current !== currentView) return\n if (result.status === \"succeeded\") {\n toast.success(\n result.effective === \"now\"\n ? \"Subscription changed\"\n : \"Change scheduled for the next renewal\"\n )\n handleOpenChange(false)\n setSelectedPriceId(\"\")\n setSeats(\"\")\n setReason(\"\")\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n if (result.status === \"processing\") {\n toast.info(\n \"The provider is still confirming this change. Check again to read the result.\"\n )\n }\n } catch (error) {\n // 402 is a final provider refusal regardless of its code.\n // Other refusals can reject a readback of an already accepted\n // operation, so retire only explicitly terminal outcomes.\n if (\n error instanceof ApiError &&\n (error.status === 402 ||\n (error.status === 409 &&\n (error.code === \"subscription_change_refused\" ||\n error.code ===\n \"subscription_change_idempotency_conflict\")))\n ) {\n completeAttempt()\n }\n if (view.current === currentView) {\n toastApiError(error, \"Change subscription\")\n }\n }\n }}\n >\n {change.isPending\n ? \"Applying…\"\n : change.data\n ? change.data.status === \"processing\"\n ? \"Check result\"\n : change.data.status === \"blocked\"\n ? \"Change blocked\"\n : \"Action required\"\n : \"Confirm change\"}\n </Button>\n )}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport { ArrowLeft01Icon } from \"@hugeicons/core-free-icons\"\nimport * as React from \"react\"\nimport { Link, useNavigate, useParams } from \"#orck/admin/router\"\n\nimport { useForm } from \"@tanstack/react-form\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Fact } from \"#orck/admin/components/fact-card\"\nimport { FormFieldErrors } from \"#orck/admin/components/form-field-errors\"\nimport { StatusBadge } from \"#orck/admin/components/status-badge\"\nimport { TypedConfirmDialog } from \"#orck/admin/components/typed-confirm-dialog\"\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"#orck/admin/components/ui/dialog\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"#orck/admin/components/ui/select\"\nimport { Switch } from \"#orck/admin/components/ui/switch\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport type { ScheduledChange } from \"#orck/admin/lib/api/types\"\nimport { DIALOG_FORM } from \"#orck/admin/lib/dialog-width\"\nimport {\n formatCard,\n formatDate,\n formatNativeAmount,\n shortId,\n} from \"#orck/admin/lib/format\"\n\nimport { ChangeSubscriptionDialog } from \"#orck/admin/pages/subscriptions/change-subscription-dialog\"\nimport { dunningSummary } from \"#orck/admin/pages/subscriptions/dunning\"\nimport { useAdminUpdates } from \"#orck/admin/lib/capabilities\"\n\nexport function SubscriptionDetailPage() {\n const { text: adminText } = useAdminUI()\n\n const { adminQueries } = useAdminServices()\n\n const canUpdate = useAdminUpdates()\n const { id = \"\" } = useParams()\n const navigate = useNavigate()\n const { data: sub, isPending: loading } = useQuery(\n adminQueries.subscription(id)\n )\n const { data: paymentPage } = useQuery(\n adminQueries.payments({ subscription_id: id }, 20)\n )\n const payments = paymentPage?.data ?? []\n if (loading)\n return (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"Loading…\"} />\n </p>\n )\n if (!sub)\n return (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"Subscription not found.\"} />\n </p>\n )\n\n const cancellable =\n sub.status === \"active\" ||\n sub.status === \"past_due\" ||\n sub.status === \"awaiting_method\" ||\n sub.status === \"unverified\"\n const resumable = sub.status === \"canceled\" || sub.status === \"past_due\"\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => navigate(-1)}\n aria-label={adminText(\"Back\")}\n >\n <HugeiconsIcon icon={ArrowLeft01Icon} className=\"size-4\" />\n </Button>\n <div>\n <h2 className=\"flex items-center gap-2 text-sm\">\n {sub.id} <StatusBadge status={sub.status} />\n </h2>\n <p className=\"text-xs text-muted-foreground\">\n {sub.rail} · {sub.rail_subscription_id || \"no rail id\"}\n </p>\n </div>\n <div className=\"ml-auto flex gap-2\">\n {canUpdate && resumable && (\n <ResumeButton id={sub.id} customerId={sub.customer_id} />\n )}\n {canUpdate && (\n <ChangeSubscriptionDialog\n subscriptionId={sub.id}\n customerId={sub.customer_id}\n productId={sub.product_id}\n priceId={sub.price_id}\n quantity={sub.quantity}\n currency={sub.price?.currency}\n collectionPolicy={sub.collection_policy}\n scheduledChange={sub.scheduled_change}\n rail={sub.rail}\n status={sub.status}\n />\n )}\n {canUpdate && (\n <ChangePaymentMethodDialog\n subscriptionId={sub.id}\n customerId={sub.customer_id}\n rail={sub.rail}\n collectionPolicy={sub.collection_policy}\n />\n )}\n {canUpdate && cancellable && (\n <CancelDialog id={sub.id} customerId={sub.customer_id} />\n )}\n </div>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <Fact label={adminText(\"Customer\")}>\n {sub.customer_id ? (\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/customers/${sub.customer_id}`}\n >\n {shortId(sub.customer_id, 13)}\n </Link>\n ) : (\n \"—\"\n )}\n </Fact>\n <Fact label={adminText(\"Started\")}>{formatDate(sub.started_at)}</Fact>\n <Fact label={adminText(\"Current period\")}>\n {formatDate(sub.current_period_starts_at)} →{\" \"}\n {formatDate(sub.current_period_ends_at)}\n </Fact>\n <Fact label={adminText(\"Price\")}>\n <div className=\"flex flex-col gap-1\">\n <span className=\"flex items-center gap-2\">\n {sub.price?.unit_amount !== undefined && sub.price?.currency ? (\n <Link\n className=\"underline-offset-2 hover:underline\"\n to={`/catalog/prices/${encodeURIComponent(sub.price_id)}`}\n >\n {formatNativeAmount(\n sub.price.unit_amount,\n sub.price.currency\n )}\n </Link>\n ) : (\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/catalog/prices/${encodeURIComponent(sub.price_id)}`}\n >\n {shortId(sub.price_id ?? \"—\", 13)}\n </Link>\n )}\n {sub.price?.archived && (\n <Badge\n variant=\"secondary\"\n title={adminText(\"Pinned to an archived (prior) version\")}\n >\n <AdminMessage id={\"prior version\"} />\n </Badge>\n )}\n </span>\n {sub.price?.key && (\n <span className=\"text-xs text-muted-foreground\">\n {sub.price.key}\n </span>\n )}\n {sub.scheduled_change && (\n <ScheduledChangeBadge change={sub.scheduled_change} />\n )}\n </div>\n </Fact>\n {sub.quantity !== null && (\n <Fact label={adminText(\"Seats\")}>\n {sub.quantity}\n {sub.scheduled_change?.quantity != null &&\n ` → ${sub.scheduled_change.quantity} at renewal`}\n </Fact>\n )}\n <Fact label={adminText(\"Dunning\")}>\n {sub.dunning ? dunningSummary(sub.dunning) : \"—\"}\n </Fact>\n <Fact\n label={\n sub.dunning?.waiting_for_new_card ? \"Card deadline\" : \"Final retry\"\n }\n >\n {formatDate(sub.dunning?.final_retry_at)}\n </Fact>\n <Fact label={adminText(\"Last decline\")}>\n {sub.dunning?.last_failure_reason ?? \"—\"}\n </Fact>\n <Fact label={adminText(\"Canceled\")}>\n {sub.canceled_at\n ? `${formatDate(sub.canceled_at)} (${sub.cancel_type ?? \"?\"})`\n : \"—\"}\n </Fact>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Payments\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {!payments.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"No payments recorded.\"} />\n </p>\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Payment\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Status\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Kind\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Amount\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Created\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {payments.map((p) => (\n <TableRow key={p.id}>\n <TableCell>\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/payments/${p.id}`}\n >\n {shortId(p.id, 13)}\n </Link>\n </TableCell>\n <TableCell>\n <StatusBadge status={p.status} />\n </TableCell>\n <TableCell>{p.kind}</TableCell>\n <TableCell>\n {formatNativeAmount(p.amount, p.currency)}\n </TableCell>\n <TableCell>{formatDate(p.created_at)}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </CardContent>\n </Card>\n </div>\n )\n}\n\nfunction CancelDialog({ id, customerId }: { id: string; customerId?: string }) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const { text: adminText, id: adminId } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const queryClient = useQueryClient()\n const cancel = useMutation(\n adminMutations.cancelSubscription(queryClient, id, customerId)\n )\n const form = useForm({\n defaultValues: { reason: \"\", revokeAccess: false },\n })\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next)\n if (!next) {\n form.reset()\n cancel.reset()\n }\n }\n\n return (\n <>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => setOpen(true)}>\n <AdminMessage id={\"Cancel subscription\"} />\n </Button>\n <TypedConfirmDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={adminText(\"Cancel subscription\")}\n description={adminText(\n \"Terminal cancellation at the payment rail. This is a last resort. Dunning parks subscriptions as past_due without losing entitlements.\"\n )}\n confirmationWord=\"CANCEL\"\n actionLabel=\"Cancel subscription\"\n onConfirm={async () => {\n try {\n await cancel.mutateAsync(form.state.values)\n toast.success(\"Subscription canceled\")\n } catch (err) {\n toastApiError(err, \"Cancel subscription\")\n throw err\n }\n }}\n >\n <div className=\"grid gap-3\">\n <form.Field name=\"reason\">\n {(field) => (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"cancel-reason\")}>\n <AdminMessage id={\"Reason\"} />\n </Label>\n <Input\n id={adminId(\"cancel-reason\")}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(event) => field.handleChange(event.target.value)}\n placeholder={adminText(\"why is this being canceled?\")}\n />\n </div>\n )}\n </form.Field>\n <form.Field name=\"revokeAccess\">\n {(field) => (\n <div className=\"flex items-center gap-2\">\n <Switch\n id={adminId(\"cancel-revoke\")}\n checked={field.state.value}\n onCheckedChange={field.handleChange}\n />\n <Label htmlFor={adminId(\"cancel-revoke\")}>\n <AdminMessage id={\"Also revoke access immediately\"} />\n </Label>\n </div>\n )}\n </form.Field>\n </div>\n </TypedConfirmDialog>\n </>\n )\n}\n\nfunction ResumeButton({ id, customerId }: { id: string; customerId?: string }) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const queryClient = useQueryClient()\n const resume = useMutation(\n adminMutations.resumeSubscription(queryClient, id, customerId)\n )\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={resume.isPending}\n onClick={async () => {\n try {\n await resume.mutateAsync()\n toast.success(\"Resume queued\")\n } catch (err) {\n toastApiError(err, \"Resume subscription\")\n }\n }}\n >\n {resume.isPending ? \"Queuing…\" : \"Resume\"}\n </Button>\n )\n}\n\n// The choice that makes the subscription follow the customer's default card.\nconst FOLLOW_DEFAULT = \"default\"\n\nfunction ChangePaymentMethodDialog({\n subscriptionId,\n customerId,\n rail,\n collectionPolicy,\n}: {\n subscriptionId: string\n customerId?: string\n rail: string\n collectionPolicy?: string\n}) {\n const { toast, toastApiError, adminMutations, adminQueries } =\n useAdminServices()\n\n const { id: adminId, text: adminText } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const queryClient = useQueryClient()\n const changePaymentMethod = useMutation(\n adminMutations.changeSubscriptionPaymentMethod(\n queryClient,\n subscriptionId,\n customerId\n )\n )\n const { data: pms } = useQuery(\n adminQueries.customerPaymentMethods(open ? customerId : undefined)\n )\n const form = useForm({\n defaultValues: { paymentMethodId: \"\" },\n onSubmit: async ({ value }) => {\n try {\n await changePaymentMethod.mutateAsync(\n value.paymentMethodId === FOLLOW_DEFAULT\n ? null\n : value.paymentMethodId\n )\n toast.success(\"Payment method updated\")\n handleOpenChange(false)\n } catch (err) {\n toastApiError(err, \"Change payment method\")\n }\n },\n })\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next)\n if (!next) {\n form.reset()\n changePaymentMethod.reset()\n }\n }\n\n // A card subscription OpenRails collects, or an NMI schedule; a provider\n // that keeps the card (Stripe-owned, CCBill) or a wallet has none to change.\n const supported =\n rail !== \"solana\" &&\n (collectionPolicy === \"engine\" || collectionPolicy === \"nmi_schedule\")\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogTrigger\n render={\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!supported}\n title={\n supported\n ? undefined\n : `Payment-method change is not supported on ${rail}`\n }\n >\n <AdminMessage id={\"Change payment method\"} />\n </Button>\n }\n />\n <DialogContent className={DIALOG_FORM}>\n <DialogHeader>\n <DialogTitle>\n <AdminMessage id={\"Change payment method\"} />\n </DialogTitle>\n <DialogDescription>\n <AdminMessage\n id={\n \"Points future renewals of this subscription at another of the customer&apos;s stored cards (same rail), or back at their default card for its currency.\"\n }\n />\n </DialogDescription>\n </DialogHeader>\n <form\n onSubmit={(event) => {\n event.preventDefault()\n event.stopPropagation()\n void form.handleSubmit()\n }}\n className=\"grid gap-4\"\n >\n <form.Field\n name=\"paymentMethodId\"\n validators={{\n onChange: ({ value }) =>\n value ? undefined : \"Pick a stored payment method\",\n }}\n >\n {(field) => (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-payment-method\")}>\n <AdminMessage id={\"Payment method\"} />\n </Label>\n <Select\n value={field.state.value}\n onValueChange={(value) => field.handleChange(value ?? \"\")}\n >\n <SelectTrigger\n className=\"w-full\"\n id={adminId(\"subscription-payment-method\")}\n aria-invalid={field.state.meta.errors.length > 0}\n >\n <SelectValue\n placeholder={adminText(\"Pick a stored payment method\")}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={FOLLOW_DEFAULT}>\n <AdminMessage id={\"The customer&apos;s default card\"} />\n </SelectItem>\n {(pms ?? [])\n .filter((pm) => pm.rail === rail)\n .map((pm) => (\n <SelectItem key={pm.id} value={pm.id}>\n {formatCard(pm.card)} ({pm.rail})\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <FormFieldErrors errors={field.state.meta.errors} />\n </div>\n )}\n </form.Field>\n <DialogFooter>\n <form.Subscribe\n selector={(state) =>\n [\n state.values.paymentMethodId,\n state.canSubmit,\n state.isSubmitting,\n ] as const\n }\n >\n {([paymentMethodId, canSubmit, isSubmitting]) => (\n <Button\n type=\"submit\"\n disabled={!paymentMethodId || !canSubmit || isSubmitting}\n >\n {isSubmitting ? \"Updating…\" : \"Update\"}\n </Button>\n )}\n </form.Subscribe>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n\n// ScheduledChangeBadge shows the change waiting for the next renewal: a price\n// migration's move or a scheduled downgrade. A change back to the current\n// price clears it.\nfunction ScheduledChangeBadge({ change }: { change: ScheduledChange }) {\n const { adminQueries } = useAdminServices()\n\n const { data: toPrice } = useQuery(adminQueries.price(change.price_id))\n return (\n <Badge className=\"bg-held-surface text-held\">\n {change.source === \"migration\" ? \"migrates\" : \"changes\"}\n <AdminMessage id={\" to\"} />{\" \"}\n {toPrice\n ? formatNativeAmount(toPrice.unit_amount, toPrice.currency)\n : shortId(change.price_id, 9)}{\" \"}\n <AdminMessage id={\"at the first renewal from \"} />\n {formatDate(change.effective_at)}\n </Badge>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"admin-detail-Cq59e14B.js","names":[],"sources":["../src/admin/pages/subscriptions/subscription-change-options.ts","../src/admin/pages/subscriptions/change-subscription-dialog.tsx","../src/admin/pages/subscriptions/detail.tsx"],"sourcesContent":["import type { Rail, SubscriptionStatus } from \"#orck/admin/lib/api/types\"\nimport type {\n Price,\n Product,\n ScheduledChange,\n} from \"#orck/client/generated/wire\"\nimport { formatNativeAmount } from \"#orck/admin/lib/format\"\nimport { priceIntervalLabel } from \"#orck/admin/pages/catalog/price-format\"\n\nexport interface SubscriptionChangeOption {\n direction: \"current\" | \"upgrade\" | \"downgrade\"\n price: Price\n product: Product\n}\n\nexport function subscriptionChangeOptionLabel(\n option: SubscriptionChangeOption\n): string {\n const price = option.price\n const amount = `${formatNativeAmount(price.unit_amount, price.currency)}${price.quantity ? \" per seat\" : \"\"}`\n return [\n option.product.display_name,\n option.direction,\n `${amount} ${priceIntervalLabel(price)}`,\n price.key,\n ].join(\" · \")\n}\n\n// The seats a change starts from: the subscription's when the price allows\n// them, otherwise the price's minimum.\nexport function initialSeats(\n price: Price,\n current: number | null\n): number | null {\n const bounds = price.quantity\n if (!bounds) return null\n if (current !== null && current >= bounds.min && current <= bounds.max) {\n return current\n }\n return bounds.min\n}\n\nexport function adminSubscriptionChangeBlockReason({\n rail,\n status,\n collectionPolicy,\n scheduledChange,\n}: {\n rail: Rail\n status: SubscriptionStatus\n collectionPolicy?: string\n scheduledChange?: Pick<ScheduledChange, \"source\"> | null\n}): string | undefined {\n if (status !== \"active\" && status !== \"past_due\") {\n return \"Only active or past-due subscriptions can change\"\n }\n // OpenRails changes back only the scheduled change it bills itself.\n if (scheduledChange && collectionPolicy !== \"engine\") {\n return \"Its provider already bills a scheduled change\"\n }\n if (rail === \"ccbill\") return \"CCBill changes require customer self-service\"\n if (rail === \"solana\") {\n return \"Solana changes require the customer's wallet signature\"\n }\n return undefined\n}\n\n// The changes the console offers: the current price, for its seats or to\n// change back from a scheduled change, then, unless a price migration is\n// pending, live recurring prices of the tier group in the same currency.\nexport function subscriptionChangeOptions({\n currentProduct,\n currentPrice,\n currentCurrency,\n products,\n prices,\n scheduledChange,\n}: {\n currentProduct?: Product\n currentPrice?: Price\n currentCurrency?: string\n products: Product[]\n prices: Price[]\n scheduledChange?: Pick<ScheduledChange, \"source\"> | null\n}): SubscriptionChangeOption[] {\n const current: SubscriptionChangeOption[] =\n currentProduct && currentPrice && (currentPrice.quantity || scheduledChange)\n ? [{ direction: \"current\", price: currentPrice, product: currentProduct }]\n : []\n const tierGroup = currentProduct?.tier_group?.trim()\n const currency = currentCurrency?.trim().toLowerCase()\n if (\n !currentProduct ||\n !tierGroup ||\n !currency ||\n scheduledChange?.source === \"migration\"\n ) {\n return current\n }\n\n const productsByID = new Map(\n products\n .filter(\n (product) =>\n !product.archived &&\n product.id !== currentProduct.id &&\n product.tier_group?.trim() === tierGroup\n )\n .map((product) => [product.id, product])\n )\n\n return current.concat(\n prices\n .flatMap((price): SubscriptionChangeOption[] => {\n const product = productsByID.get(price.product_id)\n if (\n !product ||\n price.archived ||\n !price.billing_interval_hours ||\n price.currency.trim().toLowerCase() !== currency\n ) {\n return []\n }\n return [\n {\n direction:\n product.tier_rank < currentProduct.tier_rank\n ? \"downgrade\"\n : \"upgrade\",\n price,\n product,\n },\n ]\n })\n .sort(\n (left, right) =>\n left.product.tier_rank - right.product.tier_rank ||\n left.product.display_name.localeCompare(right.product.display_name) ||\n left.price.id.localeCompare(right.price.id)\n )\n )\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport * as React from \"react\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"#orck/admin/components/ui/dialog\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"#orck/admin/components/ui/select\"\nimport type {\n ChangeSubscriptionParams,\n Rail,\n ScheduledChange,\n SubscriptionStatus,\n} from \"#orck/admin/lib/api/types\"\nimport { ApiError } from \"#orck/admin/lib/api/client\"\nimport { DIALOG_WIDE } from \"#orck/admin/lib/dialog-width\"\nimport { formatDate, formatNativeAmount } from \"#orck/admin/lib/format\"\n\nimport {\n adminSubscriptionChangeBlockReason,\n initialSeats,\n subscriptionChangeOptionLabel,\n subscriptionChangeOptions,\n} from \"#orck/admin/pages/subscriptions/subscription-change-options\"\n\ninterface ChangeSubscriptionDialogProps {\n subscriptionId: string\n customerId?: string\n productId: string\n priceId: string\n quantity: number | null\n currency?: string\n collectionPolicy?: string\n scheduledChange?: ScheduledChange | null\n rail: Rail\n status: SubscriptionStatus\n}\n\nexport function ChangeSubscriptionDialog(props: ChangeSubscriptionDialogProps) {\n const { selectedMerchant } = useAdminServices()\n\n return (\n <ChangeSubscriptionForm\n key={`${selectedMerchant() ?? \"\"}:${props.subscriptionId}`}\n {...props}\n />\n )\n}\n\nfunction ChangeSubscriptionForm({\n subscriptionId,\n customerId,\n productId,\n priceId,\n quantity,\n currency,\n collectionPolicy,\n scheduledChange,\n rail,\n status,\n}: ChangeSubscriptionDialogProps) {\n const { toast, toastApiError, adminMutations, adminQueries } =\n useAdminServices()\n\n const { id: adminId, text: adminText } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const [selectedPriceId, setSelectedPriceId] = React.useState(\"\")\n const [seats, setSeats] = React.useState(\"\")\n const [reason, setReason] = React.useState(\"\")\n const [reviewedKey, setReviewedKey] = React.useState(\"\")\n // A dismissed dialog or another preview cannot establish non-execution.\n // Retain each submitted request's key until its outcome is definitive.\n const attempts = React.useRef(new Map<string, string>())\n const view = React.useRef(0)\n React.useEffect(\n () => () => {\n view.current++\n },\n []\n )\n const queryClient = useQueryClient()\n const preview = useMutation(\n adminMutations.previewSubscriptionChange(subscriptionId)\n )\n const change = useMutation(\n adminMutations.changeSubscription(queryClient, subscriptionId, customerId)\n )\n const productsQuery = useQuery({\n ...adminQueries.allProducts({ errorAction: \"Load subscription plans\" }),\n enabled: open,\n })\n const pricesQuery = useQuery({\n ...adminQueries.allPrices({ errorAction: \"Load subscription prices\" }),\n enabled: open,\n })\n\n const products = productsQuery.data?.data ?? []\n const prices = pricesQuery.data?.data ?? []\n const currentProduct = products.find((product) => product.id === productId)\n const currentPrice = prices.find((price) => price.id === priceId)\n const options = subscriptionChangeOptions({\n currentProduct,\n currentPrice,\n currentCurrency: currency ?? currentPrice?.currency,\n products,\n prices,\n scheduledChange,\n })\n const selected = options.find((option) => option.price.id === selectedPriceId)\n const bounds = selected?.price.quantity\n const seatCount = Number(seats)\n const seatsValid =\n !bounds ||\n (Number.isInteger(seatCount) &&\n seatCount >= bounds.min &&\n seatCount <= bounds.max)\n // The current price with its seats changes back from a scheduled change.\n const request: ChangeSubscriptionParams | undefined =\n selected && seatsValid\n ? {\n price_id: selected.price.id,\n ...(bounds ? { quantity: seatCount } : {}),\n }\n : undefined\n const unchanged =\n selected?.direction === \"current\" &&\n !scheduledChange &&\n (!bounds || seatCount === quantity)\n const requestKey = request ? JSON.stringify(request) : \"\"\n const reviewed =\n requestKey && reviewedKey === requestKey ? preview.data : undefined\n const blockReason = adminSubscriptionChangeBlockReason({\n rail,\n status,\n collectionPolicy,\n scheduledChange,\n })\n\n const handleOpenChange = (next: boolean) => {\n view.current++\n setOpen(next)\n }\n\n const handleSelect = (value: string | null) => {\n view.current++\n const price = options.find((option) => option.price.id === value)?.price\n setSelectedPriceId(value ?? \"\")\n setSeats(String(price ? (initialSeats(price, quantity) ?? \"\") : \"\"))\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n\n const handleSeats = (value: string) => {\n view.current++\n setSeats(value)\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n\n const previewError =\n preview.error instanceof Error ? preview.error.message : \"\"\n const changeError = change.error instanceof Error ? change.error.message : \"\"\n const responseMessage = change.data?.message\n const responseURL = change.data?.next_action?.url ?? undefined\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogTrigger\n render={\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={Boolean(blockReason) && !change.variables}\n title={blockReason}\n >\n <AdminMessage id={\"Change subscription\"} />\n </Button>\n }\n />\n <DialogContent className={DIALOG_WIDE}>\n <DialogHeader>\n <DialogTitle>\n <AdminMessage id={\"Change subscription\"} />\n </DialogTitle>\n <DialogDescription>\n <AdminMessage\n id={\"Schedule the customer's plan or seats for the next renewal. No card is charged now. Choosing the current plan and seats clears a pending change. The customer is told.\"}\n />\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"grid gap-5\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-tier\")}>\n <AdminMessage id={\"New plan\"} />\n </Label>\n <Select value={selectedPriceId} onValueChange={handleSelect}>\n <SelectTrigger\n id={adminId(\"subscription-tier\")}\n className=\"w-full\"\n disabled={productsQuery.isPending || pricesQuery.isPending}\n >\n <SelectValue\n placeholder={\n productsQuery.isPending || pricesQuery.isPending\n ? \"Loading plans…\"\n : \"Choose a plan\"\n }\n />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.price.id} value={option.price.id}>\n {subscriptionChangeOptionLabel(option)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {!productsQuery.isPending &&\n !pricesQuery.isPending &&\n !productsQuery.isError &&\n !pricesQuery.isError &&\n options.length === 0 && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n \"No eligible recurring plans share this tier group and currency.\"\n }\n />\n </p>\n )}\n {(productsQuery.isError || pricesQuery.isError) && (\n <p className=\"text-xs text-destructive\" role=\"alert\">\n <AdminMessage id={\"Could not load the available plans.\"} />\n </p>\n )}\n </div>\n\n {bounds && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-seats\")}>\n <AdminMessage id={\"Seats\"} />\n </Label>\n <Input\n id={adminId(\"subscription-seats\")}\n type=\"number\"\n inputMode=\"numeric\"\n min={bounds.min}\n max={bounds.max}\n value={seats}\n onChange={(event) => handleSeats(event.target.value)}\n />\n <p className=\"text-xs text-muted-foreground\">\n {bounds.min}\n <AdminMessage id={\" to \"} />\n {bounds.max}\n <AdminMessage id={\" seats.\"} />\n </p>\n </div>\n )}\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-change-reason\")}>\n <AdminMessage id={\"Reason\"} />\n </Label>\n <Input\n id={adminId(\"subscription-change-reason\")}\n value={reason}\n maxLength={500}\n placeholder={adminText(\"What the customer asked for\")}\n onChange={(event) => setReason(event.target.value)}\n />\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Kept with the scheduled change.\"} />\n </p>\n </div>\n\n {reviewed && selected && (\n <div className=\"grid gap-3\" aria-live=\"polite\">\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-sm font-medium\">\n <AdminMessage id={\"Review\"} />\n </span>\n <Badge variant=\"secondary\">\n {reviewed.effective === \"now\" ? \"Immediate\" : \"At renewal\"}\n </Badge>\n </div>\n <dl className=\"grid grid-cols-2 gap-x-8 gap-y-3 border-y py-4 text-sm\">\n {reviewed.quantity !== null && (\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Seats\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {reviewed.quantity}\n </dd>\n </div>\n )}\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Due now\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatNativeAmount(\n reviewed.amount_due_now,\n reviewed.currency\n )}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Next charge\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatNativeAmount(\n reviewed.next_charge_amount,\n reviewed.currency\n )}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Effective\"} />\n </dt>\n <dd className=\"font-medium\">\n {reviewed.effective === \"now\"\n ? \"Immediately\"\n : formatDate(reviewed.next_charge_date)}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Next billing date\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatDate(reviewed.next_charge_date)}\n </dd>\n </div>\n </dl>\n {reviewed.is_estimate && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n \"The payment provider calculates the final prorated amount.\"\n }\n />\n </p>\n )}\n </div>\n )}\n\n {(previewError || changeError) && (\n <p className=\"text-sm text-destructive\" role=\"alert\">\n {changeError || previewError}\n </p>\n )}\n\n {change.data && change.data.status !== \"succeeded\" && (\n <div\n className=\"grid gap-2 rounded-lg bg-muted px-3 py-2.5 text-sm\"\n aria-live=\"polite\"\n >\n <p>{responseMessage ?? \"This change needs another step.\"}</p>\n {responseURL && (\n <a\n href={responseURL}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"w-fit font-medium text-primary underline underline-offset-4\"\n >\n <AdminMessage id={\"Continue with payment provider\"} />\n </a>\n )}\n </div>\n )}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => handleOpenChange(false)}\n >\n <AdminMessage id={\"Cancel\"} />\n </Button>\n {!reviewed ? (\n <Button\n type=\"button\"\n disabled={!request || unchanged || preview.isPending}\n onClick={async () => {\n if (!request) return\n const currentView = view.current\n try {\n await preview.mutateAsync(request)\n if (view.current !== currentView) return\n setReviewedKey(requestKey)\n } catch (error) {\n if (view.current === currentView) {\n toastApiError(error, \"Preview subscription change\")\n }\n }\n }}\n >\n {preview.isPending ? \"Reviewing…\" : \"Review change\"}\n </Button>\n ) : (\n <Button\n type=\"button\"\n disabled={\n change.isPending ||\n !reason.trim() ||\n (Boolean(change.data) && change.data?.status !== \"processing\")\n }\n onClick={async () => {\n if (!request) return\n const currentView = view.current\n const changeKey =\n attempts.current.get(requestKey) ?? crypto.randomUUID()\n attempts.current.set(requestKey, changeKey)\n const completeAttempt = () => {\n if (attempts.current.get(requestKey) === changeKey) {\n attempts.current.delete(requestKey)\n }\n }\n try {\n const result = await change.mutateAsync({\n change: { ...request, reason: reason.trim() },\n idempotencyKey: changeKey,\n })\n if (\n result.status === \"succeeded\" ||\n result.status === \"blocked\"\n ) {\n completeAttempt()\n }\n if (view.current !== currentView) return\n if (result.status === \"succeeded\") {\n toast.success(\n result.effective === \"now\"\n ? \"Subscription changed\"\n : \"Change scheduled for the next renewal\"\n )\n handleOpenChange(false)\n setSelectedPriceId(\"\")\n setSeats(\"\")\n setReason(\"\")\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n if (result.status === \"processing\") {\n toast.info(\n \"The provider is still confirming this change. Check again to read the result.\"\n )\n }\n } catch (error) {\n // 402 is a final provider refusal regardless of its code.\n // Other refusals can reject a readback of an already accepted\n // operation, so retire only explicitly terminal outcomes.\n if (\n error instanceof ApiError &&\n (error.status === 402 ||\n (error.status === 409 &&\n (error.code === \"subscription_change_refused\" ||\n error.code ===\n \"subscription_change_idempotency_conflict\")))\n ) {\n completeAttempt()\n }\n if (view.current === currentView) {\n toastApiError(error, \"Change subscription\")\n }\n }\n }}\n >\n {change.isPending\n ? \"Applying…\"\n : change.data\n ? change.data.status === \"processing\"\n ? \"Check result\"\n : change.data.status === \"blocked\"\n ? \"Change blocked\"\n : \"Action required\"\n : \"Confirm change\"}\n </Button>\n )}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport { ArrowLeft01Icon } from \"@hugeicons/core-free-icons\"\nimport * as React from \"react\"\nimport { Link, useNavigate, useParams } from \"#orck/admin/router\"\n\nimport { useForm } from \"@tanstack/react-form\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Fact } from \"#orck/admin/components/fact-card\"\nimport { FormFieldErrors } from \"#orck/admin/components/form-field-errors\"\nimport { StatusBadge } from \"#orck/admin/components/status-badge\"\nimport { TypedConfirmDialog } from \"#orck/admin/components/typed-confirm-dialog\"\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"#orck/admin/components/ui/dialog\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"#orck/admin/components/ui/select\"\nimport { Switch } from \"#orck/admin/components/ui/switch\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport type { ScheduledChange } from \"#orck/admin/lib/api/types\"\nimport { DIALOG_FORM } from \"#orck/admin/lib/dialog-width\"\nimport {\n formatCard,\n formatDate,\n formatNativeAmount,\n shortId,\n} from \"#orck/admin/lib/format\"\n\nimport { ChangeSubscriptionDialog } from \"#orck/admin/pages/subscriptions/change-subscription-dialog\"\nimport { dunningSummary } from \"#orck/admin/pages/subscriptions/dunning\"\nimport { useAdminUpdates } from \"#orck/admin/lib/capabilities\"\n\nexport function SubscriptionDetailPage() {\n const { text: adminText } = useAdminUI()\n\n const { adminQueries } = useAdminServices()\n\n const canUpdate = useAdminUpdates()\n const { id = \"\" } = useParams()\n const navigate = useNavigate()\n const { data: sub, isPending: loading } = useQuery(\n adminQueries.subscription(id)\n )\n const { data: paymentPage } = useQuery(\n adminQueries.payments({ subscription_id: id }, 20)\n )\n const payments = paymentPage?.data ?? []\n if (loading)\n return (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"Loading…\"} />\n </p>\n )\n if (!sub)\n return (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"Subscription not found.\"} />\n </p>\n )\n\n const cancellable =\n sub.status === \"active\" ||\n sub.status === \"past_due\" ||\n sub.status === \"awaiting_method\" ||\n sub.status === \"unverified\"\n const resumable = sub.status === \"canceled\" || sub.status === \"past_due\"\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => navigate(-1)}\n aria-label={adminText(\"Back\")}\n >\n <HugeiconsIcon icon={ArrowLeft01Icon} className=\"size-4\" />\n </Button>\n <div>\n <h2 className=\"flex items-center gap-2 text-sm\">\n {sub.id} <StatusBadge status={sub.status} />\n </h2>\n <p className=\"text-xs text-muted-foreground\">\n {sub.rail} · {sub.rail_subscription_id || \"no rail id\"}\n </p>\n </div>\n <div className=\"ml-auto flex gap-2\">\n {canUpdate && resumable && (\n <ResumeButton id={sub.id} customerId={sub.customer_id} />\n )}\n {canUpdate && (\n <ChangeSubscriptionDialog\n subscriptionId={sub.id}\n customerId={sub.customer_id}\n productId={sub.product_id}\n priceId={sub.price_id}\n quantity={sub.quantity}\n currency={sub.price?.currency}\n collectionPolicy={sub.collection_policy}\n scheduledChange={sub.scheduled_change}\n rail={sub.rail}\n status={sub.status}\n />\n )}\n {canUpdate && (\n <ChangePaymentMethodDialog\n subscriptionId={sub.id}\n customerId={sub.customer_id}\n rail={sub.rail}\n collectionPolicy={sub.collection_policy}\n />\n )}\n {canUpdate && cancellable && (\n <CancelDialog id={sub.id} customerId={sub.customer_id} />\n )}\n </div>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <Fact label={adminText(\"Customer\")}>\n {sub.customer_id ? (\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/customers/${sub.customer_id}`}\n >\n {shortId(sub.customer_id, 13)}\n </Link>\n ) : (\n \"—\"\n )}\n </Fact>\n <Fact label={adminText(\"Started\")}>{formatDate(sub.started_at)}</Fact>\n <Fact label={adminText(\"Current period\")}>\n {formatDate(sub.current_period_starts_at)} →{\" \"}\n {formatDate(sub.current_period_ends_at)}\n </Fact>\n <Fact label={adminText(\"Price\")}>\n <div className=\"flex flex-col gap-1\">\n <span className=\"flex items-center gap-2\">\n {sub.price?.unit_amount !== undefined && sub.price?.currency ? (\n <Link\n className=\"underline-offset-2 hover:underline\"\n to={`/catalog/prices/${encodeURIComponent(sub.price_id)}`}\n >\n {formatNativeAmount(\n sub.price.unit_amount,\n sub.price.currency\n )}\n </Link>\n ) : (\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/catalog/prices/${encodeURIComponent(sub.price_id)}`}\n >\n {shortId(sub.price_id ?? \"—\", 13)}\n </Link>\n )}\n {sub.price?.archived && (\n <Badge\n variant=\"secondary\"\n title={adminText(\"Pinned to an archived (prior) version\")}\n >\n <AdminMessage id={\"prior version\"} />\n </Badge>\n )}\n </span>\n {sub.price?.key && (\n <span className=\"text-xs text-muted-foreground\">\n {sub.price.key}\n </span>\n )}\n {sub.scheduled_change && (\n <ScheduledChangeBadge change={sub.scheduled_change} />\n )}\n </div>\n </Fact>\n {sub.quantity !== null && (\n <Fact label={adminText(\"Seats\")}>\n {sub.quantity}\n {sub.scheduled_change?.quantity != null &&\n ` → ${sub.scheduled_change.quantity} at renewal`}\n </Fact>\n )}\n <Fact label={adminText(\"Dunning\")}>\n {sub.dunning ? dunningSummary(sub.dunning) : \"—\"}\n </Fact>\n <Fact\n label={\n sub.dunning?.waiting_for_new_card ? \"Card deadline\" : \"Final retry\"\n }\n >\n {formatDate(sub.dunning?.final_retry_at)}\n </Fact>\n <Fact label={adminText(\"Last decline\")}>\n {sub.dunning?.last_failure_reason ?? \"—\"}\n </Fact>\n <Fact label={adminText(\"Canceled\")}>\n {sub.canceled_at\n ? `${formatDate(sub.canceled_at)} (${sub.cancel_type ?? \"?\"})`\n : \"—\"}\n </Fact>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Payments\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {!payments.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"No payments recorded.\"} />\n </p>\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Payment\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Status\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Kind\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Amount\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Created\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {payments.map((p) => (\n <TableRow key={p.id}>\n <TableCell>\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/payments/${p.id}`}\n >\n {shortId(p.id, 13)}\n </Link>\n </TableCell>\n <TableCell>\n <StatusBadge status={p.status} />\n </TableCell>\n <TableCell>{p.kind}</TableCell>\n <TableCell>\n {formatNativeAmount(p.amount, p.currency)}\n </TableCell>\n <TableCell>{formatDate(p.created_at)}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </CardContent>\n </Card>\n </div>\n )\n}\n\nfunction CancelDialog({ id, customerId }: { id: string; customerId?: string }) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const { text: adminText, id: adminId } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const queryClient = useQueryClient()\n const cancel = useMutation(\n adminMutations.cancelSubscription(queryClient, id, customerId)\n )\n const form = useForm({\n defaultValues: { reason: \"\", revokeAccess: false },\n })\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next)\n if (!next) {\n form.reset()\n cancel.reset()\n }\n }\n\n return (\n <>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => setOpen(true)}>\n <AdminMessage id={\"Cancel subscription\"} />\n </Button>\n <TypedConfirmDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={adminText(\"Cancel subscription\")}\n description={adminText(\n \"Terminal cancellation at the payment rail. This is a last resort. Dunning parks subscriptions as past_due without losing entitlements.\"\n )}\n confirmationWord=\"CANCEL\"\n actionLabel=\"Cancel subscription\"\n onConfirm={async () => {\n try {\n await cancel.mutateAsync(form.state.values)\n toast.success(\"Subscription canceled\")\n } catch (err) {\n toastApiError(err, \"Cancel subscription\")\n throw err\n }\n }}\n >\n <div className=\"grid gap-3\">\n <form.Field name=\"reason\">\n {(field) => (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"cancel-reason\")}>\n <AdminMessage id={\"Reason\"} />\n </Label>\n <Input\n id={adminId(\"cancel-reason\")}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(event) => field.handleChange(event.target.value)}\n placeholder={adminText(\"why is this being canceled?\")}\n />\n </div>\n )}\n </form.Field>\n <form.Field name=\"revokeAccess\">\n {(field) => (\n <div className=\"flex items-center gap-2\">\n <Switch\n id={adminId(\"cancel-revoke\")}\n checked={field.state.value}\n onCheckedChange={field.handleChange}\n />\n <Label htmlFor={adminId(\"cancel-revoke\")}>\n <AdminMessage id={\"Also revoke access immediately\"} />\n </Label>\n </div>\n )}\n </form.Field>\n </div>\n </TypedConfirmDialog>\n </>\n )\n}\n\nfunction ResumeButton({ id, customerId }: { id: string; customerId?: string }) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const queryClient = useQueryClient()\n const resume = useMutation(\n adminMutations.resumeSubscription(queryClient, id, customerId)\n )\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={resume.isPending}\n onClick={async () => {\n try {\n await resume.mutateAsync()\n toast.success(\"Resume queued\")\n } catch (err) {\n toastApiError(err, \"Resume subscription\")\n }\n }}\n >\n {resume.isPending ? \"Queuing…\" : \"Resume\"}\n </Button>\n )\n}\n\n// The choice that makes the subscription follow the customer's default card.\nconst FOLLOW_DEFAULT = \"default\"\n\nfunction ChangePaymentMethodDialog({\n subscriptionId,\n customerId,\n rail,\n collectionPolicy,\n}: {\n subscriptionId: string\n customerId?: string\n rail: string\n collectionPolicy?: string\n}) {\n const { toast, toastApiError, adminMutations, adminQueries } =\n useAdminServices()\n\n const { id: adminId, text: adminText } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const queryClient = useQueryClient()\n const changePaymentMethod = useMutation(\n adminMutations.changeSubscriptionPaymentMethod(\n queryClient,\n subscriptionId,\n customerId\n )\n )\n const { data: pms } = useQuery(\n adminQueries.customerPaymentMethods(open ? customerId : undefined)\n )\n const form = useForm({\n defaultValues: { paymentMethodId: \"\" },\n onSubmit: async ({ value }) => {\n try {\n await changePaymentMethod.mutateAsync(\n value.paymentMethodId === FOLLOW_DEFAULT\n ? null\n : value.paymentMethodId\n )\n toast.success(\"Payment method updated\")\n handleOpenChange(false)\n } catch (err) {\n toastApiError(err, \"Change payment method\")\n }\n },\n })\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next)\n if (!next) {\n form.reset()\n changePaymentMethod.reset()\n }\n }\n\n // A card subscription OpenRails collects, or an NMI schedule; a provider\n // that keeps the card (Stripe-owned, CCBill) or a wallet has none to change.\n const supported =\n rail !== \"solana\" &&\n (collectionPolicy === \"engine\" || collectionPolicy === \"nmi_schedule\")\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogTrigger\n render={\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!supported}\n title={\n supported\n ? undefined\n : `Payment-method change is not supported on ${rail}`\n }\n >\n <AdminMessage id={\"Change payment method\"} />\n </Button>\n }\n />\n <DialogContent className={DIALOG_FORM}>\n <DialogHeader>\n <DialogTitle>\n <AdminMessage id={\"Change payment method\"} />\n </DialogTitle>\n <DialogDescription>\n <AdminMessage\n id={\n \"Points future renewals of this subscription at another of the customer&apos;s stored cards (same rail), or back at their default card for its currency.\"\n }\n />\n </DialogDescription>\n </DialogHeader>\n <form\n onSubmit={(event) => {\n event.preventDefault()\n event.stopPropagation()\n void form.handleSubmit()\n }}\n className=\"grid gap-4\"\n >\n <form.Field\n name=\"paymentMethodId\"\n validators={{\n onChange: ({ value }) =>\n value ? undefined : \"Pick a stored payment method\",\n }}\n >\n {(field) => (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-payment-method\")}>\n <AdminMessage id={\"Payment method\"} />\n </Label>\n <Select\n value={field.state.value}\n onValueChange={(value) => field.handleChange(value ?? \"\")}\n >\n <SelectTrigger\n className=\"w-full\"\n id={adminId(\"subscription-payment-method\")}\n aria-invalid={field.state.meta.errors.length > 0}\n >\n <SelectValue\n placeholder={adminText(\"Pick a stored payment method\")}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={FOLLOW_DEFAULT}>\n <AdminMessage id={\"The customer&apos;s default card\"} />\n </SelectItem>\n {(pms ?? [])\n .filter((pm) => pm.rail === rail)\n .map((pm) => (\n <SelectItem key={pm.id} value={pm.id}>\n {formatCard(pm.card)} ({pm.rail})\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <FormFieldErrors errors={field.state.meta.errors} />\n </div>\n )}\n </form.Field>\n <DialogFooter>\n <form.Subscribe\n selector={(state) =>\n [\n state.values.paymentMethodId,\n state.canSubmit,\n state.isSubmitting,\n ] as const\n }\n >\n {([paymentMethodId, canSubmit, isSubmitting]) => (\n <Button\n type=\"submit\"\n disabled={!paymentMethodId || !canSubmit || isSubmitting}\n >\n {isSubmitting ? \"Updating…\" : \"Update\"}\n </Button>\n )}\n </form.Subscribe>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n\n// ScheduledChangeBadge shows the change waiting for the next renewal: a price\n// migration's move or a scheduled downgrade. A change back to the current\n// price clears it.\nfunction ScheduledChangeBadge({ change }: { change: ScheduledChange }) {\n const { adminQueries } = useAdminServices()\n\n const { data: toPrice } = useQuery(adminQueries.price(change.price_id))\n return (\n <Badge className=\"bg-held-surface text-held\">\n {change.source === \"migration\" ? \"migrates\" : \"changes\"}\n <AdminMessage id={\" to\"} />{\" \"}\n {toPrice\n ? formatNativeAmount(toPrice.unit_amount, toPrice.currency)\n : shortId(change.price_id, 9)}{\" \"}\n <AdminMessage id={\"at the first renewal from \"} />\n {formatDate(change.effective_at)}\n </Badge>\n )\n}\n"],"mappings":"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"}
@@ -1,15 +1,15 @@
1
- import { E as e, c as t, p as n, r, w as i } from "./admin-utils-BK4Vh1o_.js";
2
- import { t as a } from "./admin-button-CTL3DgOt.js";
3
- import { t as o } from "./admin-input-CcfQfJFN.js";
4
- import { a as s } from "./admin-capabilities-BuigAgtm.js";
1
+ import { E as e, c as t, p as n, r, w as i } from "./admin-utils-DnVY5fYd.js";
2
+ import { t as a } from "./admin-button-Oip73Plq.js";
3
+ import { t as o } from "./admin-input-DO5lvCLL.js";
4
+ import { a as s } from "./admin-capabilities-BGv7oG8v.js";
5
5
  import { n as c, o as l, s as u, t as d, u as f } from "./admin-format-DoohJ7Fg.js";
6
- import { n as p, r as m } from "./admin-dom-uMmZzRvU.js";
7
- import { t as h } from "./admin-status-badge-BFPgo71d.js";
8
- import { a as g, i as _, n as v, o as y, r as b, t as x } from "./admin-dialog-BjuKI5Hp.js";
9
- import { t as S } from "./admin-label-BiEN5cjb.js";
10
- import { a as C, o as w, r as T, t as E } from "./admin-card-bzAks3-3.js";
6
+ import { n as p, r as m } from "./admin-dom-lnNSQ7ke.js";
7
+ import { t as h } from "./admin-status-badge-CwqIU8tK.js";
8
+ import { a as g, i as _, n as v, o as y, r as b, t as x } from "./admin-dialog-Ffx95AIT.js";
9
+ import { t as S } from "./admin-label-BzJpr3lg.js";
10
+ import { a as C, o as w, r as T, t as E } from "./admin-card-DGbi6ZHZ.js";
11
11
  import { r as D } from "./admin-invoice-profile-model-Cgjy3zV8.js";
12
- import { t as O } from "./admin-data-table-qfXLOFmN.js";
12
+ import { t as O } from "./admin-data-table-CgeWv__T.js";
13
13
  import { useState as k } from "react";
14
14
  import { useMutation as A, useQuery as j, useQueryClient as M } from "@tanstack/react-query";
15
15
  import { Fragment as N, jsx as P, jsxs as F } from "react/jsx-runtime";
@@ -341,4 +341,4 @@ function G({ order: t }) {
341
341
  //#endregion
342
342
  export { H as OrderDetailPage };
343
343
 
344
- //# sourceMappingURL=admin-detail-BHe51ma9.js.map
344
+ //# sourceMappingURL=admin-detail-DG-YaHhS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-detail-BHe51ma9.js","names":[],"sources":["../src/admin/pages/orders/model.ts","../src/admin/pages/orders/detail.tsx"],"sourcesContent":["import type { Order, Payment } from \"#orck/client/generated/wire\"\nimport type { UsageAction } from \"#orck/admin/lib/api/order-endpoints\"\nimport { amountFromInput } from \"#orck/admin/lib/format\"\n\nexport const usageActionLabels: Record<UsageAction, string> = {\n waive_balance: \"Waive balance\",\n mark_uncollectible: \"Mark uncollectible\",\n record_payment: \"Record payment\",\n}\nexport const usageActionDescriptions: Record<UsageAction, string> = {\n waive_balance:\n \"Forgive the remaining debt. Existing payments stay recorded and are not refunded.\",\n mark_uncollectible:\n \"Stop scheduled collection. What the order owes remains owed; collecting it again reopens it.\",\n record_payment:\n \"Record money already received outside automatic collection. This does not charge a payment method.\",\n}\n// usageActions are what staff who may change billing can do to a usage\n// order in its state: none while a collection is in progress.\nexport function usageActions(order: Order): UsageAction[] {\n const usage = order.usage\n if (order.collection_owner !== \"engine\" || !usage || BigInt(usage.amount_due) <= 0n) return []\n switch (order.status) {\n case \"open\":\n return [\"record_payment\", \"mark_uncollectible\", \"waive_balance\"]\n case \"uncollectible\":\n return [\"record_payment\", \"waive_balance\"]\n }\n return []\n}\nexport function usageResultMessage(result: Order | Payment) {\n if (\"kind\" in result) return \"Payment recorded.\"\n if (result.status === \"complete\") return \"Order paid.\"\n if (result.status === \"processing\")\n return \"Collection is pending verification. No new collection should be started.\"\n return \"Order updated.\"\n}\nexport function usagePaymentAmount(\n input: string,\n amountDue: string,\n decimals: number\n) {\n const amount = amountFromInput(input.trim(), decimals)\n if (amount === null)\n throw new Error(\n `Enter a positive amount with up to ${decimals} decimal places.`\n )\n if (BigInt(amount) <= 0n || BigInt(amount) > BigInt(amountDue))\n throw new Error(\n \"Payment must be positive and no greater than what the order owes.\"\n )\n return amount\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { useState } from \"react\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\nimport { Link, useParams } from \"#orck/admin/router\"\nimport type { ColumnDef } from \"@tanstack/react-table\"\n\nimport { CursorPager } from \"#orck/admin/components/cursor-pager\"\nimport { DataTable } from \"#orck/admin/components/data-table\"\nimport { StatusBadge } from \"#orck/admin/components/status-badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from \"#orck/admin/components/ui/dialog\"\nimport { useCursorPages } from \"#orck/admin/lib/cursor-pages\"\nimport type { Order, OrderUsage, Payment } from \"#orck/client/generated/wire\"\nimport type { UsageAction } from \"#orck/admin/lib/api/order-endpoints\"\n\nimport { useAdminUpdates } from \"#orck/admin/lib/capabilities\"\nimport {\n currencyScale,\n formatDate,\n formatNativeAmount,\n shortId,\n} from \"#orck/admin/lib/format\"\nimport { taxDisplay } from \"../customers/invoice-profile-model\"\nimport {\n usageActionDescriptions,\n usageActionLabels,\n usageActions,\n usagePaymentAmount,\n usageResultMessage,\n} from \"./model\"\n\nconst historyColumns: ColumnDef<Payment, unknown>[] = [\n {\n header: \"Paid\",\n cell: ({ row }) => formatDate(row.original.created_at),\n },\n {\n header: \"Amount\",\n cell: ({ row }) =>\n formatNativeAmount(row.original.amount, row.original.currency),\n },\n {\n header: \"Status\",\n cell: ({ row }) => <StatusBadge status={row.original.status} />,\n },\n {\n header: \"Method\",\n cell: ({ row }) => row.original.rail ?? row.original.channel,\n },\n {\n header: \"Reference\",\n cell: ({ row }) => row.original.transaction_id || shortId(row.original.id),\n },\n]\nexport function OrderDetailPage() {\n const { orderQueries } = useAdminServices()\n\n const { id = \"\" } = useParams()\n const { data: order, isPending, error } = useQuery(orderQueries.detail(id))\n if (isPending)\n return (\n <p>\n <AdminMessage id={\"Loading order…\"} />\n </p>\n )\n if (error)\n return (\n <p role=\"alert\" className=\"text-destructive\">\n {error.message}\n </p>\n )\n if (!order)\n return (\n <p>\n <AdminMessage id={\"Order not found.\"} />\n </p>\n )\n return <OrderDetail key={order.id} order={order} />\n}\nexport function OrderDetail({ order }: { order: Order }) {\n const { orderQueries } = useAdminServices()\n\n const paging = useCursorPages(order.id, 25)\n const history = useQuery(\n orderQueries.payments(order.id, paging.size, paging.cursor)\n )\n const failure = order.payment.last_payment_error\n return (\n <div className=\"flex flex-col gap-5\">\n <Link to=\"/orders\" className=\"text-sm underline\">\n <AdminMessage id={\"← Orders\"} />\n </Link>\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{order.number ?? order.id}</h1>\n <StatusBadge status={order.status} />\n {order.usage?.delinquent && <StatusBadge status=\"delinquent\" />}\n </div>\n <p className=\"text-sm\">\n <AdminMessage id={\"Customer\"} />{\" \"}\n <Link className=\"underline\" to={`/customers/${order.customer_id}`}>\n {order.customer_id}\n </Link>{\" \"}\n · {order.origin} · {order.currency}\n </p>\n <div className=\"grid gap-4 md:grid-cols-3\">\n {[\n [\"Total\", order.total],\n ...(order.usage\n ? [\n [\"Paid\", order.usage.amount_paid],\n [\"Unpaid\", order.usage.amount_due],\n ]\n : []),\n ].map(([label, value]) => (\n <Card key={String(label)}>\n <CardHeader>\n <CardTitle>{label}</CardTitle>\n </CardHeader>\n <CardContent className=\"text-xl\">\n {formatNativeAmount(value, order.currency)}\n </CardContent>\n </Card>\n ))}\n </div>\n {order.usage && <UsageFacts usage={order.usage} />}\n {order.renewal && (\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Renewal\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"grid gap-3 text-sm md:grid-cols-2\">\n <p>\n <AdminMessage id={\"Subscription:\"} />{\" \"}\n <Link\n className=\"underline\"\n to={`/subscriptions/${order.renewal.subscription_id}`}\n >\n {shortId(order.renewal.subscription_id)}\n </Link>\n </p>\n <p>\n <AdminMessage id={\"Period: \"} />\n {formatDate(order.renewal.period_starts_at)} –{\" \"}\n {formatDate(order.renewal.period_ends_at)}\n </p>\n <p>\n <AdminMessage id={\"Due: \"} />\n {formatDate(order.renewal.due_at)}\n </p>\n </CardContent>\n </Card>\n )}\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Lines\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"text-left\">\n <th>\n <AdminMessage id={\"Description\"} />\n </th>\n <th>\n <AdminMessage id={\"Quantity\"} />\n </th>\n <th className=\"text-right\">\n <AdminMessage id={\"Amount\"} />\n </th>\n </tr>\n </thead>\n <tbody>\n {order.lines.map((line) => (\n <tr key={line.id}>\n <td className=\"py-2\">\n {line.description}\n {line.source && (\n <p className=\"text-xs text-muted-foreground\">\n {line.source}\n </p>\n )}\n </td>\n <td>{line.quantity ?? \"—\"}</td>\n <td className=\"text-right\">\n {formatNativeAmount(line.amount, order.currency)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n {!order.lines.length && (\n <p>\n <AdminMessage id={\"No lines.\"} />\n </p>\n )}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Payment\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <p>\n <AdminMessage id={\"Status: \"} />\n <StatusBadge status={order.payment.status} />\n </p>\n {order.collection_owner !== \"engine\" && (\n <p>\n {order.collection_owner === \"nmi_schedule\"\n ? \"Collection follows the NMI schedule. Recovery is coordinated through the subscription.\"\n : \"The payment provider collects this bill. Payment activity appears in the history below.\"}\n </p>\n )}\n {order.provider_bills.map((bill, index) => (\n <p key={`${bill.psp_id}:${bill.kind}:${bill.reference}:${index}`}>\n {bill.reference || bill.kind}\n {bill.settled_at\n ? ` · Settled via ${bill.settlement_source} · ${formatDate(bill.settled_at)}`\n : \" · Settlement not yet verified\"}\n </p>\n ))}\n {failure && (\n <p>\n <AdminMessage id={\"Last failure: \"} />\n {failure.message}\n </p>\n )}\n {order.usage && <UsageActions order={order} />}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Payment history\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {history.error ? (\n <p role=\"alert\" className=\"text-destructive\">\n {history.error.message}\n </p>\n ) : (\n <>\n <DataTable\n columns={historyColumns}\n data={history.data?.data ?? []}\n loading={history.isPending}\n emptyMessage=\"No payments recorded.\"\n />\n <CursorPager\n pages={paging}\n rows={history.data?.data?.length ?? 0}\n nextCursor={history.data?.next_cursor}\n busy={history.isFetching}\n />\n </>\n )}\n </CardContent>\n </Card>\n </div>\n )\n}\n\nfunction UsageFacts({ usage }: { usage: OrderUsage }) {\n return (\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Usage billed\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"grid gap-3 text-sm md:grid-cols-2\">\n <p>\n <AdminMessage id={\"Period: \"} />\n {formatDate(usage.period_starts_at)} –{\" \"}\n {formatDate(usage.period_ends_at)}\n </p>\n <p>\n <AdminMessage id={\"Due: \"} />\n {formatDate(usage.due_at)}\n </p>\n <p>\n <AdminMessage id={\"Collection:\"} />{\" \"}\n {usage.collection_method === \"send_invoice\"\n ? \"Manual remittance\"\n : \"Saved payment method\"}\n </p>\n <p>\n <AdminMessage id={\"Next attempt: \"} />\n {formatDate(usage.next_collection_attempt_at)}\n </p>\n <p>\n <AdminMessage id={\"Purchase order: \"} />\n {usage.po_number ?? \"—\"}\n </p>\n <p>\n <AdminMessage id={\"Memo: \"} />\n {usage.memo ?? \"—\"}\n </p>\n <div>\n <p className=\"font-medium\">\n <AdminMessage id={\"Billing contacts\"} />\n </p>\n {usage.billing_contacts.length ? (\n usage.billing_contacts.map((c, i) => (\n <p key={i}>\n {c.name ? `${c.name} · ` : \"\"}\n {c.email}\n </p>\n ))\n ) : (\n <p>—</p>\n )}\n </div>\n <div>\n <p className=\"font-medium\">\n <AdminMessage id={\"Tax details\"} />\n </p>\n {Object.entries(usage.tax ?? {}).map(([key, value]) => (\n <p key={key}>\n {key}: {taxDisplay(value)}\n </p>\n ))}\n </div>\n <p className=\"text-muted-foreground md:col-span-2\">\n <AdminMessage\n id={\n \"These are the customer&apos;s invoice profile when the order was billed. Editing the profile affects later orders.\"\n }\n />\n </p>\n </CardContent>\n </Card>\n )\n}\n\nfunction UsageActions({ order }: { order: Order }) {\n const { toast, usageActionMutation } = useAdminServices()\n\n const { id: adminId } = useAdminUI()\n\n const canUpdate = useAdminUpdates()\n const [action, setAction] = useState<UsageAction | null>(null)\n const [amount, setAmount] = useState(\"\")\n const [reference, setReference] = useState(\"\")\n const [error, setError] = useState<string | null>(null)\n const client = useQueryClient()\n const mutation = useMutation(usageActionMutation(client, order.customer_id))\n const actions = canUpdate ? usageActions(order) : []\n async function submit() {\n if (!action || mutation.isPending) return\n setError(null)\n try {\n if (!actions.includes(action))\n throw new Error(\n \"This action is no longer available. Refresh the order before continuing.\"\n )\n if (action === \"record_payment\" && !reference.trim())\n throw new Error(\"Enter the bank or payment reference.\")\n let paid: string | undefined\n if (action === \"record_payment\") {\n const scale = currencyScale(order.currency)\n if (scale === undefined)\n throw new Error(`${order.currency} is not a registered currency.`)\n paid = usagePaymentAmount(amount, order.usage!.amount_due, scale)\n }\n const result = await mutation.mutateAsync({\n id: order.id,\n action,\n amount: paid,\n reference: reference.trim(),\n })\n toast(usageResultMessage(result))\n setAction(null)\n } catch (failure) {\n setError(\n failure instanceof Error ? failure.message : \"Order action failed.\"\n )\n }\n }\n return (\n <>\n {order.status === \"processing\" && (\n <p role=\"status\">\n <AdminMessage\n id={\n \"A collection of this order is in progress. It must finish, or be resolved with \"\n }\n />\n <code>\n <AdminMessage id={\"openrails intents resolve\"} />\n </code>\n <AdminMessage id={\", before another action.\"} />\n </p>\n )}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((value) => (\n <Button\n key={value}\n variant={value === \"waive_balance\" ? \"destructive\" : \"outline\"}\n onClick={() => {\n setAction(value)\n setError(null)\n }}\n >\n {usageActionLabels[value]}\n </Button>\n ))}\n </div>\n {!actions.length && order.status !== \"processing\" && (\n <p className=\"text-muted-foreground\">\n <AdminMessage\n id={\n \"No actions are available for your permissions and this order&apos;s state.\"\n }\n />\n </p>\n )}\n <Dialog\n open={action !== null}\n onOpenChange={(open) => {\n if (!open && !mutation.isPending) setAction(null)\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {action ? usageActionLabels[action] : \"Order action\"}\n </DialogTitle>\n <DialogDescription>\n {action ? usageActionDescriptions[action] : \"\"}\n </DialogDescription>\n </DialogHeader>\n {action === \"record_payment\" && (\n <div className=\"space-y-3\">\n <div>\n <Label htmlFor={adminId(\"order-payment-amount\")}>\n <AdminMessage id={\"Amount (\"} />\n {order.currency})\n </Label>\n <Input\n id={adminId(\"order-payment-amount\")}\n inputMode=\"decimal\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n />\n </div>\n <div>\n <Label htmlFor={adminId(\"order-payment-reference\")}>\n <AdminMessage id={\"Payment reference\"} />\n </Label>\n <Input\n id={adminId(\"order-payment-reference\")}\n maxLength={255}\n value={reference}\n onChange={(e) => setReference(e.target.value)}\n />\n </div>\n </div>\n )}\n {error && (\n <p role=\"alert\" className=\"text-destructive\">\n {error}\n </p>\n )}\n <DialogFooter>\n <Button\n variant=\"outline\"\n disabled={mutation.isPending}\n onClick={() => setAction(null)}\n >\n <AdminMessage id={\"Cancel\"} />\n </Button>\n <Button\n disabled={\n mutation.isPending || !action || !actions.includes(action)\n }\n onClick={() => void submit()}\n >\n {mutation.isPending ? \"Working…\" : \"Confirm\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"admin-detail-DG-YaHhS.js","names":[],"sources":["../src/admin/pages/orders/model.ts","../src/admin/pages/orders/detail.tsx"],"sourcesContent":["import type { Order, Payment } from \"#orck/client/generated/wire\"\nimport type { UsageAction } from \"#orck/admin/lib/api/order-endpoints\"\nimport { amountFromInput } from \"#orck/admin/lib/format\"\n\nexport const usageActionLabels: Record<UsageAction, string> = {\n waive_balance: \"Waive balance\",\n mark_uncollectible: \"Mark uncollectible\",\n record_payment: \"Record payment\",\n}\nexport const usageActionDescriptions: Record<UsageAction, string> = {\n waive_balance:\n \"Forgive the remaining debt. Existing payments stay recorded and are not refunded.\",\n mark_uncollectible:\n \"Stop scheduled collection. What the order owes remains owed; collecting it again reopens it.\",\n record_payment:\n \"Record money already received outside automatic collection. This does not charge a payment method.\",\n}\n// usageActions are what staff who may change billing can do to a usage\n// order in its state: none while a collection is in progress.\nexport function usageActions(order: Order): UsageAction[] {\n const usage = order.usage\n if (order.collection_owner !== \"engine\" || !usage || BigInt(usage.amount_due) <= 0n) return []\n switch (order.status) {\n case \"open\":\n return [\"record_payment\", \"mark_uncollectible\", \"waive_balance\"]\n case \"uncollectible\":\n return [\"record_payment\", \"waive_balance\"]\n }\n return []\n}\nexport function usageResultMessage(result: Order | Payment) {\n if (\"kind\" in result) return \"Payment recorded.\"\n if (result.status === \"complete\") return \"Order paid.\"\n if (result.status === \"processing\")\n return \"Collection is pending verification. No new collection should be started.\"\n return \"Order updated.\"\n}\nexport function usagePaymentAmount(\n input: string,\n amountDue: string,\n decimals: number\n) {\n const amount = amountFromInput(input.trim(), decimals)\n if (amount === null)\n throw new Error(\n `Enter a positive amount with up to ${decimals} decimal places.`\n )\n if (BigInt(amount) <= 0n || BigInt(amount) > BigInt(amountDue))\n throw new Error(\n \"Payment must be positive and no greater than what the order owes.\"\n )\n return amount\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { useState } from \"react\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\nimport { Link, useParams } from \"#orck/admin/router\"\nimport type { ColumnDef } from \"@tanstack/react-table\"\n\nimport { CursorPager } from \"#orck/admin/components/cursor-pager\"\nimport { DataTable } from \"#orck/admin/components/data-table\"\nimport { StatusBadge } from \"#orck/admin/components/status-badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from \"#orck/admin/components/ui/dialog\"\nimport { useCursorPages } from \"#orck/admin/lib/cursor-pages\"\nimport type { Order, OrderUsage, Payment } from \"#orck/client/generated/wire\"\nimport type { UsageAction } from \"#orck/admin/lib/api/order-endpoints\"\n\nimport { useAdminUpdates } from \"#orck/admin/lib/capabilities\"\nimport {\n currencyScale,\n formatDate,\n formatNativeAmount,\n shortId,\n} from \"#orck/admin/lib/format\"\nimport { taxDisplay } from \"../customers/invoice-profile-model\"\nimport {\n usageActionDescriptions,\n usageActionLabels,\n usageActions,\n usagePaymentAmount,\n usageResultMessage,\n} from \"./model\"\n\nconst historyColumns: ColumnDef<Payment, unknown>[] = [\n {\n header: \"Paid\",\n cell: ({ row }) => formatDate(row.original.created_at),\n },\n {\n header: \"Amount\",\n cell: ({ row }) =>\n formatNativeAmount(row.original.amount, row.original.currency),\n },\n {\n header: \"Status\",\n cell: ({ row }) => <StatusBadge status={row.original.status} />,\n },\n {\n header: \"Method\",\n cell: ({ row }) => row.original.rail ?? row.original.channel,\n },\n {\n header: \"Reference\",\n cell: ({ row }) => row.original.transaction_id || shortId(row.original.id),\n },\n]\nexport function OrderDetailPage() {\n const { orderQueries } = useAdminServices()\n\n const { id = \"\" } = useParams()\n const { data: order, isPending, error } = useQuery(orderQueries.detail(id))\n if (isPending)\n return (\n <p>\n <AdminMessage id={\"Loading order…\"} />\n </p>\n )\n if (error)\n return (\n <p role=\"alert\" className=\"text-destructive\">\n {error.message}\n </p>\n )\n if (!order)\n return (\n <p>\n <AdminMessage id={\"Order not found.\"} />\n </p>\n )\n return <OrderDetail key={order.id} order={order} />\n}\nexport function OrderDetail({ order }: { order: Order }) {\n const { orderQueries } = useAdminServices()\n\n const paging = useCursorPages(order.id, 25)\n const history = useQuery(\n orderQueries.payments(order.id, paging.size, paging.cursor)\n )\n const failure = order.payment.last_payment_error\n return (\n <div className=\"flex flex-col gap-5\">\n <Link to=\"/orders\" className=\"text-sm underline\">\n <AdminMessage id={\"← Orders\"} />\n </Link>\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{order.number ?? order.id}</h1>\n <StatusBadge status={order.status} />\n {order.usage?.delinquent && <StatusBadge status=\"delinquent\" />}\n </div>\n <p className=\"text-sm\">\n <AdminMessage id={\"Customer\"} />{\" \"}\n <Link className=\"underline\" to={`/customers/${order.customer_id}`}>\n {order.customer_id}\n </Link>{\" \"}\n · {order.origin} · {order.currency}\n </p>\n <div className=\"grid gap-4 md:grid-cols-3\">\n {[\n [\"Total\", order.total],\n ...(order.usage\n ? [\n [\"Paid\", order.usage.amount_paid],\n [\"Unpaid\", order.usage.amount_due],\n ]\n : []),\n ].map(([label, value]) => (\n <Card key={String(label)}>\n <CardHeader>\n <CardTitle>{label}</CardTitle>\n </CardHeader>\n <CardContent className=\"text-xl\">\n {formatNativeAmount(value, order.currency)}\n </CardContent>\n </Card>\n ))}\n </div>\n {order.usage && <UsageFacts usage={order.usage} />}\n {order.renewal && (\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Renewal\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"grid gap-3 text-sm md:grid-cols-2\">\n <p>\n <AdminMessage id={\"Subscription:\"} />{\" \"}\n <Link\n className=\"underline\"\n to={`/subscriptions/${order.renewal.subscription_id}`}\n >\n {shortId(order.renewal.subscription_id)}\n </Link>\n </p>\n <p>\n <AdminMessage id={\"Period: \"} />\n {formatDate(order.renewal.period_starts_at)} –{\" \"}\n {formatDate(order.renewal.period_ends_at)}\n </p>\n <p>\n <AdminMessage id={\"Due: \"} />\n {formatDate(order.renewal.due_at)}\n </p>\n </CardContent>\n </Card>\n )}\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Lines\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"text-left\">\n <th>\n <AdminMessage id={\"Description\"} />\n </th>\n <th>\n <AdminMessage id={\"Quantity\"} />\n </th>\n <th className=\"text-right\">\n <AdminMessage id={\"Amount\"} />\n </th>\n </tr>\n </thead>\n <tbody>\n {order.lines.map((line) => (\n <tr key={line.id}>\n <td className=\"py-2\">\n {line.description}\n {line.source && (\n <p className=\"text-xs text-muted-foreground\">\n {line.source}\n </p>\n )}\n </td>\n <td>{line.quantity ?? \"—\"}</td>\n <td className=\"text-right\">\n {formatNativeAmount(line.amount, order.currency)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n {!order.lines.length && (\n <p>\n <AdminMessage id={\"No lines.\"} />\n </p>\n )}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Payment\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <p>\n <AdminMessage id={\"Status: \"} />\n <StatusBadge status={order.payment.status} />\n </p>\n {order.collection_owner !== \"engine\" && (\n <p>\n {order.collection_owner === \"nmi_schedule\"\n ? \"Collection follows the NMI schedule. Recovery is coordinated through the subscription.\"\n : \"The payment provider collects this bill. Payment activity appears in the history below.\"}\n </p>\n )}\n {order.provider_bills.map((bill, index) => (\n <p key={`${bill.psp_id}:${bill.kind}:${bill.reference}:${index}`}>\n {bill.reference || bill.kind}\n {bill.settled_at\n ? ` · Settled via ${bill.settlement_source} · ${formatDate(bill.settled_at)}`\n : \" · Settlement not yet verified\"}\n </p>\n ))}\n {failure && (\n <p>\n <AdminMessage id={\"Last failure: \"} />\n {failure.message}\n </p>\n )}\n {order.usage && <UsageActions order={order} />}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Payment history\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {history.error ? (\n <p role=\"alert\" className=\"text-destructive\">\n {history.error.message}\n </p>\n ) : (\n <>\n <DataTable\n columns={historyColumns}\n data={history.data?.data ?? []}\n loading={history.isPending}\n emptyMessage=\"No payments recorded.\"\n />\n <CursorPager\n pages={paging}\n rows={history.data?.data?.length ?? 0}\n nextCursor={history.data?.next_cursor}\n busy={history.isFetching}\n />\n </>\n )}\n </CardContent>\n </Card>\n </div>\n )\n}\n\nfunction UsageFacts({ usage }: { usage: OrderUsage }) {\n return (\n <Card>\n <CardHeader>\n <CardTitle>\n <AdminMessage id={\"Usage billed\"} />\n </CardTitle>\n </CardHeader>\n <CardContent className=\"grid gap-3 text-sm md:grid-cols-2\">\n <p>\n <AdminMessage id={\"Period: \"} />\n {formatDate(usage.period_starts_at)} –{\" \"}\n {formatDate(usage.period_ends_at)}\n </p>\n <p>\n <AdminMessage id={\"Due: \"} />\n {formatDate(usage.due_at)}\n </p>\n <p>\n <AdminMessage id={\"Collection:\"} />{\" \"}\n {usage.collection_method === \"send_invoice\"\n ? \"Manual remittance\"\n : \"Saved payment method\"}\n </p>\n <p>\n <AdminMessage id={\"Next attempt: \"} />\n {formatDate(usage.next_collection_attempt_at)}\n </p>\n <p>\n <AdminMessage id={\"Purchase order: \"} />\n {usage.po_number ?? \"—\"}\n </p>\n <p>\n <AdminMessage id={\"Memo: \"} />\n {usage.memo ?? \"—\"}\n </p>\n <div>\n <p className=\"font-medium\">\n <AdminMessage id={\"Billing contacts\"} />\n </p>\n {usage.billing_contacts.length ? (\n usage.billing_contacts.map((c, i) => (\n <p key={i}>\n {c.name ? `${c.name} · ` : \"\"}\n {c.email}\n </p>\n ))\n ) : (\n <p>—</p>\n )}\n </div>\n <div>\n <p className=\"font-medium\">\n <AdminMessage id={\"Tax details\"} />\n </p>\n {Object.entries(usage.tax ?? {}).map(([key, value]) => (\n <p key={key}>\n {key}: {taxDisplay(value)}\n </p>\n ))}\n </div>\n <p className=\"text-muted-foreground md:col-span-2\">\n <AdminMessage\n id={\n \"These are the customer&apos;s invoice profile when the order was billed. Editing the profile affects later orders.\"\n }\n />\n </p>\n </CardContent>\n </Card>\n )\n}\n\nfunction UsageActions({ order }: { order: Order }) {\n const { toast, usageActionMutation } = useAdminServices()\n\n const { id: adminId } = useAdminUI()\n\n const canUpdate = useAdminUpdates()\n const [action, setAction] = useState<UsageAction | null>(null)\n const [amount, setAmount] = useState(\"\")\n const [reference, setReference] = useState(\"\")\n const [error, setError] = useState<string | null>(null)\n const client = useQueryClient()\n const mutation = useMutation(usageActionMutation(client, order.customer_id))\n const actions = canUpdate ? usageActions(order) : []\n async function submit() {\n if (!action || mutation.isPending) return\n setError(null)\n try {\n if (!actions.includes(action))\n throw new Error(\n \"This action is no longer available. Refresh the order before continuing.\"\n )\n if (action === \"record_payment\" && !reference.trim())\n throw new Error(\"Enter the bank or payment reference.\")\n let paid: string | undefined\n if (action === \"record_payment\") {\n const scale = currencyScale(order.currency)\n if (scale === undefined)\n throw new Error(`${order.currency} is not a registered currency.`)\n paid = usagePaymentAmount(amount, order.usage!.amount_due, scale)\n }\n const result = await mutation.mutateAsync({\n id: order.id,\n action,\n amount: paid,\n reference: reference.trim(),\n })\n toast(usageResultMessage(result))\n setAction(null)\n } catch (failure) {\n setError(\n failure instanceof Error ? failure.message : \"Order action failed.\"\n )\n }\n }\n return (\n <>\n {order.status === \"processing\" && (\n <p role=\"status\">\n <AdminMessage\n id={\n \"A collection of this order is in progress. It must finish, or be resolved with \"\n }\n />\n <code>\n <AdminMessage id={\"openrails intents resolve\"} />\n </code>\n <AdminMessage id={\", before another action.\"} />\n </p>\n )}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((value) => (\n <Button\n key={value}\n variant={value === \"waive_balance\" ? \"destructive\" : \"outline\"}\n onClick={() => {\n setAction(value)\n setError(null)\n }}\n >\n {usageActionLabels[value]}\n </Button>\n ))}\n </div>\n {!actions.length && order.status !== \"processing\" && (\n <p className=\"text-muted-foreground\">\n <AdminMessage\n id={\n \"No actions are available for your permissions and this order&apos;s state.\"\n }\n />\n </p>\n )}\n <Dialog\n open={action !== null}\n onOpenChange={(open) => {\n if (!open && !mutation.isPending) setAction(null)\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {action ? usageActionLabels[action] : \"Order action\"}\n </DialogTitle>\n <DialogDescription>\n {action ? usageActionDescriptions[action] : \"\"}\n </DialogDescription>\n </DialogHeader>\n {action === \"record_payment\" && (\n <div className=\"space-y-3\">\n <div>\n <Label htmlFor={adminId(\"order-payment-amount\")}>\n <AdminMessage id={\"Amount (\"} />\n {order.currency})\n </Label>\n <Input\n id={adminId(\"order-payment-amount\")}\n inputMode=\"decimal\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n />\n </div>\n <div>\n <Label htmlFor={adminId(\"order-payment-reference\")}>\n <AdminMessage id={\"Payment reference\"} />\n </Label>\n <Input\n id={adminId(\"order-payment-reference\")}\n maxLength={255}\n value={reference}\n onChange={(e) => setReference(e.target.value)}\n />\n </div>\n </div>\n )}\n {error && (\n <p role=\"alert\" className=\"text-destructive\">\n {error}\n </p>\n )}\n <DialogFooter>\n <Button\n variant=\"outline\"\n disabled={mutation.isPending}\n onClick={() => setAction(null)}\n >\n <AdminMessage id={\"Cancel\"} />\n </Button>\n <Button\n disabled={\n mutation.isPending || !action || !actions.includes(action)\n }\n onClick={() => void submit()}\n >\n {mutation.isPending ? \"Working…\" : \"Confirm\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n )\n}\n"],"mappings":"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"}
@@ -1,20 +1,20 @@
1
- import { E as e, c as t, f as n, p as r, r as i, s as a, w as o } from "./admin-utils-BK4Vh1o_.js";
2
- import { t as s } from "./admin-button-CTL3DgOt.js";
3
- import { t as c } from "./admin-input-CcfQfJFN.js";
4
- import { a as l } from "./admin-capabilities-BuigAgtm.js";
5
- import { t as u } from "./admin-auth-DQGHtt0j.js";
1
+ import { E as e, c as t, f as n, p as r, r as i, s as a, w as o } from "./admin-utils-DnVY5fYd.js";
2
+ import { t as s } from "./admin-button-Oip73Plq.js";
3
+ import { t as c } from "./admin-input-DO5lvCLL.js";
4
+ import { a as l } from "./admin-capabilities-BGv7oG8v.js";
5
+ import { t as u } from "./admin-auth-CiuZ-Hlm.js";
6
6
  import { a as d, i as f, n as p, o as m, s as h, t as g, u as _ } from "./admin-format-DoohJ7Fg.js";
7
7
  import { t as v } from "./admin-form-field-errors-hbUMIriS.js";
8
- import { a as y, i as b, n as x, r as S, t as C } from "./admin-select-DBgprVW6.js";
9
- import { n as w, r as T } from "./admin-dom-uMmZzRvU.js";
10
- import { a as E, n as D, o as O, r as k, s as A, t as j } from "./admin-table-CH9TrXJf.js";
11
- import { t as M } from "./admin-linked-table-row-BsaUruCN.js";
12
- import { t as N } from "./admin-badge-DR5-1qd8.js";
13
- import { t as P } from "./admin-status-badge-BFPgo71d.js";
14
- import { a as F, i as I, n as L, o as R, r as z, s as ee, t as B } from "./admin-dialog-BjuKI5Hp.js";
15
- import { t as V } from "./admin-label-BiEN5cjb.js";
8
+ import { a as y, i as b, n as x, r as S, t as C } from "./admin-select-CUXvh6j1.js";
9
+ import { n as w, r as T } from "./admin-dom-lnNSQ7ke.js";
10
+ import { a as E, n as D, o as O, r as k, s as A, t as j } from "./admin-table-CWhiCb9d.js";
11
+ import { t as M } from "./admin-linked-table-row-5vFb6rXY.js";
12
+ import { t as N } from "./admin-badge-VCGbnfiN.js";
13
+ import { t as P } from "./admin-status-badge-CwqIU8tK.js";
14
+ import { a as F, i as I, n as L, o as R, r as z, s as ee, t as B } from "./admin-dialog-Ffx95AIT.js";
15
+ import { t as V } from "./admin-label-BzJpr3lg.js";
16
16
  import { n as te } from "./admin-dialog-width-BPrgdYlj.js";
17
- import { a as H, o as U, r as W, t as G } from "./admin-card-bzAks3-3.js";
17
+ import { a as H, o as U, r as W, t as G } from "./admin-card-DGbi6ZHZ.js";
18
18
  import { n as ne, t as re } from "./admin-invoice-profile-model-Cgjy3zV8.js";
19
19
  import { t as ie } from "./admin-dunning-B2zgtrOo.js";
20
20
  import * as K from "react";
@@ -1309,4 +1309,4 @@ function Me({ contact: e }) {
1309
1309
  //#endregion
1310
1310
  export { we as CustomerDetailPage };
1311
1311
 
1312
- //# sourceMappingURL=admin-detail-CGOyqs7s.js.map
1312
+ //# sourceMappingURL=admin-detail-Dc7rU4mM.js.map