@openrails/billing-ui 0.241.0 → 0.243.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 (265) hide show
  1. package/CHANGELOG.md +27 -11
  2. package/README.md +41 -8
  3. package/dist/admin/billing-admin.d.ts +3 -0
  4. package/dist/admin/components/app-sidebar.d.ts +1 -0
  5. package/dist/admin/components/confirm.d.ts +4 -0
  6. package/dist/admin/components/cursor-pager.d.ts +8 -0
  7. package/dist/admin/components/data-table.d.ts +14 -0
  8. package/dist/admin/components/fact-card.d.ts +5 -0
  9. package/dist/admin/components/form-field-errors.d.ts +3 -0
  10. package/dist/admin/components/linked-table-row.d.ts +5 -0
  11. package/dist/admin/components/logo.d.ts +3 -0
  12. package/dist/admin/components/no-access.d.ts +3 -0
  13. package/dist/admin/components/no-merchants.d.ts +1 -0
  14. package/dist/admin/components/notification-bell.d.ts +2 -0
  15. package/dist/admin/components/route-error.d.ts +3 -0
  16. package/dist/admin/components/site-header.d.ts +9 -0
  17. package/dist/admin/components/status-badge.d.ts +3 -0
  18. package/dist/admin/components/typed-confirm-dialog.d.ts +11 -0
  19. package/dist/admin/components/ui/alert-dialog.d.ts +18 -0
  20. package/dist/admin/components/ui/avatar.d.ts +11 -0
  21. package/dist/admin/components/ui/badge.d.ts +7 -0
  22. package/dist/admin/components/ui/breadcrumb.d.ts +10 -0
  23. package/dist/admin/components/ui/button.d.ts +8 -0
  24. package/dist/admin/components/ui/card.d.ts +11 -0
  25. package/dist/admin/components/ui/chart.d.ts +44 -0
  26. package/dist/admin/components/ui/dialog.d.ts +17 -0
  27. package/dist/admin/components/ui/dropdown-menu.d.ts +29 -0
  28. package/dist/admin/components/ui/input.d.ts +3 -0
  29. package/dist/admin/components/ui/label.d.ts +3 -0
  30. package/dist/admin/components/ui/select.d.ts +15 -0
  31. package/dist/admin/components/ui/separator.d.ts +3 -0
  32. package/dist/admin/components/ui/sheet.d.ts +14 -0
  33. package/dist/admin/components/ui/sidebar.d.ts +63 -0
  34. package/dist/admin/components/ui/skeleton.d.ts +2 -0
  35. package/dist/admin/components/ui/sonner.d.ts +3 -0
  36. package/dist/admin/components/ui/switch.d.ts +5 -0
  37. package/dist/admin/components/ui/table.d.ts +10 -0
  38. package/dist/admin/components/ui/tabs.d.ts +10 -0
  39. package/dist/admin/components/ui/textarea.d.ts +3 -0
  40. package/dist/admin/components/ui/tooltip.d.ts +6 -0
  41. package/dist/admin/context.d.ts +1193 -0
  42. package/dist/admin/hooks/use-mobile.d.ts +1 -0
  43. package/dist/admin/index.d.ts +5 -0
  44. package/dist/admin/layouts/app-layout.d.ts +4 -0
  45. package/dist/admin/lib/api/client.d.ts +64 -0
  46. package/dist/admin/lib/api/copilot.d.ts +6 -0
  47. package/dist/admin/lib/api/credit-endpoints.d.ts +8 -0
  48. package/dist/admin/lib/api/credit-types.d.ts +9 -0
  49. package/dist/admin/lib/api/endpoints.d.ts +133 -0
  50. package/dist/admin/lib/api/index.d.ts +89 -0
  51. package/dist/admin/lib/api/invoice-profile-endpoints.d.ts +6 -0
  52. package/dist/admin/lib/api/metrics.d.ts +68 -0
  53. package/dist/admin/lib/api/order-endpoints.d.ts +21 -0
  54. package/dist/admin/lib/api/types.d.ts +122 -0
  55. package/dist/admin/lib/auth.d.ts +6 -0
  56. package/dist/admin/lib/capabilities.d.ts +13 -0
  57. package/dist/admin/lib/chunk-error.d.ts +1 -0
  58. package/dist/admin/lib/confirm.d.ts +11 -0
  59. package/dist/admin/lib/credit-queries.d.ts +23 -0
  60. package/dist/admin/lib/csv.d.ts +3 -0
  61. package/dist/admin/lib/cursor-pages.d.ts +13 -0
  62. package/dist/admin/lib/dialog-width.d.ts +6 -0
  63. package/dist/admin/lib/dom.d.ts +1 -0
  64. package/dist/admin/lib/duration.d.ts +3 -0
  65. package/dist/admin/lib/format.d.ts +23 -0
  66. package/dist/admin/lib/mount.d.ts +6 -0
  67. package/dist/admin/lib/mutations.d.ts +125 -0
  68. package/dist/admin/lib/order-queries.d.ts +29 -0
  69. package/dist/admin/lib/queries.d.ts +369 -0
  70. package/dist/admin/lib/query-client.d.ts +3 -0
  71. package/dist/admin/lib/toast.d.ts +10 -0
  72. package/dist/admin/lib/utils.d.ts +2 -0
  73. package/dist/admin/messages.d.ts +670 -0
  74. package/dist/admin/navigation.d.ts +14 -0
  75. package/dist/admin/pages/catalog/application-dialog.d.ts +2 -0
  76. package/dist/admin/pages/catalog/copilot-panel.d.ts +4 -0
  77. package/dist/admin/pages/catalog/index.d.ts +4 -0
  78. package/dist/admin/pages/catalog/meter-form.d.ts +6 -0
  79. package/dist/admin/pages/catalog/metering-model.d.ts +67 -0
  80. package/dist/admin/pages/catalog/metering.d.ts +3 -0
  81. package/dist/admin/pages/catalog/price-detail.d.ts +2 -0
  82. package/dist/admin/pages/catalog/price-format.d.ts +3 -0
  83. package/dist/admin/pages/catalog/price-wizard-logic.d.ts +20 -0
  84. package/dist/admin/pages/catalog/price-wizard.d.ts +10 -0
  85. package/dist/admin/pages/catalog/psp-links.d.ts +10 -0
  86. package/dist/admin/pages/catalog/rate-card-editor.d.ts +10 -0
  87. package/dist/admin/pages/customers/credit-form.d.ts +14 -0
  88. package/dist/admin/pages/customers/credits.d.ts +5 -0
  89. package/dist/admin/pages/customers/default-card-badges.d.ts +3 -0
  90. package/dist/admin/pages/customers/detail.d.ts +5 -0
  91. package/dist/admin/pages/customers/grant-duration.d.ts +32 -0
  92. package/dist/admin/pages/customers/index.d.ts +2 -0
  93. package/dist/admin/pages/customers/invoice-profile-model.d.ts +18 -0
  94. package/dist/admin/pages/customers/invoice-profile.d.ts +9 -0
  95. package/dist/admin/pages/dashboard/index.d.ts +2 -0
  96. package/dist/admin/pages/dashboard/lib.d.ts +48 -0
  97. package/dist/admin/pages/dashboard/range-picker.d.ts +1 -0
  98. package/dist/admin/pages/dashboard/range.d.ts +34 -0
  99. package/dist/admin/pages/dashboard/reports-model.d.ts +29 -0
  100. package/dist/admin/pages/dashboard/reports.d.ts +2 -0
  101. package/dist/admin/pages/dashboard/use-range.d.ts +5 -0
  102. package/dist/admin/pages/dashboard/widget-editor.d.ts +8 -0
  103. package/dist/admin/pages/dashboard/widget-tile.d.ts +9 -0
  104. package/dist/admin/pages/dashboard/widget-viz.d.ts +12 -0
  105. package/dist/admin/pages/ops/index.d.ts +2 -0
  106. package/dist/admin/pages/orders/detail.d.ts +5 -0
  107. package/dist/admin/pages/orders/index.d.ts +1 -0
  108. package/dist/admin/pages/orders/model.d.ts +7 -0
  109. package/dist/admin/pages/payments/attempts.d.ts +7 -0
  110. package/dist/admin/pages/payments/detail.d.ts +2 -0
  111. package/dist/admin/pages/payments/health-model.d.ts +149 -0
  112. package/dist/admin/pages/payments/health.d.ts +2 -0
  113. package/dist/admin/pages/payments/index.d.ts +2 -0
  114. package/dist/admin/pages/settings/configuration-edit.d.ts +9 -0
  115. package/dist/admin/pages/settings/index.d.ts +9 -0
  116. package/dist/admin/pages/settings/notifications.d.ts +2 -0
  117. package/dist/admin/pages/settings/setting-fields.d.ts +20 -0
  118. package/dist/admin/pages/subscriptions/change-subscription-dialog.d.ts +16 -0
  119. package/dist/admin/pages/subscriptions/detail.d.ts +2 -0
  120. package/dist/admin/pages/subscriptions/dunning.d.ts +2 -0
  121. package/dist/admin/pages/subscriptions/index.d.ts +2 -0
  122. package/dist/admin/pages/subscriptions/subscription-change-options.d.ts +23 -0
  123. package/dist/admin/pages/subscriptions/views.d.ts +15 -0
  124. package/dist/admin/router.d.ts +32 -0
  125. package/dist/admin/routes.d.ts +5 -0
  126. package/dist/admin/summary.d.ts +27 -0
  127. package/dist/admin/theme.d.ts +2 -0
  128. package/dist/admin/types.d.ts +56 -0
  129. package/dist/admin/ui-context.d.ts +14 -0
  130. package/dist/admin-attempts-lAoW-Urd.js +419 -0
  131. package/dist/admin-attempts-lAoW-Urd.js.map +1 -0
  132. package/dist/admin-auth-DQGHtt0j.js +14 -0
  133. package/dist/admin-auth-DQGHtt0j.js.map +1 -0
  134. package/dist/admin-badge-DR5-1qd8.js +31 -0
  135. package/dist/admin-badge-DR5-1qd8.js.map +1 -0
  136. package/dist/admin-button-CTL3DgOt.js +46 -0
  137. package/dist/admin-button-CTL3DgOt.js.map +1 -0
  138. package/dist/admin-capabilities-BuigAgtm.js +59 -0
  139. package/dist/admin-capabilities-BuigAgtm.js.map +1 -0
  140. package/dist/admin-card-bzAks3-3.js +51 -0
  141. package/dist/admin-card-bzAks3-3.js.map +1 -0
  142. package/dist/admin-catalog-CC7I4n0_.js +1189 -0
  143. package/dist/admin-catalog-CC7I4n0_.js.map +1 -0
  144. package/dist/admin-confirm-katGq0Qo.js +12 -0
  145. package/dist/admin-confirm-katGq0Qo.js.map +1 -0
  146. package/dist/admin-csv-CPoNZj2D.js +16 -0
  147. package/dist/admin-csv-CPoNZj2D.js.map +1 -0
  148. package/dist/admin-customers-D8u5gq3M.js +160 -0
  149. package/dist/admin-customers-D8u5gq3M.js.map +1 -0
  150. package/dist/admin-dashboard-DqqFjOzq.js +420 -0
  151. package/dist/admin-dashboard-DqqFjOzq.js.map +1 -0
  152. package/dist/admin-data-table-qfXLOFmN.js +96 -0
  153. package/dist/admin-data-table-qfXLOFmN.js.map +1 -0
  154. package/dist/admin-detail-5aNNvrc0.js +324 -0
  155. package/dist/admin-detail-5aNNvrc0.js.map +1 -0
  156. package/dist/admin-detail-7p684Uyc.js +342 -0
  157. package/dist/admin-detail-7p684Uyc.js.map +1 -0
  158. package/dist/admin-detail-CGOyqs7s.js +1312 -0
  159. package/dist/admin-detail-CGOyqs7s.js.map +1 -0
  160. package/dist/admin-detail-DUAJQg8G.js +710 -0
  161. package/dist/admin-detail-DUAJQg8G.js.map +1 -0
  162. package/dist/admin-dialog-BjuKI5Hp.js +88 -0
  163. package/dist/admin-dialog-BjuKI5Hp.js.map +1 -0
  164. package/dist/admin-dialog-width-BPrgdYlj.js +6 -0
  165. package/dist/admin-dialog-width-BPrgdYlj.js.map +1 -0
  166. package/dist/admin-dom-uMmZzRvU.js +149 -0
  167. package/dist/admin-dom-uMmZzRvU.js.map +1 -0
  168. package/dist/admin-dropdown-menu-BW1D_h6s.js +69 -0
  169. package/dist/admin-dropdown-menu-BW1D_h6s.js.map +1 -0
  170. package/dist/admin-dunning-B2zgtrOo.js +10 -0
  171. package/dist/admin-dunning-B2zgtrOo.js.map +1 -0
  172. package/dist/admin-fact-card-DO_fHosg.js +20 -0
  173. package/dist/admin-fact-card-DO_fHosg.js.map +1 -0
  174. package/dist/admin-form-field-errors-hbUMIriS.js +14 -0
  175. package/dist/admin-form-field-errors-hbUMIriS.js.map +1 -0
  176. package/dist/admin-format-DoohJ7Fg.js +136 -0
  177. package/dist/admin-format-DoohJ7Fg.js.map +1 -0
  178. package/dist/admin-health-B4jN2LwR.js +983 -0
  179. package/dist/admin-health-B4jN2LwR.js.map +1 -0
  180. package/dist/admin-input-CcfQfJFN.js +17 -0
  181. package/dist/admin-input-CcfQfJFN.js.map +1 -0
  182. package/dist/admin-invoice-profile-model-Cgjy3zV8.js +53 -0
  183. package/dist/admin-invoice-profile-model-Cgjy3zV8.js.map +1 -0
  184. package/dist/admin-label-BiEN5cjb.js +15 -0
  185. package/dist/admin-label-BiEN5cjb.js.map +1 -0
  186. package/dist/admin-linked-table-row-BsaUruCN.js +26 -0
  187. package/dist/admin-linked-table-row-BsaUruCN.js.map +1 -0
  188. package/dist/admin-metering-BGAXbT23.js +1702 -0
  189. package/dist/admin-metering-BGAXbT23.js.map +1 -0
  190. package/dist/admin-ops-B3mcr76u.js +217 -0
  191. package/dist/admin-ops-B3mcr76u.js.map +1 -0
  192. package/dist/admin-orders-dxC99Idl.js +192 -0
  193. package/dist/admin-orders-dxC99Idl.js.map +1 -0
  194. package/dist/admin-payments-Bs7HSfP0.js +246 -0
  195. package/dist/admin-payments-Bs7HSfP0.js.map +1 -0
  196. package/dist/admin-price-detail-DRquxpA9.js +482 -0
  197. package/dist/admin-price-detail-DRquxpA9.js.map +1 -0
  198. package/dist/admin-price-format-DM1qORWI.js +44 -0
  199. package/dist/admin-price-format-DM1qORWI.js.map +1 -0
  200. package/dist/admin-price-wizard-CI7K-2Nz.js +357 -0
  201. package/dist/admin-price-wizard-CI7K-2Nz.js.map +1 -0
  202. package/dist/admin-range-picker-Dr2M1EZr.js +192 -0
  203. package/dist/admin-range-picker-Dr2M1EZr.js.map +1 -0
  204. package/dist/admin-reports-CywKLiSA.js +320 -0
  205. package/dist/admin-reports-CywKLiSA.js.map +1 -0
  206. package/dist/admin-select-DBgprVW6.js +81 -0
  207. package/dist/admin-select-DBgprVW6.js.map +1 -0
  208. package/dist/admin-settings-Bmoy95uO.js +1434 -0
  209. package/dist/admin-settings-Bmoy95uO.js.map +1 -0
  210. package/dist/admin-skeleton-DsM7crYi.js +14 -0
  211. package/dist/admin-skeleton-DsM7crYi.js.map +1 -0
  212. package/dist/admin-status-badge-BFPgo71d.js +38 -0
  213. package/dist/admin-status-badge-BFPgo71d.js.map +1 -0
  214. package/dist/admin-subscriptions-CLYc_HEV.js +301 -0
  215. package/dist/admin-subscriptions-CLYc_HEV.js.map +1 -0
  216. package/dist/admin-switch-BJUxLCsa.js +20 -0
  217. package/dist/admin-switch-BJUxLCsa.js.map +1 -0
  218. package/dist/admin-table-CH9TrXJf.js +61 -0
  219. package/dist/admin-table-CH9TrXJf.js.map +1 -0
  220. package/dist/admin-tabs-528FJMjt.js +46 -0
  221. package/dist/admin-tabs-528FJMjt.js.map +1 -0
  222. package/dist/admin-textarea-DEz38RaI.js +15 -0
  223. package/dist/admin-textarea-DEz38RaI.js.map +1 -0
  224. package/dist/admin-typed-confirm-dialog-DU7m9-O7.js +66 -0
  225. package/dist/admin-typed-confirm-dialog-DU7m9-O7.js.map +1 -0
  226. package/dist/admin-utils-BK4Vh1o_.js +1809 -0
  227. package/dist/admin-utils-BK4Vh1o_.js.map +1 -0
  228. package/dist/admin-widget-viz-Da48c-Zf.js +581 -0
  229. package/dist/admin-widget-viz-Da48c-Zf.js.map +1 -0
  230. package/dist/admin.css +3 -0
  231. package/dist/admin.js +2164 -0
  232. package/dist/admin.js.map +1 -0
  233. package/dist/appearance.d.ts +1 -1
  234. package/dist/client/generated/error-codes.d.ts +1 -1
  235. package/dist/client/generated/routes.d.ts +2156 -189
  236. package/dist/client/generated/wire.d.ts +1265 -50
  237. package/dist/client/types.d.ts +0 -1
  238. package/dist/{client-Cxz_miQj.js → client-PjivPHmE.js} +2 -3
  239. package/dist/client-PjivPHmE.js.map +1 -0
  240. package/dist/client.js +1 -1
  241. package/dist/{hooks-aKefXeMO.js → hooks-Ckd8F2JF.js} +8 -8
  242. package/dist/hooks-Ckd8F2JF.js.map +1 -0
  243. package/dist/index.d.ts +1 -1
  244. package/dist/index.js +12 -12
  245. package/dist/index.js.map +1 -1
  246. package/dist/lib/{offer-label.d.ts → price-label.d.ts} +1 -1
  247. package/dist/locales/de.js +1 -1
  248. package/dist/locales/de.js.map +1 -1
  249. package/dist/locales/en.d.ts +1 -1
  250. package/dist/locales/en.js +1 -1
  251. package/dist/locales/en.js.map +1 -1
  252. package/dist/locales/es.js +1 -1
  253. package/dist/locales/es.js.map +1 -1
  254. package/dist/locales/ja.js +1 -1
  255. package/dist/locales/ja.js.map +1 -1
  256. package/dist/locales/ko.js +1 -1
  257. package/dist/locales/ko.js.map +1 -1
  258. package/dist/locales/zh.js +1 -1
  259. package/dist/locales/zh.js.map +1 -1
  260. package/dist/{offers.d.ts → product-list.d.ts} +5 -5
  261. package/dist/react.js +1 -1
  262. package/dist/styles.css +1 -1
  263. package/package.json +28 -6
  264. package/dist/client-Cxz_miQj.js.map +0 -1
  265. package/dist/hooks-aKefXeMO.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-health-B4jN2LwR.js","names":[],"sources":["../src/admin/pages/payments/health-model.ts","../src/admin/pages/payments/health.tsx"],"sourcesContent":["// Payments → Health: the metrics queries behind each panel, the shaping of\n// their results, and the list URL every tile and cell opens. Metric and list\n// filters share names, so a drill-down carries them unchanged; only the PSP\n// differs (metrics group by its key, lists take its id).\nimport type {\n MetricsCell,\n MetricsQuery,\n MetricsResult,\n} from \"#orck/admin/lib/api/metrics\"\nimport { indexColumns } from \"#orck/admin/pages/dashboard/lib\"\n\nexport const OWNERS = [\n { value: \"\", label: \"All owners\" },\n { value: \"nmi_schedule\", label: \"NMI-owned\" },\n { value: \"engine\", label: \"OpenRails-owned\" },\n { value: \"provider\", label: \"Provider-owned\" },\n] as const\n\nexport const RANGES = [\n { value: \"7d\", label: \"Last 7 days\" },\n { value: \"30d\", label: \"Last 30 days\" },\n { value: \"90d\", label: \"Last 90 days\" },\n] as const\n\n// Scope is the page's controls: owner, PSP id and the trailing range.\nexport interface Scope {\n owner: string\n psp?: { id: string }\n last: string\n}\n\ntype Filters = Record<string, string[]>\n\nexport const NEW_CARD: Filters = {\n kind: [\"verify\", \"initial\"],\n card_entry: [\"new\"],\n}\nexport const FAILED_CATEGORIES = [\n \"card_data\",\n \"issuer_soft\",\n \"issuer_hard\",\n \"gateway_rule\",\n \"system_error\",\n \"unknown\",\n]\nexport const FIRST_FAILED = [\"declined\", \"error\", \"missed\"]\n\nfunction scoped(scope: Scope, extra: Filters = {}): Filters | undefined {\n const out: Filters = { ...extra }\n if (scope.owner) out.owner = [scope.owner]\n if (scope.psp) out.psp = [scope.psp.id]\n return Object.keys(out).length ? out : undefined\n}\n\nexport interface Tile {\n id: string\n title: string\n measure: string\n // lower: a rise is bad news.\n better: \"lower\" | \"higher\"\n query: (scope: Scope) => MetricsQuery\n list: \"attempts\" | \"cycles\"\n listFilters: Filters\n}\n\nconst compared = (\n measures: string[],\n scope: Scope,\n filters: Filters = {}\n): MetricsQuery => ({\n measures,\n range: { last: scope.last },\n filters: scoped(scope, filters),\n compare: \"previous_period\",\n})\n\nconst CYCLE_MEASURES = [\n \"rebill_first_failure_rate\",\n \"rebills_missed\",\n \"dunning_recovery_rate\",\n \"rebill_collection_rate\",\n]\nconst cycleTiles = (scope: Scope) => compared(CYCLE_MEASURES, scope)\n\nexport const TILES: Tile[] = [\n {\n id: \"new-card-decline\",\n title: \"New-card decline rate\",\n measure: \"attempt_failure_rate\",\n better: \"lower\",\n query: (scope) => compared([\"attempt_failure_rate\"], scope, NEW_CARD),\n list: \"attempts\",\n listFilters: { ...NEW_CARD, category: FAILED_CATEGORIES },\n },\n {\n id: \"checkout-failure\",\n title: \"New-card checkout failure rate\",\n measure: \"checkout_failure_rate\",\n better: \"lower\",\n query: (scope) => compared([\"checkout_failure_rate\"], scope),\n list: \"attempts\",\n listFilters: { card_entry: [\"new\"] },\n },\n {\n id: \"rebill-first-failure\",\n title: \"Rebill first-attempt failure rate\",\n measure: \"rebill_first_failure_rate\",\n better: \"lower\",\n query: cycleTiles,\n list: \"cycles\",\n listFilters: { first_outcome: FIRST_FAILED },\n },\n {\n id: \"missed\",\n title: \"Missed rebills\",\n measure: \"rebills_missed\",\n better: \"lower\",\n query: cycleTiles,\n list: \"cycles\",\n listFilters: { first_outcome: [\"missed\"] },\n },\n {\n id: \"recovery\",\n title: \"Dunning recovery rate\",\n measure: \"dunning_recovery_rate\",\n better: \"higher\",\n query: cycleTiles,\n list: \"cycles\",\n listFilters: { first_outcome: FIRST_FAILED, outcome: [\"collected\"] },\n },\n {\n id: \"collection\",\n title: \"Rebill collection rate\",\n measure: \"rebill_collection_rate\",\n better: \"higher\",\n query: cycleTiles,\n list: \"cycles\",\n listFilters: { outcome: [\"collected\", \"lost\"] },\n },\n]\n\nexport interface TileValue {\n value: MetricsCell\n unit?: string\n // change is the move from the previous period: percentage points for a\n // rate, the difference for a count; null when either side is empty.\n change: number | null\n worse: boolean\n}\n\nexport function tileValue(\n result: MetricsResult | undefined,\n tile: Tile\n): TileValue | undefined {\n if (!result) return undefined\n const idx = indexColumns(result.columns)\n const m = idx.measures.find((c) => c.name === tile.measure)\n if (!m) return undefined\n const current = result.rows[0]?.[m.index] ?? null\n const previous = result.compare_rows?.[0]?.[m.index] ?? null\n let change: number | null = null\n if (current !== null && previous !== null) {\n change = Number(current) - Number(previous)\n if (!Number.isFinite(change)) change = null\n }\n const worse =\n change !== null &&\n change !== 0 &&\n (tile.better === \"lower\" ? change > 0 : change < 0)\n return { value: current, unit: m.unit, change, worse }\n}\n\nexport function formatChange(v: TileValue): string {\n if (v.change === null) return \"no previous period\"\n const sign = v.change > 0 ? \"+\" : \"\"\n if (v.unit === \"ratio\")\n return `${sign}${(v.change * 100).toFixed(1)} pp vs previous period`\n return `${sign}${v.change.toLocaleString()} vs previous period`\n}\n\nexport const trendQueries = (scope: Scope) => {\n const weekly = (measure: string, filters: Filters = {}): MetricsQuery => ({\n measures: [measure],\n by: [\"time\", \"owner\"],\n grain: \"week\",\n range: { last: \"12w\" },\n filters: scoped(scope, filters),\n })\n return {\n newCard: weekly(\"attempt_failure_rate\", NEW_CARD),\n rebill: weekly(\"rebill_first_failure_rate\"),\n }\n}\n\nexport const reasonsQuery = (scope: Scope): MetricsQuery => ({\n measures: [\"failed_attempts\"],\n by: [\"category\", \"reason\", \"response_code\"],\n range: { last: scope.last },\n filters: scoped(scope),\n compare: \"previous_period\",\n})\n\nexport interface ReasonRow {\n category: string\n reason: string\n code: string\n count: number\n share: number\n // previous is the count in the previous period (0 when absent).\n previous: number\n}\n\nexport interface ReasonGroup {\n category: string\n count: number\n share: number\n rows: ReasonRow[]\n}\n\n// reasonGroups nests category → reason → code, largest first; share is of all\n// failed attempts in the range.\nexport function reasonGroups(result: MetricsResult | undefined): ReasonGroup[] {\n if (!result) return []\n const idx = indexColumns(result.columns)\n const col = (name: string) =>\n idx.dims.find((d) => d.name === name)?.index ?? -1\n const [cat, rsn, code] = [\n col(\"category\"),\n col(\"reason\"),\n col(\"response_code\"),\n ]\n const measure = idx.measures[0]?.index ?? -1\n if (cat < 0 || rsn < 0 || code < 0 || measure < 0) return []\n const key = (r: MetricsCell[]) => JSON.stringify([r[cat], r[rsn], r[code]])\n const previous = new Map<string, number>()\n for (const r of result.compare_rows ?? [])\n previous.set(key(r), Number(r[measure] ?? 0))\n const rows: ReasonRow[] = result.rows.map((r) => ({\n category: String(r[cat] ?? \"\"),\n reason: String(r[rsn] ?? \"\"),\n code: String(r[code] ?? \"\"),\n count: Number(r[measure] ?? 0),\n share: 0,\n previous: previous.get(key(r)) ?? 0,\n }))\n const total = rows.reduce((sum, r) => sum + r.count, 0)\n const groups = new Map<string, ReasonGroup>()\n for (const r of rows) {\n r.share = total ? r.count / total : 0\n let g = groups.get(r.category)\n if (!g) {\n g = { category: r.category, count: 0, share: 0, rows: [] }\n groups.set(r.category, g)\n }\n g.count += r.count\n g.rows.push(r)\n }\n return [...groups.values()]\n .map((g) => ({\n ...g,\n share: total ? g.count / total : 0,\n rows: g.rows.sort((a, b) => b.count - a.count),\n }))\n .sort((a, b) => b.count - a.count)\n}\n\nexport const checkQueries = (scope: Scope) => {\n const by = (dim: string): MetricsQuery => ({\n measures: [\"attempts\", \"attempt_failure_rate\"],\n by: [dim],\n range: { last: scope.last },\n filters: scoped(scope, NEW_CARD),\n })\n return { avs: by(\"avs_result\"), cvv: by(\"cvv_result\") }\n}\n\nexport interface CheckRow {\n result: string\n attempts: number\n failureRate: number | null\n}\n\nexport function checkRows(result: MetricsResult | undefined): CheckRow[] {\n if (!result) return []\n const idx = indexColumns(result.columns)\n const dim = idx.dims[0]?.index ?? -1\n const count = idx.measures.find((m) => m.name === \"attempts\")?.index ?? -1\n const rate =\n idx.measures.find((m) => m.name === \"attempt_failure_rate\")?.index ?? -1\n if (dim < 0 || count < 0 || rate < 0) return []\n return result.rows\n .map((r) => ({\n result: String(r[dim] ?? \"\"),\n attempts: Number(r[count] ?? 0),\n failureRate: r[rate] === null ? null : Number(r[rate]),\n }))\n .sort((a, b) => b.attempts - a.attempts)\n}\n\nexport const RECOVERY_ATTEMPTS = [\"1\", \"2\", \"3\", \"4\", \"5+\"]\nexport const RECOVERY_DAYS = [1, 3, 7, 14, 30]\n\nexport const recoveryQueries = (scope: Scope) => {\n const q = (measures: string[], by: string[]): MetricsQuery => ({\n measures,\n by,\n range: { last: scope.last },\n filters: scoped(scope),\n })\n return {\n rate: q([\"dunning_recovery_rate\", \"dunning_recovered\"], [\"owner\"]),\n byAttempt: q([\"dunning_recovered\"], [\"owner\", \"recovery_attempt\"]),\n byDays: q([\"dunning_recovered\"], [\"owner\", \"days_to_recover\"]),\n }\n}\n\nexport interface RecoveryCurve {\n owner: string\n // points[i] is the share of failed cycles recovered by step i.\n points: number[]\n}\n\n// recoveryCurves turns recoveries per step into cumulative shares of failed\n// cycles: a step's share is its recoveries over the owner's closed failed\n// cycles, which is recovered / recovery rate.\nexport function recoveryCurves(\n rate: MetricsResult | undefined,\n steps: MetricsResult | undefined,\n dimension: \"recovery_attempt\" | \"days_to_recover\"\n): RecoveryCurve[] {\n if (!rate || !steps) return []\n const r = indexColumns(rate.columns)\n const s = indexColumns(steps.columns)\n const rOwner = r.dims.find((d) => d.name === \"owner\")?.index ?? -1\n const rRate =\n r.measures.find((m) => m.name === \"dunning_recovery_rate\")?.index ?? -1\n const rCount =\n r.measures.find((m) => m.name === \"dunning_recovered\")?.index ?? -1\n const sOwner = s.dims.find((d) => d.name === \"owner\")?.index ?? -1\n const sStep = s.dims.find((d) => d.name === dimension)?.index ?? -1\n const sCount = s.measures[0]?.index ?? -1\n if ([rOwner, rRate, rCount, sOwner, sStep, sCount].includes(-1)) return []\n const failed = new Map<string, number>()\n for (const row of rate.rows) {\n const recovered = Number(row[rCount] ?? 0)\n const share = Number(row[rRate] ?? 0)\n if (recovered > 0 && share > 0)\n failed.set(String(row[rOwner]), recovered / share)\n }\n const buckets =\n dimension === \"recovery_attempt\" ? RECOVERY_ATTEMPTS : RECOVERY_DAYS\n const out: RecoveryCurve[] = []\n for (const [owner, denominator] of failed) {\n const points = buckets.map((bucket) => {\n let recovered = 0\n for (const row of steps.rows) {\n if (String(row[sOwner]) !== owner || row[sStep] === \"\") continue\n const step = String(row[sStep])\n const within =\n dimension === \"recovery_attempt\"\n ? RECOVERY_ATTEMPTS.indexOf(step) <=\n RECOVERY_ATTEMPTS.indexOf(String(bucket))\n : Number(step) <= Number(bucket)\n if (within) recovered += Number(row[sCount] ?? 0)\n }\n return recovered / denominator\n })\n out.push({ owner, points })\n }\n return out.sort((a, b) => a.owner.localeCompare(b.owner))\n}\n\nexport const missedQuery = (scope: Scope): MetricsQuery => ({\n measures: [\"rebills_missed\"],\n by: [\"miss_reason\", \"psp\"],\n range: { last: scope.last },\n filters: scoped(scope),\n})\n\nexport interface MissedRow {\n reason: string\n psp: string\n count: number\n}\n\nexport function missedRows(result: MetricsResult | undefined): MissedRow[] {\n if (!result) return []\n const idx = indexColumns(result.columns)\n const reason = idx.dims.find((d) => d.name === \"miss_reason\")?.index ?? -1\n const psp = idx.dims.find((d) => d.name === \"psp\")?.index ?? -1\n const count = idx.measures[0]?.index ?? -1\n if (reason < 0 || psp < 0 || count < 0) return []\n return result.rows\n .map((r) => ({\n reason: String(r[reason] ?? \"\"),\n psp: String(r[psp] ?? \"\"),\n count: Number(r[count] ?? 0),\n }))\n .filter((r) => r.reason !== \"\" && r.count > 0)\n .sort((a, b) => b.count - a.count)\n}\n\n// coverageQuery: how OpenRails learned of the providers' own charges.\nexport const coverageQuery = (scope: Scope): MetricsQuery => ({\n measures: [\"attempts\"],\n by: [\"psp\", \"observed_via\"],\n range: { last: scope.last },\n filters: scoped(scope, { source: [\"provider_schedule\"] }),\n})\n\nexport interface CoverageRow {\n psp: string\n webhook: number\n pull: number\n // coverage is the share learned by webhook.\n coverage: number | null\n}\n\nexport function coverageRows(result: MetricsResult | undefined): CoverageRow[] {\n if (!result) return []\n const idx = indexColumns(result.columns)\n const psp = idx.dims.find((d) => d.name === \"psp\")?.index ?? -1\n const via = idx.dims.find((d) => d.name === \"observed_via\")?.index ?? -1\n const count = idx.measures[0]?.index ?? -1\n if (psp < 0 || via < 0 || count < 0) return []\n const rows = new Map<string, CoverageRow>()\n for (const r of result.rows) {\n const key = String(r[psp] ?? \"\")\n let row = rows.get(key)\n if (!row) {\n row = { psp: key, webhook: 0, pull: 0, coverage: null }\n rows.set(key, row)\n }\n const n = Number(r[count] ?? 0)\n if (r[via] === \"webhook\") row.webhook += n\n else if (r[via] === \"pull\") row.pull += n\n }\n return [...rows.values()]\n .map((row) => {\n const seen = row.webhook + row.pull\n return { ...row, coverage: seen ? row.webhook / seen : null }\n })\n .sort((a, b) => a.psp.localeCompare(b.psp))\n}\n\n// listURL opens the attempt or cycle list with the panel's filters, the page's\n// scope and the query's resolved range.\nexport function listURL(\n list: \"attempts\" | \"cycles\",\n filters: Filters,\n scope: Scope,\n range?: { from: string; to: string },\n pspId?: string\n): string {\n const p = new URLSearchParams()\n for (const [key, values] of Object.entries(filters))\n if (values.length) p.set(key, values.join(\",\"))\n if (scope.owner && !p.has(\"owner\")) p.set(\"owner\", scope.owner)\n const psp = pspId ?? scope.psp?.id\n if (psp) p.set(\"psp_id\", psp)\n if (range) {\n p.set(list === \"attempts\" ? \"since\" : \"due_since\", range.from)\n p.set(list === \"attempts\" ? \"until\" : \"due_until\", range.to)\n }\n return `/payments/${list}?${p.toString()}`\n}\n\n// NMI's own transaction history, read daily per NMI PSP and kept 25 months. It\n// has no owner, so only the PSP scopes it.\nexport const NMI_KINDS = [\n { value: \"verification\", label: \"Card verifications\" },\n { value: \"one_off_sale\", label: \"One-off sales\" },\n { value: \"scheduled_rebill\", label: \"NMI-scheduled rebills\" },\n] as const\n\nexport const nmiHistoryQueries = (scope: Scope) => {\n const psp: Filters = scope.psp ? { psp: [scope.psp.id] } : {}\n const range = { last: \"25m\" }\n const months: MetricsQuery = {\n measures: [\"nmi_history_authorizations\", \"nmi_history_refusal_rate\"],\n by: [\"time\", \"nmi_kind\"],\n grain: \"month\",\n range,\n filters: scope.psp ? psp : undefined,\n }\n const reasons: MetricsQuery = {\n measures: [\"nmi_history_refused\"],\n by: [\"nmi_kind\", \"category\", \"reason\"],\n range,\n filters: { ...psp, category: FAILED_CATEGORIES },\n }\n // OpenRails' own NMI attempts by month: the first marks where it began.\n const recorded: MetricsQuery = {\n measures: [\"attempts\"],\n by: [\"time\"],\n grain: \"month\",\n range,\n filters: { ...psp, rail: [\"nmi\"] },\n }\n return { months, reasons, recorded }\n}\n\n// recordingSince is the first month OpenRails recorded an NMI attempt in.\nexport function recordingSince(\n result: MetricsResult | undefined\n): string | null {\n if (!result) return null\n const idx = indexColumns(result.columns)\n const count = idx.measures[0]?.index ?? -1\n if (idx.time < 0 || count < 0) return null\n const months = result.rows\n .filter((r) => Number(r[count] ?? 0) > 0)\n .map((r) => String(r[idx.time]))\n .sort()\n return months[0] ?? null\n}\n\nexport interface NMIHistoryCell {\n authorizations: number\n refusalRate: number | null\n}\n\nexport interface NMIHistoryMonth {\n month: string\n kinds: Record<string, NMIHistoryCell>\n // recorded: OpenRails recorded its own attempts by this month.\n recorded: boolean\n}\n\n// nmiHistoryMonths is newest first, only months NMI answered anything in.\nexport function nmiHistoryMonths(\n result: MetricsResult | undefined,\n since: string | null\n): NMIHistoryMonth[] {\n if (!result) return []\n const idx = indexColumns(result.columns)\n const kind = idx.dims.find((d) => d.name === \"nmi_kind\")?.index ?? -1\n const count =\n idx.measures.find((m) => m.name === \"nmi_history_authorizations\")?.index ??\n -1\n const rate =\n idx.measures.find((m) => m.name === \"nmi_history_refusal_rate\")?.index ?? -1\n if ([idx.time, kind, count, rate].includes(-1)) return []\n const months = new Map<string, NMIHistoryMonth>()\n for (const r of result.rows) {\n const authorizations = Number(r[count] ?? 0)\n if (authorizations === 0) continue\n const month = String(r[idx.time])\n let m = months.get(month)\n if (!m) {\n m = { month, kinds: {}, recorded: since !== null && month >= since }\n months.set(month, m)\n }\n m.kinds[String(r[kind])] = {\n authorizations,\n refusalRate: r[rate] === null ? null : Number(r[rate]),\n }\n }\n return [...months.values()].sort((a, b) => b.month.localeCompare(a.month))\n}\n\nexport interface NMIRefusal {\n kind: string\n category: string\n reason: string\n count: number\n // share is of every refusal in the range.\n share: number\n}\n\nexport function nmiRefusals(result: MetricsResult | undefined): NMIRefusal[] {\n if (!result) return []\n const idx = indexColumns(result.columns)\n const col = (name: string) =>\n idx.dims.find((d) => d.name === name)?.index ?? -1\n const [kind, cat, rsn] = [col(\"nmi_kind\"), col(\"category\"), col(\"reason\")]\n const count = idx.measures[0]?.index ?? -1\n if ([kind, cat, rsn, count].includes(-1)) return []\n const rows = result.rows\n .map((r) => ({\n kind: String(r[kind] ?? \"\"),\n category: String(r[cat] ?? \"\"),\n reason: String(r[rsn] ?? \"\"),\n count: Number(r[count] ?? 0),\n share: 0,\n }))\n .filter((r) => r.count > 0)\n const total = rows.reduce((sum, r) => sum + r.count, 0)\n return rows\n .map((r) => ({ ...r, share: total ? r.count / total : 0 }))\n .sort((a, b) => b.count - a.count)\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\n// Payments → Health: decline and rebill-failure health from the metrics API.\n// Every tile and cell opens the matching attempt or cycle list.\nimport { useMerchantConfig } from \"#orck/admin/lib/capabilities\"\nimport * as React from \"react\"\nimport { Link, useSearchParams } from \"#orck/admin/router\"\nimport { useQuery } from \"@tanstack/react-query\"\n\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"#orck/admin/components/ui/select\"\nimport { Skeleton } from \"#orck/admin/components/ui/skeleton\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport type { MetricsResult } from \"#orck/admin/lib/api/metrics\"\n\nimport { cn } from \"#orck/admin/lib/utils\"\nimport { formatBucket, formatMeasure } from \"#orck/admin/pages/dashboard/lib\"\nimport { WidgetVizView } from \"#orck/admin/pages/dashboard/widget-viz\"\n\nimport {\n checkQueries,\n checkRows,\n coverageQuery,\n coverageRows,\n FAILED_CATEGORIES,\n FIRST_FAILED,\n formatChange,\n listURL,\n missedQuery,\n missedRows,\n NEW_CARD,\n NMI_KINDS,\n nmiHistoryMonths,\n nmiHistoryQueries,\n nmiRefusals,\n OWNERS,\n RANGES,\n reasonGroups,\n reasonsQuery,\n RECOVERY_ATTEMPTS,\n RECOVERY_DAYS,\n recoveryCurves,\n recoveryQueries,\n recordingSince,\n TILES,\n tileValue,\n trendQueries,\n type RecoveryCurve,\n type Scope,\n type Tile,\n} from \"./health-model\"\n\nconst pct = (v: number | null) => (v === null ? \"—\" : formatMeasure(v, \"ratio\"))\nconst ownerLabel = (owner: string) =>\n OWNERS.find((o) => o.value === owner)?.label ?? owner\n\nexport function PaymentHealthPage() {\n const { text: adminText } = useAdminUI()\n\n const { adminQueries } = useAdminServices()\n\n const [params, setParams] = useSearchParams()\n const config = useMerchantConfig()\n const psps = useQuery({ ...adminQueries.psps(), enabled: config }).data?.data\n const pspId = params.get(\"psp_id\") ?? \"\"\n const psp = psps?.find((p) => p.id === pspId)\n const scope: Scope = {\n owner: params.get(\"owner\") ?? \"\",\n psp: psp ? { id: psp.id } : undefined,\n last: params.get(\"last\") ?? \"30d\",\n }\n const set = (key: string, value: string) => {\n const p = new URLSearchParams(params)\n if (value) p.set(key, value)\n else p.delete(key)\n setParams(p)\n }\n const pspKey = (id: string) => psps?.find((p) => p.id === id)?.key ?? id\n const nmi = psp\n ? psp.rail === \"nmi\"\n : Boolean(psps?.some((p) => p.rail === \"nmi\"))\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <h1 className=\"text-2xl font-semibold tracking-tight\">\n <AdminMessage id={\"Payment health\"} />\n </h1>\n <div className=\"flex flex-wrap items-center gap-3\">\n <Picker\n label={adminText(\"Owner\")}\n value={scope.owner}\n options={OWNERS.map((o) => ({ value: o.value, label: o.label }))}\n onChange={(v) => set(\"owner\", v)}\n />\n <Picker\n label={adminText(\"PSP\")}\n value={pspId}\n options={[\n { value: \"\", label: \"All PSPs\" },\n ...(psps ?? []).map((p) => ({\n value: p.id,\n label: `${p.key} · ${p.rail}`,\n })),\n ]}\n onChange={(v) => set(\"psp_id\", v)}\n />\n <Picker\n label={adminText(\"Range\")}\n value={scope.last}\n options={RANGES.map((r) => ({ value: r.value, label: r.label }))}\n onChange={(v) => set(\"last\", v === \"30d\" ? \"\" : v)}\n />\n </div>\n </div>\n\n <Tiles scope={scope} />\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <Trend\n title={adminText(\"New-card decline rate by week\")}\n query={trendQueries(scope).newCard}\n />\n <Trend\n title={adminText(\"Rebill first-attempt failure rate by week\")}\n query={trendQueries(scope).rebill}\n />\n </div>\n <Reasons scope={scope} />\n <Checks scope={scope} />\n <Recovery scope={scope} />\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <Missed scope={scope} pspKey={pspKey} />\n <Coverage scope={scope} pspKey={pspKey} />\n </div>\n {nmi && <NMIHistory scope={scope} />}\n </div>\n )\n}\n\nfunction Picker({\n label,\n value,\n options,\n onChange,\n}: {\n label: string\n value: string\n options: { value: string; label: string }[]\n onChange: (value: string) => void\n}) {\n // Base UI's select cannot hold \"\", so the empty option travels as \"all\".\n const items = options.map((o) => ({ ...o, value: o.value || \"all\" }))\n return (\n <Select\n items={items}\n value={value || \"all\"}\n onValueChange={(v) => onChange(!v || v === \"all\" ? \"\" : String(v))}\n >\n <SelectTrigger className=\"w-44\" aria-label={label}>\n <SelectValue placeholder={label} />\n </SelectTrigger>\n <SelectContent>\n {items.map((o) => (\n <SelectItem key={o.value} value={o.value}>\n {o.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n}\n\nfunction Panel({\n title,\n children,\n className,\n}: {\n title: string\n children: React.ReactNode\n className?: string\n}) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-sm\">{title}</CardTitle>\n </CardHeader>\n <CardContent>{children}</CardContent>\n </Card>\n )\n}\n\nfunction Loading() {\n return <Skeleton className=\"h-24 w-full\" />\n}\n\nfunction Empty({ label = \"Nothing in this range.\" }: { label?: string }) {\n return <p className=\"text-sm text-muted-foreground\">{label}</p>\n}\n\nfunction Tiles({ scope }: { scope: Scope }) {\n return (\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6\">\n {TILES.map((tile) => (\n <TileCard key={tile.id} tile={tile} scope={scope} />\n ))}\n </div>\n )\n}\n\nfunction TileCard({ tile, scope }: { tile: Tile; scope: Scope }) {\n const metrics = useAdminServices().adminQueries.widgetMetrics\n\n const { data, isPending } = useQuery(metrics(tile.query(scope)))\n const value = tileValue(data, tile)\n return (\n <Link\n to={listURL(tile.list, tile.listFilters, scope, data?.range)}\n className=\"rounded-xl focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none\"\n >\n <Card className=\"h-full gap-2 transition-colors hover:bg-muted/40\">\n <CardHeader>\n <CardTitle className=\"text-xs font-medium tracking-wider text-muted-foreground uppercase\">\n {tile.title}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-1\">\n {isPending || !value ? (\n <Skeleton className=\"h-8 w-20\" />\n ) : (\n <>\n <span className=\"text-2xl font-semibold tabular-nums\">\n {formatMeasure(value.value, value.unit)}\n </span>\n <span\n className={cn(\n \"text-xs\",\n value.change === null || value.change === 0\n ? \"text-muted-foreground\"\n : value.worse\n ? \"text-failed\"\n : \"text-settled\"\n )}\n >\n {formatChange(value)}\n </span>\n </>\n )}\n </CardContent>\n </Card>\n </Link>\n )\n}\n\nfunction Trend({\n title,\n query,\n}: {\n title: string\n query: ReturnType<typeof trendQueries>[\"newCard\"]\n}) {\n const metrics = useAdminServices().adminQueries.widgetMetrics\n\n const { data, isPending } = useQuery(metrics(query))\n return (\n <Panel title={title}>\n <div className=\"h-56\">\n {isPending || !data ? (\n <Loading />\n ) : (\n <WidgetVizView viz=\"line\" result={data} query={query} />\n )}\n </div>\n </Panel>\n )\n}\n\nfunction Reasons({ scope }: { scope: Scope }) {\n const { text: adminText } = useAdminUI()\n\n const metrics = useAdminServices().adminQueries.widgetMetrics\n\n const { data, isPending } = useQuery(metrics(reasonsQuery(scope)))\n const groups = reasonGroups(data)\n const link = (filters: Record<string, string[]>) =>\n listURL(\"attempts\", filters, scope, data?.range)\n return (\n <Panel title={adminText(\"Decline reasons\")}>\n {isPending ? (\n <Loading />\n ) : groups.length === 0 ? (\n <Empty label={adminText(\"No declines in this range.\")} />\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>\n <AdminMessage id={\"Category / reason\"} />\n </TableHead>\n <TableHead>\n <AdminMessage id={\"Code\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Declines\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Share\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Previous period\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {groups.map((g) => (\n <React.Fragment key={g.category}>\n <TableRow className=\"bg-muted/30\">\n <TableCell colSpan={2} className=\"font-medium\">\n <Link\n className=\"hover:underline\"\n to={link({ category: [g.category] })}\n >\n {g.category}\n </Link>\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {g.count}\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {pct(g.share)}\n </TableCell>\n <TableCell />\n </TableRow>\n {g.rows.map((r) => (\n <TableRow key={`${r.reason}|${r.code}`}>\n <TableCell className=\"pl-6\">\n <Link\n className=\"hover:underline\"\n to={link({\n category: [r.category],\n reason: r.reason ? [r.reason] : [],\n })}\n >\n {r.reason || \"—\"}\n </Link>\n </TableCell>\n <TableCell>\n {r.code ? (\n <Link\n className=\"font-mono text-xs hover:underline\"\n to={link({\n category: [r.category],\n response_code: [r.code],\n })}\n >\n {r.code}\n </Link>\n ) : (\n \"—\"\n )}\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {r.count}\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {pct(r.share)}\n </TableCell>\n <TableCell\n className={cn(\n \"text-right tabular-nums\",\n r.count > r.previous\n ? \"text-failed\"\n : \"text-muted-foreground\"\n )}\n >\n {r.previous}\n </TableCell>\n </TableRow>\n ))}\n </React.Fragment>\n ))}\n </TableBody>\n </Table>\n )}\n </Panel>\n )\n}\n\nfunction Checks({ scope }: { scope: Scope }) {\n const { text: adminText } = useAdminUI()\n\n const queries = checkQueries(scope)\n return (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <CheckTable\n title={adminText(\"New cards by AVS result\")}\n dimension=\"avs_result\"\n query={queries.avs}\n scope={scope}\n />\n <CheckTable\n title={adminText(\"New cards by CVV result\")}\n dimension=\"cvv_result\"\n query={queries.cvv}\n scope={scope}\n />\n </div>\n )\n}\n\nfunction CheckTable({\n title,\n dimension,\n query,\n scope,\n}: {\n title: string\n dimension: \"avs_result\" | \"cvv_result\"\n query: ReturnType<typeof checkQueries>[\"avs\"]\n scope: Scope\n}) {\n const metrics = useAdminServices().adminQueries.widgetMetrics\n\n const { data, isPending } = useQuery(metrics(query))\n const rows = checkRows(data)\n return (\n <Panel title={title}>\n {isPending ? (\n <Loading />\n ) : rows.length === 0 ? (\n <Empty />\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>\n <AdminMessage id={\"Result\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Attempts\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Declined\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((r) => (\n <TableRow key={r.result}>\n <TableCell className=\"font-mono text-xs\">\n {r.result || \"none\"}\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n <Link\n className=\"hover:underline\"\n to={listURL(\n \"attempts\",\n { ...NEW_CARD, [dimension]: r.result ? [r.result] : [] },\n scope,\n data?.range\n )}\n >\n {r.attempts}\n </Link>\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n <Link\n className=\"hover:underline\"\n to={listURL(\n \"attempts\",\n {\n ...NEW_CARD,\n [dimension]: r.result ? [r.result] : [],\n category: FAILED_CATEGORIES,\n },\n scope,\n data?.range\n )}\n >\n {pct(r.failureRate)}\n </Link>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </Panel>\n )\n}\n\nfunction Recovery({ scope }: { scope: Scope }) {\n const { text: adminText } = useAdminUI()\n\n const metrics = useAdminServices().adminQueries.widgetMetrics\n\n const q = recoveryQueries(scope)\n const rate = useQuery(metrics(q.rate))\n const byAttempt = useQuery(metrics(q.byAttempt))\n const byDays = useQuery(metrics(q.byDays))\n const loading = rate.isPending || byAttempt.isPending || byDays.isPending\n return (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <Panel\n title={adminText(\"Dunning recovery by retry (share of failed cycles)\")}\n >\n {loading ? (\n <Loading />\n ) : (\n <CurveTable\n curves={recoveryCurves(\n rate.data,\n byAttempt.data,\n \"recovery_attempt\"\n )}\n steps={RECOVERY_ATTEMPTS.map((s) => `#${s}`)}\n scope={scope}\n range={rate.data?.range}\n />\n )}\n </Panel>\n <Panel\n title={adminText(\"Dunning recovery by days since the first failure\")}\n >\n {loading ? (\n <Loading />\n ) : (\n <CurveTable\n curves={recoveryCurves(rate.data, byDays.data, \"days_to_recover\")}\n steps={RECOVERY_DAYS.map((d) => `≤ ${d}d`)}\n scope={scope}\n range={rate.data?.range}\n />\n )}\n </Panel>\n </div>\n )\n}\n\nfunction CurveTable({\n curves,\n steps,\n scope,\n range,\n}: {\n curves: RecoveryCurve[]\n steps: string[]\n scope: Scope\n range?: MetricsResult[\"range\"]\n}) {\n const { text: adminText } = useAdminUI()\n\n if (curves.length === 0)\n return <Empty label={adminText(\"No recovered cycles.\")} />\n return (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>\n <AdminMessage id={\"Owner\"} />\n </TableHead>\n {steps.map((s) => (\n <TableHead key={s} className=\"text-right\">\n {s}\n </TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {curves.map((c) => (\n <TableRow key={c.owner}>\n <TableCell>\n <Link\n className=\"hover:underline\"\n to={listURL(\n \"cycles\",\n {\n owner: [c.owner],\n first_outcome: FIRST_FAILED,\n outcome: [\"collected\"],\n },\n scope,\n range\n )}\n >\n {ownerLabel(c.owner)}\n </Link>\n </TableCell>\n {c.points.map((p, i) => (\n <TableCell key={steps[i]} className=\"text-right tabular-nums\">\n {pct(p)}\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )\n}\n\nfunction Missed({\n scope,\n pspKey,\n}: {\n scope: Scope\n pspKey: (id: string) => string\n}) {\n const { text: adminText } = useAdminUI()\n\n const metrics = useAdminServices().adminQueries.widgetMetrics\n\n const { data, isPending } = useQuery(metrics(missedQuery(scope)))\n const rows = missedRows(data)\n return (\n <Panel title={adminText(\"Missed rebills\")}>\n {isPending ? (\n <Loading />\n ) : rows.length === 0 ? (\n <Empty label={adminText(\"No missed rebills in this range.\")} />\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>\n <AdminMessage id={\"Reason\"} />\n </TableHead>\n <TableHead>PSP</TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Cycles\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((r) => (\n <TableRow key={`${r.reason}|${r.psp}`}>\n <TableCell>{r.reason}</TableCell>\n <TableCell className=\"text-xs\">{pspKey(r.psp)}</TableCell>\n <TableCell className=\"text-right tabular-nums\">\n <Link\n className=\"hover:underline\"\n to={listURL(\n \"cycles\",\n { first_outcome: [\"missed\"], miss_reason: [r.reason] },\n scope,\n data?.range,\n r.psp || undefined\n )}\n >\n {r.count}\n </Link>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </Panel>\n )\n}\n\nfunction Coverage({\n scope,\n pspKey,\n}: {\n scope: Scope\n pspKey: (id: string) => string\n}) {\n const { text: adminText } = useAdminUI()\n\n const metrics = useAdminServices().adminQueries.widgetMetrics\n\n const { data, isPending } = useQuery(metrics(coverageQuery(scope)))\n const rows = coverageRows(data)\n const link = (psp: string, via: string) =>\n listURL(\n \"attempts\",\n { source: [\"provider_schedule\"], observed_via: [via] },\n scope,\n data?.range,\n psp || undefined\n )\n return (\n <Panel title={adminText(\"Provider charges seen by webhook\")}>\n {isPending ? (\n <Loading />\n ) : rows.length === 0 ? (\n <Empty\n label={adminText(\"No provider-scheduled charges in this range.\")}\n />\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>PSP</TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Webhook\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Pull\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Coverage\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((r) => (\n <TableRow key={r.psp}>\n <TableCell className=\"text-xs\">{pspKey(r.psp)}</TableCell>\n <TableCell className=\"text-right tabular-nums\">\n <Link className=\"hover:underline\" to={link(r.psp, \"webhook\")}>\n {r.webhook}\n </Link>\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n <Link className=\"hover:underline\" to={link(r.psp, \"pull\")}>\n {r.pull}\n </Link>\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {pct(r.coverage)}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </Panel>\n )\n}\n\nfunction NMIHistory({ scope }: { scope: Scope }) {\n const { id: adminId, text: adminText } = useAdminUI()\n\n const metrics = useAdminServices().adminQueries.widgetMetrics\n\n const q = nmiHistoryQueries(scope)\n const months = useQuery(metrics(q.months))\n const reasons = useQuery(metrics(q.reasons))\n const recorded = useQuery(metrics(q.recorded))\n const since = recordingSince(recorded.data)\n const rows = nmiHistoryMonths(months.data, since)\n const refusals = nmiRefusals(reasons.data).slice(0, 10)\n return (\n <section\n className=\"flex flex-col gap-3\"\n aria-labelledby={adminId(\"nmi-history\")}\n >\n <div className=\"flex flex-col gap-1\">\n <h2\n id={adminId(\"nmi-history\")}\n className=\"text-lg font-semibold tracking-tight\"\n >\n <AdminMessage\n id={\"NMI history (before OpenRails recorded attempts)\"}\n />\n </h2>\n <p className=\"max-w-4xl text-sm text-muted-foreground\">\n <AdminMessage\n id={\n \"NMI&apos;s own transaction history, read daily and kept 25 months. It counts every sender, OpenRails too once it started. One-off sales mix initial sales, upgrades and retries of declined rebills: the history cannot tell them apart. Scheduled rebills are NMI&apos;s own charges, each the first try of its period. Rates count authorizations, not buyers.\"\n }\n />{\" \"}\n {since\n ? `OpenRails recorded its own attempts from ${formatBucket(since, \"month\")}; from then on the panels above measure them.`\n : \"OpenRails recorded no NMI attempt in this range.\"}\n </p>\n </div>\n <div className=\"grid gap-4 xl:grid-cols-3\">\n <Panel\n title={adminText(\"Refusal rate by month\")}\n className=\"xl:col-span-2\"\n >\n {months.isPending || recorded.isPending ? (\n <Loading />\n ) : rows.length === 0 ? (\n <Empty label={adminText(\"No NMI history yet: it is read daily.\")} />\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>\n <AdminMessage id={\"Month\"} />\n </TableHead>\n {NMI_KINDS.map((k) => (\n <TableHead key={k.value} className=\"text-right\">\n {k.label}\n </TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((m) => (\n <TableRow\n key={m.month}\n className={cn(m.recorded && \"text-muted-foreground\")}\n >\n <TableCell>\n <span className=\"flex items-center gap-2\">\n {formatBucket(m.month, \"month\")}\n {m.month === since && (\n <Badge variant=\"outline\">\n <AdminMessage id={\"OpenRails starts\"} />\n </Badge>\n )}\n </span>\n </TableCell>\n {NMI_KINDS.map((k) => {\n const cell = m.kinds[k.value]\n return (\n <TableCell\n key={k.value}\n className=\"text-right tabular-nums\"\n >\n {cell ? (\n <>\n {pct(cell.refusalRate)}\n <span className=\"ml-1 text-xs text-muted-foreground\">\n <AdminMessage id={\"of \"} />\n {cell.authorizations.toLocaleString()}\n </span>\n </>\n ) : (\n \"—\"\n )}\n </TableCell>\n )\n })}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </Panel>\n <Panel title={adminText(\"Top refusal reasons\")}>\n {reasons.isPending ? (\n <Loading />\n ) : refusals.length === 0 ? (\n <Empty label={adminText(\"No refusals in NMI's history.\")} />\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead>\n <AdminMessage id={\"Kind / reason\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Refused\"} />\n </TableHead>\n <TableHead className=\"text-right\">\n <AdminMessage id={\"Share\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {refusals.map((r) => (\n <TableRow key={`${r.kind}|${r.category}|${r.reason}`}>\n <TableCell>\n <span className=\"block text-xs text-muted-foreground\">\n {NMI_KINDS.find((k) => k.value === r.kind)?.label ??\n r.kind}{\" \"}\n · {r.category}\n </span>\n {r.reason}\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {r.count.toLocaleString()}\n </TableCell>\n <TableCell className=\"text-right tabular-nums\">\n {pct(r.share)}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </Panel>\n </div>\n </section>\n )\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { t as e } from "./admin-utils-BK4Vh1o_.js";
2
+ import "react";
3
+ import { jsx as t } from "react/jsx-runtime";
4
+ import { Input as n } from "@base-ui/react/input";
5
+ //#region src/admin/components/ui/input.tsx
6
+ function r({ className: r, type: i, ...a }) {
7
+ return /* @__PURE__ */ t(n, {
8
+ type: i,
9
+ "data-slot": "input",
10
+ className: e("h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", r),
11
+ ...a
12
+ });
13
+ }
14
+ //#endregion
15
+ export { r as t };
16
+
17
+ //# sourceMappingURL=admin-input-CcfQfJFN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-input-CcfQfJFN.js","names":[],"sources":["../src/admin/components/ui/input.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { Input as InputPrimitive } from \"@base-ui/react/input\"\n\nimport { cn } from \"#orck/admin/lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <InputPrimitive\n type={type}\n data-slot=\"input\"\n className={cn(\n \"h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n"],"mappings":";;;;;AAKA,SAAS,EAAM,EAAE,cAAW,SAAM,GAAG,KAAwC;CAC3E,OACE,kBAAC,GAAD;EACQ;EACN,aAAU;EACV,WAAW,EACT,+oBACA,CACF;EACA,GAAI;CACL,CAAA;AAEL"}
@@ -0,0 +1,53 @@
1
+ //#region src/admin/pages/customers/invoice-profile-model.ts
2
+ var e = (e) => typeof e == "string" ? e : JSON.stringify(e);
3
+ function t(t) {
4
+ return {
5
+ terms: String(t?.net_terms_days ?? 0),
6
+ method: t?.collection_method ?? "charge_automatically",
7
+ po: t?.po_number ?? "",
8
+ memo: t?.memo ?? "",
9
+ contacts: (t?.billing_contacts ?? []).map((e) => ({
10
+ name: e.name,
11
+ email: e.email
12
+ })),
13
+ tax: Object.entries(t?.tax ?? {}).map(([t, n]) => ({
14
+ key: t,
15
+ value: e(n)
16
+ }))
17
+ };
18
+ }
19
+ function n(t, n) {
20
+ let r = Number(t.terms);
21
+ if (!/^\d+$/.test(t.terms) || !Number.isSafeInteger(r) || r > 2147483647) throw Error("Terms must be a non-negative whole number of days.");
22
+ let i = t.contacts.filter((e) => e.name.trim() || e.email.trim()).map((e) => ({
23
+ name: e.name.trim(),
24
+ email: e.email.trim()
25
+ }));
26
+ if (i.some((e) => !/^\S+@\S+$/.test(e.email))) throw Error("Each billing contact needs a valid email address.");
27
+ let a = t.tax.filter((e) => e.key.trim() || e.value.trim()), o = a.map((e) => e.key.trim());
28
+ if (o.some((e) => !e) || new Set(o).size !== o.length) throw Error("Tax details need distinct, non-empty names.");
29
+ let s = Object.fromEntries(a.map((t) => {
30
+ let r = t.key.trim(), i = n?.tax?.[r];
31
+ if (i !== void 0 && typeof i != "string") {
32
+ if (t.value === e(i)) return [r, i];
33
+ try {
34
+ return [r, JSON.parse(t.value)];
35
+ } catch {
36
+ throw Error(`Invalid structured tax detail: ${r}`);
37
+ }
38
+ }
39
+ return [r, t.value.trim()];
40
+ }));
41
+ return {
42
+ net_terms_days: r,
43
+ collection_method: t.method,
44
+ po_number: t.po.trim(),
45
+ memo: t.memo.trim(),
46
+ billing_contacts: i,
47
+ tax: s
48
+ };
49
+ }
50
+ //#endregion
51
+ export { t as n, e as r, n as t };
52
+
53
+ //# sourceMappingURL=admin-invoice-profile-model-Cgjy3zV8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-invoice-profile-model-Cgjy3zV8.js","names":[],"sources":["../src/admin/pages/customers/invoice-profile-model.ts"],"sourcesContent":["import type { InvoiceProfile } from \"#orck/client/generated/wire\"\n\nexport interface ProfileFormValues {\n terms: string\n method: InvoiceProfile[\"collection_method\"]\n po: string\n memo: string\n contacts: { name: string; email: string }[]\n tax: { key: string; value: string }[]\n}\nexport const taxDisplay = (value: unknown) =>\n typeof value === \"string\" ? value : JSON.stringify(value)\nexport function invoiceProfileValues(\n profile: InvoiceProfile | null\n): ProfileFormValues {\n return {\n terms: String(profile?.net_terms_days ?? 0),\n method: profile?.collection_method ?? \"charge_automatically\",\n po: profile?.po_number ?? \"\",\n memo: profile?.memo ?? \"\",\n contacts: (profile?.billing_contacts ?? []).map((c) => ({\n name: c.name,\n email: c.email,\n })),\n tax: Object.entries(profile?.tax ?? {}).map(([key, value]) => ({\n key,\n value: taxDisplay(value),\n })),\n }\n}\nexport function invoiceProfileRequest(\n values: ProfileFormValues,\n original: InvoiceProfile | null\n): InvoiceProfile {\n const terms = Number(values.terms)\n if (\n !/^\\d+$/.test(values.terms) ||\n !Number.isSafeInteger(terms) ||\n terms > 2147483647\n )\n throw new Error(\"Terms must be a non-negative whole number of days.\")\n const contacts = values.contacts\n .filter((c) => c.name.trim() || c.email.trim())\n .map((c) => ({ name: c.name.trim(), email: c.email.trim() }))\n if (contacts.some((c) => !/^\\S+@\\S+$/.test(c.email)))\n throw new Error(\"Each billing contact needs a valid email address.\")\n const rows = values.tax.filter((row) => row.key.trim() || row.value.trim())\n const keys = rows.map((row) => row.key.trim())\n if (keys.some((k) => !k) || new Set(keys).size !== keys.length)\n throw new Error(\"Tax details need distinct, non-empty names.\")\n const tax = Object.fromEntries(\n rows.map((row) => {\n const key = row.key.trim(),\n old = original?.tax?.[key]\n if (old !== undefined && typeof old !== \"string\") {\n if (row.value === taxDisplay(old)) return [key, old]\n try {\n return [key, JSON.parse(row.value)]\n } catch {\n throw new Error(`Invalid structured tax detail: ${key}`)\n }\n }\n return [key, row.value.trim()]\n })\n )\n return {\n net_terms_days: terms,\n collection_method: values.method,\n po_number: values.po.trim(),\n memo: values.memo.trim(),\n billing_contacts: contacts,\n tax,\n }\n}\n"],"mappings":";AAUA,IAAa,KAAc,MACzB,OAAO,KAAU,WAAW,IAAQ,KAAK,UAAU,CAAK;AAC1D,SAAgB,EACd,GACmB;CACnB,OAAO;EACL,OAAO,OAAO,GAAS,kBAAkB,CAAC;EAC1C,QAAQ,GAAS,qBAAqB;EACtC,IAAI,GAAS,aAAa;EAC1B,MAAM,GAAS,QAAQ;EACvB,WAAW,GAAS,oBAAoB,CAAC,EAAA,CAAG,KAAK,OAAO;GACtD,MAAM,EAAE;GACR,OAAO,EAAE;EACX,EAAE;EACF,KAAK,OAAO,QAAQ,GAAS,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAK,QAAY;GAC7D;GACA,OAAO,EAAW,CAAK;EACzB,EAAE;CACJ;AACF;AACA,SAAgB,EACd,GACA,GACgB;CAChB,IAAM,IAAQ,OAAO,EAAO,KAAK;CACjC,IACE,CAAC,QAAQ,KAAK,EAAO,KAAK,KAC1B,CAAC,OAAO,cAAc,CAAK,KAC3B,IAAQ,YAER,MAAU,MAAM,oDAAoD;CACtE,IAAM,IAAW,EAAO,SACrB,QAAQ,MAAM,EAAE,KAAK,KAAK,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC,CAC9C,KAAK,OAAO;EAAE,MAAM,EAAE,KAAK,KAAK;EAAG,OAAO,EAAE,MAAM,KAAK;CAAE,EAAE;CAC9D,IAAI,EAAS,MAAM,MAAM,CAAC,YAAY,KAAK,EAAE,KAAK,CAAC,GACjD,MAAU,MAAM,mDAAmD;CACrE,IAAM,IAAO,EAAO,IAAI,QAAQ,MAAQ,EAAI,IAAI,KAAK,KAAK,EAAI,MAAM,KAAK,CAAC,GACpE,IAAO,EAAK,KAAK,MAAQ,EAAI,IAAI,KAAK,CAAC;CAC7C,IAAI,EAAK,MAAM,MAAM,CAAC,CAAC,KAAK,IAAI,IAAI,CAAI,CAAC,CAAC,SAAS,EAAK,QACtD,MAAU,MAAM,6CAA6C;CAC/D,IAAM,IAAM,OAAO,YACjB,EAAK,KAAK,MAAQ;EAChB,IAAM,IAAM,EAAI,IAAI,KAAK,GACvB,IAAM,GAAU,MAAM;EACxB,IAAI,MAAQ,KAAA,KAAa,OAAO,KAAQ,UAAU;GAChD,IAAI,EAAI,UAAU,EAAW,CAAG,GAAG,OAAO,CAAC,GAAK,CAAG;GACnD,IAAI;IACF,OAAO,CAAC,GAAK,KAAK,MAAM,EAAI,KAAK,CAAC;GACpC,QAAQ;IACN,MAAU,MAAM,kCAAkC,GAAK;GACzD;EACF;EACA,OAAO,CAAC,GAAK,EAAI,MAAM,KAAK,CAAC;CAC/B,CAAC,CACH;CACA,OAAO;EACL,gBAAgB;EAChB,mBAAmB,EAAO;EAC1B,WAAW,EAAO,GAAG,KAAK;EAC1B,MAAM,EAAO,KAAK,KAAK;EACvB,kBAAkB;EAClB;CACF;AACF"}
@@ -0,0 +1,15 @@
1
+ import { t as e } from "./admin-utils-BK4Vh1o_.js";
2
+ import "react";
3
+ import { jsx as t } from "react/jsx-runtime";
4
+ //#region src/admin/components/ui/label.tsx
5
+ function n({ className: n, ...r }) {
6
+ return /* @__PURE__ */ t("label", {
7
+ "data-slot": "label",
8
+ className: e("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", n),
9
+ ...r
10
+ });
11
+ }
12
+ //#endregion
13
+ export { n as t };
14
+
15
+ //# sourceMappingURL=admin-label-BiEN5cjb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-label-BiEN5cjb.js","names":[],"sources":["../src/admin/components/ui/label.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { cn } from \"#orck/admin/lib/utils\"\n\nfunction Label({ className, ...props }: React.ComponentProps<\"label\">) {\n return (\n <label\n data-slot=\"label\"\n className={cn(\n \"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Label }\n"],"mappings":";;;;AAIA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAwC;CACrE,OACE,kBAAC,SAAD;EACE,aAAU;EACV,WAAW,EACT,uNACA,CACF;EACA,GAAI;CACL,CAAA;AAEL"}
@@ -0,0 +1,26 @@
1
+ import { s as e, t } from "./admin-utils-BK4Vh1o_.js";
2
+ import { t as n } from "./admin-dom-uMmZzRvU.js";
3
+ import { s as r } from "./admin-table-CH9TrXJf.js";
4
+ import "react";
5
+ import { jsx as i } from "react/jsx-runtime";
6
+ //#region src/admin/components/linked-table-row.tsx
7
+ function a({ to: a, className: o, children: s, ...c }) {
8
+ let l = e(), u = (e) => {
9
+ n(e) || l(a);
10
+ };
11
+ return /* @__PURE__ */ i(r, {
12
+ role: "link",
13
+ tabIndex: 0,
14
+ onClick: (e) => u(e.target),
15
+ onKeyDown: (e) => {
16
+ e.key === "Enter" && u(e.target);
17
+ },
18
+ className: t("cursor-pointer focus-visible:bg-muted/50 focus-visible:outline-none", o),
19
+ ...c,
20
+ children: s
21
+ });
22
+ }
23
+ //#endregion
24
+ export { a as t };
25
+
26
+ //# sourceMappingURL=admin-linked-table-row-BsaUruCN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-linked-table-row-BsaUruCN.js","names":[],"sources":["../src/admin/components/linked-table-row.tsx"],"sourcesContent":["// A table row that behaves like the link inside it: the whole row is a target,\n// and the primary cell's link stays for keyboard and assistive navigation.\nimport * as React from \"react\"\nimport { useNavigate } from \"#orck/admin/router\"\n\nimport { TableRow } from \"#orck/admin/components/ui/table\"\nimport { isInteractiveTarget } from \"#orck/admin/lib/dom\"\nimport { cn } from \"#orck/admin/lib/utils\"\n\nexport function LinkedTableRow({\n to,\n className,\n children,\n ...props\n}: React.ComponentProps<typeof TableRow> & { to: string }) {\n const navigate = useNavigate()\n const follow = (target: EventTarget | null) => {\n if (isInteractiveTarget(target)) return\n navigate(to)\n }\n return (\n <TableRow\n role=\"link\"\n tabIndex={0}\n onClick={(event) => follow(event.target)}\n onKeyDown={(event) => {\n if (event.key !== \"Enter\") return\n follow(event.target)\n }}\n className={cn(\n \"cursor-pointer focus-visible:bg-muted/50 focus-visible:outline-none\",\n className\n )}\n {...props}\n >\n {children}\n </TableRow>\n )\n}\n"],"mappings":";;;;;;AASA,SAAgB,EAAe,EAC7B,OACA,cACA,aACA,GAAG,KACsD;CACzD,IAAM,IAAW,EAAY,GACvB,KAAU,MAA+B;EACzC,EAAoB,CAAM,KAC9B,EAAS,CAAE;CACb;CACA,OACE,kBAAC,GAAD;EACE,MAAK;EACL,UAAU;EACV,UAAU,MAAU,EAAO,EAAM,MAAM;EACvC,YAAY,MAAU;GAChB,EAAM,QAAQ,WAClB,EAAO,EAAM,MAAM;EACrB;EACA,WAAW,EACT,uEACA,CACF;EACA,GAAI;EAEH;CACO,CAAA;AAEd"}