@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,983 @@
1
+ import { E as e, l as t, p as n, r, t as i, w as a } from "./admin-utils-BK4Vh1o_.js";
2
+ import { t as o } from "./admin-skeleton-DsM7crYi.js";
3
+ import { l as s } from "./admin-capabilities-BuigAgtm.js";
4
+ import { a as c, i as l, n as u, r as d, t as f } from "./admin-select-DBgprVW6.js";
5
+ import { a as p, n as m, o as h, r as g, s as _, t as v } from "./admin-table-CH9TrXJf.js";
6
+ import { t as ee } from "./admin-badge-DR5-1qd8.js";
7
+ import { a as y, o as b, r as x, t as S } from "./admin-card-bzAks3-3.js";
8
+ import { a as C, i as w, r as T, t as te } from "./admin-widget-viz-Da48c-Zf.js";
9
+ import * as ne from "react";
10
+ import { useQuery as E } from "@tanstack/react-query";
11
+ import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
12
+ //#region src/admin/pages/payments/health-model.ts
13
+ var A = [
14
+ {
15
+ value: "",
16
+ label: "All owners"
17
+ },
18
+ {
19
+ value: "nmi_schedule",
20
+ label: "NMI-owned"
21
+ },
22
+ {
23
+ value: "engine",
24
+ label: "OpenRails-owned"
25
+ },
26
+ {
27
+ value: "provider",
28
+ label: "Provider-owned"
29
+ }
30
+ ], re = [
31
+ {
32
+ value: "7d",
33
+ label: "Last 7 days"
34
+ },
35
+ {
36
+ value: "30d",
37
+ label: "Last 30 days"
38
+ },
39
+ {
40
+ value: "90d",
41
+ label: "Last 90 days"
42
+ }
43
+ ], j = {
44
+ kind: ["verify", "initial"],
45
+ card_entry: ["new"]
46
+ }, M = [
47
+ "card_data",
48
+ "issuer_soft",
49
+ "issuer_hard",
50
+ "gateway_rule",
51
+ "system_error",
52
+ "unknown"
53
+ ], N = [
54
+ "declined",
55
+ "error",
56
+ "missed"
57
+ ];
58
+ function P(e, t = {}) {
59
+ let n = { ...t };
60
+ return e.owner && (n.owner = [e.owner]), e.psp && (n.psp = [e.psp.id]), Object.keys(n).length ? n : void 0;
61
+ }
62
+ var F = (e, t, n = {}) => ({
63
+ measures: e,
64
+ range: { last: t.last },
65
+ filters: P(t, n),
66
+ compare: "previous_period"
67
+ }), I = [
68
+ "rebill_first_failure_rate",
69
+ "rebills_missed",
70
+ "dunning_recovery_rate",
71
+ "rebill_collection_rate"
72
+ ], L = (e) => F(I, e), ie = [
73
+ {
74
+ id: "new-card-decline",
75
+ title: "New-card decline rate",
76
+ measure: "attempt_failure_rate",
77
+ better: "lower",
78
+ query: (e) => F(["attempt_failure_rate"], e, j),
79
+ list: "attempts",
80
+ listFilters: {
81
+ ...j,
82
+ category: M
83
+ }
84
+ },
85
+ {
86
+ id: "checkout-failure",
87
+ title: "New-card checkout failure rate",
88
+ measure: "checkout_failure_rate",
89
+ better: "lower",
90
+ query: (e) => F(["checkout_failure_rate"], e),
91
+ list: "attempts",
92
+ listFilters: { card_entry: ["new"] }
93
+ },
94
+ {
95
+ id: "rebill-first-failure",
96
+ title: "Rebill first-attempt failure rate",
97
+ measure: "rebill_first_failure_rate",
98
+ better: "lower",
99
+ query: L,
100
+ list: "cycles",
101
+ listFilters: { first_outcome: N }
102
+ },
103
+ {
104
+ id: "missed",
105
+ title: "Missed rebills",
106
+ measure: "rebills_missed",
107
+ better: "lower",
108
+ query: L,
109
+ list: "cycles",
110
+ listFilters: { first_outcome: ["missed"] }
111
+ },
112
+ {
113
+ id: "recovery",
114
+ title: "Dunning recovery rate",
115
+ measure: "dunning_recovery_rate",
116
+ better: "higher",
117
+ query: L,
118
+ list: "cycles",
119
+ listFilters: {
120
+ first_outcome: N,
121
+ outcome: ["collected"]
122
+ }
123
+ },
124
+ {
125
+ id: "collection",
126
+ title: "Rebill collection rate",
127
+ measure: "rebill_collection_rate",
128
+ better: "higher",
129
+ query: L,
130
+ list: "cycles",
131
+ listFilters: { outcome: ["collected", "lost"] }
132
+ }
133
+ ];
134
+ function ae(e, t) {
135
+ if (!e) return;
136
+ let n = C(e.columns).measures.find((e) => e.name === t.measure);
137
+ if (!n) return;
138
+ let r = e.rows[0]?.[n.index] ?? null, i = e.compare_rows?.[0]?.[n.index] ?? null, a = null;
139
+ r !== null && i !== null && (a = Number(r) - Number(i), Number.isFinite(a) || (a = null));
140
+ let o = a !== null && a !== 0 && (t.better === "lower" ? a > 0 : a < 0);
141
+ return {
142
+ value: r,
143
+ unit: n.unit,
144
+ change: a,
145
+ worse: o
146
+ };
147
+ }
148
+ function oe(e) {
149
+ if (e.change === null) return "no previous period";
150
+ let t = e.change > 0 ? "+" : "";
151
+ return e.unit === "ratio" ? `${t}${(e.change * 100).toFixed(1)} pp vs previous period` : `${t}${e.change.toLocaleString()} vs previous period`;
152
+ }
153
+ var R = (e) => {
154
+ let t = (t, n = {}) => ({
155
+ measures: [t],
156
+ by: ["time", "owner"],
157
+ grain: "week",
158
+ range: { last: "12w" },
159
+ filters: P(e, n)
160
+ });
161
+ return {
162
+ newCard: t("attempt_failure_rate", j),
163
+ rebill: t("rebill_first_failure_rate")
164
+ };
165
+ }, se = (e) => ({
166
+ measures: ["failed_attempts"],
167
+ by: [
168
+ "category",
169
+ "reason",
170
+ "response_code"
171
+ ],
172
+ range: { last: e.last },
173
+ filters: P(e),
174
+ compare: "previous_period"
175
+ });
176
+ function ce(e) {
177
+ if (!e) return [];
178
+ let t = C(e.columns), n = (e) => t.dims.find((t) => t.name === e)?.index ?? -1, [r, i, a] = [
179
+ n("category"),
180
+ n("reason"),
181
+ n("response_code")
182
+ ], o = t.measures[0]?.index ?? -1;
183
+ if (r < 0 || i < 0 || a < 0 || o < 0) return [];
184
+ let s = (e) => JSON.stringify([
185
+ e[r],
186
+ e[i],
187
+ e[a]
188
+ ]), c = /* @__PURE__ */ new Map();
189
+ for (let t of e.compare_rows ?? []) c.set(s(t), Number(t[o] ?? 0));
190
+ let l = e.rows.map((e) => ({
191
+ category: String(e[r] ?? ""),
192
+ reason: String(e[i] ?? ""),
193
+ code: String(e[a] ?? ""),
194
+ count: Number(e[o] ?? 0),
195
+ share: 0,
196
+ previous: c.get(s(e)) ?? 0
197
+ })), u = l.reduce((e, t) => e + t.count, 0), d = /* @__PURE__ */ new Map();
198
+ for (let e of l) {
199
+ e.share = u ? e.count / u : 0;
200
+ let t = d.get(e.category);
201
+ t || (t = {
202
+ category: e.category,
203
+ count: 0,
204
+ share: 0,
205
+ rows: []
206
+ }, d.set(e.category, t)), t.count += e.count, t.rows.push(e);
207
+ }
208
+ return [...d.values()].map((e) => ({
209
+ ...e,
210
+ share: u ? e.count / u : 0,
211
+ rows: e.rows.sort((e, t) => t.count - e.count)
212
+ })).sort((e, t) => t.count - e.count);
213
+ }
214
+ var le = (e) => {
215
+ let t = (t) => ({
216
+ measures: ["attempts", "attempt_failure_rate"],
217
+ by: [t],
218
+ range: { last: e.last },
219
+ filters: P(e, j)
220
+ });
221
+ return {
222
+ avs: t("avs_result"),
223
+ cvv: t("cvv_result")
224
+ };
225
+ };
226
+ function ue(e) {
227
+ if (!e) return [];
228
+ let t = C(e.columns), n = t.dims[0]?.index ?? -1, r = t.measures.find((e) => e.name === "attempts")?.index ?? -1, i = t.measures.find((e) => e.name === "attempt_failure_rate")?.index ?? -1;
229
+ return n < 0 || r < 0 || i < 0 ? [] : e.rows.map((e) => ({
230
+ result: String(e[n] ?? ""),
231
+ attempts: Number(e[r] ?? 0),
232
+ failureRate: e[i] === null ? null : Number(e[i])
233
+ })).sort((e, t) => t.attempts - e.attempts);
234
+ }
235
+ var z = [
236
+ "1",
237
+ "2",
238
+ "3",
239
+ "4",
240
+ "5+"
241
+ ], B = [
242
+ 1,
243
+ 3,
244
+ 7,
245
+ 14,
246
+ 30
247
+ ], V = (e) => {
248
+ let t = (t, n) => ({
249
+ measures: t,
250
+ by: n,
251
+ range: { last: e.last },
252
+ filters: P(e)
253
+ });
254
+ return {
255
+ rate: t(["dunning_recovery_rate", "dunning_recovered"], ["owner"]),
256
+ byAttempt: t(["dunning_recovered"], ["owner", "recovery_attempt"]),
257
+ byDays: t(["dunning_recovered"], ["owner", "days_to_recover"])
258
+ };
259
+ };
260
+ function H(e, t, n) {
261
+ if (!e || !t) return [];
262
+ let r = C(e.columns), i = C(t.columns), a = r.dims.find((e) => e.name === "owner")?.index ?? -1, o = r.measures.find((e) => e.name === "dunning_recovery_rate")?.index ?? -1, s = r.measures.find((e) => e.name === "dunning_recovered")?.index ?? -1, c = i.dims.find((e) => e.name === "owner")?.index ?? -1, l = i.dims.find((e) => e.name === n)?.index ?? -1, u = i.measures[0]?.index ?? -1;
263
+ if ([
264
+ a,
265
+ o,
266
+ s,
267
+ c,
268
+ l,
269
+ u
270
+ ].includes(-1)) return [];
271
+ let d = /* @__PURE__ */ new Map();
272
+ for (let t of e.rows) {
273
+ let e = Number(t[s] ?? 0), n = Number(t[o] ?? 0);
274
+ e > 0 && n > 0 && d.set(String(t[a]), e / n);
275
+ }
276
+ let f = n === "recovery_attempt" ? z : B, p = [];
277
+ for (let [e, r] of d) {
278
+ let i = f.map((i) => {
279
+ let a = 0;
280
+ for (let r of t.rows) {
281
+ if (String(r[c]) !== e || r[l] === "") continue;
282
+ let t = String(r[l]);
283
+ (n === "recovery_attempt" ? z.indexOf(t) <= z.indexOf(String(i)) : Number(t) <= Number(i)) && (a += Number(r[u] ?? 0));
284
+ }
285
+ return a / r;
286
+ });
287
+ p.push({
288
+ owner: e,
289
+ points: i
290
+ });
291
+ }
292
+ return p.sort((e, t) => e.owner.localeCompare(t.owner));
293
+ }
294
+ var de = (e) => ({
295
+ measures: ["rebills_missed"],
296
+ by: ["miss_reason", "psp"],
297
+ range: { last: e.last },
298
+ filters: P(e)
299
+ });
300
+ function fe(e) {
301
+ if (!e) return [];
302
+ let t = C(e.columns), n = t.dims.find((e) => e.name === "miss_reason")?.index ?? -1, r = t.dims.find((e) => e.name === "psp")?.index ?? -1, i = t.measures[0]?.index ?? -1;
303
+ return n < 0 || r < 0 || i < 0 ? [] : e.rows.map((e) => ({
304
+ reason: String(e[n] ?? ""),
305
+ psp: String(e[r] ?? ""),
306
+ count: Number(e[i] ?? 0)
307
+ })).filter((e) => e.reason !== "" && e.count > 0).sort((e, t) => t.count - e.count);
308
+ }
309
+ var pe = (e) => ({
310
+ measures: ["attempts"],
311
+ by: ["psp", "observed_via"],
312
+ range: { last: e.last },
313
+ filters: P(e, { source: ["provider_schedule"] })
314
+ });
315
+ function me(e) {
316
+ if (!e) return [];
317
+ let t = C(e.columns), n = t.dims.find((e) => e.name === "psp")?.index ?? -1, r = t.dims.find((e) => e.name === "observed_via")?.index ?? -1, i = t.measures[0]?.index ?? -1;
318
+ if (n < 0 || r < 0 || i < 0) return [];
319
+ let a = /* @__PURE__ */ new Map();
320
+ for (let t of e.rows) {
321
+ let e = String(t[n] ?? ""), o = a.get(e);
322
+ o || (o = {
323
+ psp: e,
324
+ webhook: 0,
325
+ pull: 0,
326
+ coverage: null
327
+ }, a.set(e, o));
328
+ let s = Number(t[i] ?? 0);
329
+ t[r] === "webhook" ? o.webhook += s : t[r] === "pull" && (o.pull += s);
330
+ }
331
+ return [...a.values()].map((e) => {
332
+ let t = e.webhook + e.pull;
333
+ return {
334
+ ...e,
335
+ coverage: t ? e.webhook / t : null
336
+ };
337
+ }).sort((e, t) => e.psp.localeCompare(t.psp));
338
+ }
339
+ function U(e, t, n, r, i) {
340
+ let a = new URLSearchParams();
341
+ for (let [e, n] of Object.entries(t)) n.length && a.set(e, n.join(","));
342
+ n.owner && !a.has("owner") && a.set("owner", n.owner);
343
+ let o = i ?? n.psp?.id;
344
+ return o && a.set("psp_id", o), r && (a.set(e === "attempts" ? "since" : "due_since", r.from), a.set(e === "attempts" ? "until" : "due_until", r.to)), `/payments/${e}?${a.toString()}`;
345
+ }
346
+ var W = [
347
+ {
348
+ value: "verification",
349
+ label: "Card verifications"
350
+ },
351
+ {
352
+ value: "one_off_sale",
353
+ label: "One-off sales"
354
+ },
355
+ {
356
+ value: "scheduled_rebill",
357
+ label: "NMI-scheduled rebills"
358
+ }
359
+ ], he = (e) => {
360
+ let t = e.psp ? { psp: [e.psp.id] } : {}, n = { last: "25m" };
361
+ return {
362
+ months: {
363
+ measures: ["nmi_history_authorizations", "nmi_history_refusal_rate"],
364
+ by: ["time", "nmi_kind"],
365
+ grain: "month",
366
+ range: n,
367
+ filters: e.psp ? t : void 0
368
+ },
369
+ reasons: {
370
+ measures: ["nmi_history_refused"],
371
+ by: [
372
+ "nmi_kind",
373
+ "category",
374
+ "reason"
375
+ ],
376
+ range: n,
377
+ filters: {
378
+ ...t,
379
+ category: M
380
+ }
381
+ },
382
+ recorded: {
383
+ measures: ["attempts"],
384
+ by: ["time"],
385
+ grain: "month",
386
+ range: n,
387
+ filters: {
388
+ ...t,
389
+ rail: ["nmi"]
390
+ }
391
+ }
392
+ };
393
+ };
394
+ function ge(e) {
395
+ if (!e) return null;
396
+ let t = C(e.columns), n = t.measures[0]?.index ?? -1;
397
+ return t.time < 0 || n < 0 ? null : e.rows.filter((e) => Number(e[n] ?? 0) > 0).map((e) => String(e[t.time])).sort()[0] ?? null;
398
+ }
399
+ function _e(e, t) {
400
+ if (!e) return [];
401
+ let n = C(e.columns), r = n.dims.find((e) => e.name === "nmi_kind")?.index ?? -1, i = n.measures.find((e) => e.name === "nmi_history_authorizations")?.index ?? -1, a = n.measures.find((e) => e.name === "nmi_history_refusal_rate")?.index ?? -1;
402
+ if ([
403
+ n.time,
404
+ r,
405
+ i,
406
+ a
407
+ ].includes(-1)) return [];
408
+ let o = /* @__PURE__ */ new Map();
409
+ for (let s of e.rows) {
410
+ let e = Number(s[i] ?? 0);
411
+ if (e === 0) continue;
412
+ let c = String(s[n.time]), l = o.get(c);
413
+ l || (l = {
414
+ month: c,
415
+ kinds: {},
416
+ recorded: t !== null && c >= t
417
+ }, o.set(c, l)), l.kinds[String(s[r])] = {
418
+ authorizations: e,
419
+ refusalRate: s[a] === null ? null : Number(s[a])
420
+ };
421
+ }
422
+ return [...o.values()].sort((e, t) => t.month.localeCompare(e.month));
423
+ }
424
+ function ve(e) {
425
+ if (!e) return [];
426
+ let t = C(e.columns), n = (e) => t.dims.find((t) => t.name === e)?.index ?? -1, [r, i, a] = [
427
+ n("nmi_kind"),
428
+ n("category"),
429
+ n("reason")
430
+ ], o = t.measures[0]?.index ?? -1;
431
+ if ([
432
+ r,
433
+ i,
434
+ a,
435
+ o
436
+ ].includes(-1)) return [];
437
+ let s = e.rows.map((e) => ({
438
+ kind: String(e[r] ?? ""),
439
+ category: String(e[i] ?? ""),
440
+ reason: String(e[a] ?? ""),
441
+ count: Number(e[o] ?? 0),
442
+ share: 0
443
+ })).filter((e) => e.count > 0), c = s.reduce((e, t) => e + t.count, 0);
444
+ return s.map((e) => ({
445
+ ...e,
446
+ share: c ? e.count / c : 0
447
+ })).sort((e, t) => t.count - e.count);
448
+ }
449
+ //#endregion
450
+ //#region src/admin/pages/payments/health.tsx
451
+ var G = (e) => e === null ? "—" : w(e, "ratio"), ye = (e) => A.find((t) => t.value === e)?.label ?? e;
452
+ function be() {
453
+ let { text: r } = e(), { adminQueries: i } = n(), [o, c] = t(), l = s(), u = E({
454
+ ...i.psps(),
455
+ enabled: l
456
+ }).data?.data, d = o.get("psp_id") ?? "", f = u?.find((e) => e.id === d), p = {
457
+ owner: o.get("owner") ?? "",
458
+ psp: f ? { id: f.id } : void 0,
459
+ last: o.get("last") ?? "30d"
460
+ }, m = (e, t) => {
461
+ let n = new URLSearchParams(o);
462
+ t ? n.set(e, t) : n.delete(e), c(n);
463
+ }, h = (e) => u?.find((t) => t.id === e)?.key ?? e, g = f ? f.rail === "nmi" : !!u?.some((e) => e.rail === "nmi");
464
+ return /* @__PURE__ */ k("div", {
465
+ className: "flex flex-col gap-4",
466
+ children: [
467
+ /* @__PURE__ */ k("div", {
468
+ className: "flex flex-wrap items-center justify-between gap-3",
469
+ children: [/* @__PURE__ */ O("h1", {
470
+ className: "text-2xl font-semibold tracking-tight",
471
+ children: /* @__PURE__ */ O(a, { id: "Payment health" })
472
+ }), /* @__PURE__ */ k("div", {
473
+ className: "flex flex-wrap items-center gap-3",
474
+ children: [
475
+ /* @__PURE__ */ O(K, {
476
+ label: r("Owner"),
477
+ value: p.owner,
478
+ options: A.map((e) => ({
479
+ value: e.value,
480
+ label: e.label
481
+ })),
482
+ onChange: (e) => m("owner", e)
483
+ }),
484
+ /* @__PURE__ */ O(K, {
485
+ label: r("PSP"),
486
+ value: d,
487
+ options: [{
488
+ value: "",
489
+ label: "All PSPs"
490
+ }, ...(u ?? []).map((e) => ({
491
+ value: e.id,
492
+ label: `${e.key} · ${e.rail}`
493
+ }))],
494
+ onChange: (e) => m("psp_id", e)
495
+ }),
496
+ /* @__PURE__ */ O(K, {
497
+ label: r("Range"),
498
+ value: p.last,
499
+ options: re.map((e) => ({
500
+ value: e.value,
501
+ label: e.label
502
+ })),
503
+ onChange: (e) => m("last", e === "30d" ? "" : e)
504
+ })
505
+ ]
506
+ })]
507
+ }),
508
+ /* @__PURE__ */ O(xe, { scope: p }),
509
+ /* @__PURE__ */ k("div", {
510
+ className: "grid gap-4 lg:grid-cols-2",
511
+ children: [/* @__PURE__ */ O(X, {
512
+ title: r("New-card decline rate by week"),
513
+ query: R(p).newCard
514
+ }), /* @__PURE__ */ O(X, {
515
+ title: r("Rebill first-attempt failure rate by week"),
516
+ query: R(p).rebill
517
+ })]
518
+ }),
519
+ /* @__PURE__ */ O(Ce, { scope: p }),
520
+ /* @__PURE__ */ O(we, { scope: p }),
521
+ /* @__PURE__ */ O(Q, { scope: p }),
522
+ /* @__PURE__ */ k("div", {
523
+ className: "grid gap-4 lg:grid-cols-2",
524
+ children: [/* @__PURE__ */ O(Te, {
525
+ scope: p,
526
+ pspKey: h
527
+ }), /* @__PURE__ */ O(Ee, {
528
+ scope: p,
529
+ pspKey: h
530
+ })]
531
+ }),
532
+ g && /* @__PURE__ */ O(De, { scope: p })
533
+ ]
534
+ });
535
+ }
536
+ function K({ label: e, value: t, options: n, onChange: r }) {
537
+ let i = n.map((e) => ({
538
+ ...e,
539
+ value: e.value || "all"
540
+ }));
541
+ return /* @__PURE__ */ k(f, {
542
+ items: i,
543
+ value: t || "all",
544
+ onValueChange: (e) => r(!e || e === "all" ? "" : String(e)),
545
+ children: [/* @__PURE__ */ O(l, {
546
+ className: "w-44",
547
+ "aria-label": e,
548
+ children: /* @__PURE__ */ O(c, { placeholder: e })
549
+ }), /* @__PURE__ */ O(u, { children: i.map((e) => /* @__PURE__ */ O(d, {
550
+ value: e.value,
551
+ children: e.label
552
+ }, e.value)) })]
553
+ });
554
+ }
555
+ function q({ title: e, children: t, className: n }) {
556
+ return /* @__PURE__ */ k(S, {
557
+ className: n,
558
+ children: [/* @__PURE__ */ O(y, { children: /* @__PURE__ */ O(b, {
559
+ className: "text-sm",
560
+ children: e
561
+ }) }), /* @__PURE__ */ O(x, { children: t })]
562
+ });
563
+ }
564
+ function J() {
565
+ return /* @__PURE__ */ O(o, { className: "h-24 w-full" });
566
+ }
567
+ function Y({ label: e = "Nothing in this range." }) {
568
+ return /* @__PURE__ */ O("p", {
569
+ className: "text-sm text-muted-foreground",
570
+ children: e
571
+ });
572
+ }
573
+ function xe({ scope: e }) {
574
+ return /* @__PURE__ */ O("div", {
575
+ className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6",
576
+ children: ie.map((t) => /* @__PURE__ */ O(Se, {
577
+ tile: t,
578
+ scope: e
579
+ }, t.id))
580
+ });
581
+ }
582
+ function Se({ tile: e, scope: t }) {
583
+ let a = n().adminQueries.widgetMetrics, { data: s, isPending: c } = E(a(e.query(t))), l = ae(s, e);
584
+ return /* @__PURE__ */ O(r, {
585
+ to: U(e.list, e.listFilters, t, s?.range),
586
+ className: "rounded-xl focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none",
587
+ children: /* @__PURE__ */ k(S, {
588
+ className: "h-full gap-2 transition-colors hover:bg-muted/40",
589
+ children: [/* @__PURE__ */ O(y, { children: /* @__PURE__ */ O(b, {
590
+ className: "text-xs font-medium tracking-wider text-muted-foreground uppercase",
591
+ children: e.title
592
+ }) }), /* @__PURE__ */ O(x, {
593
+ className: "flex flex-col gap-1",
594
+ children: c || !l ? /* @__PURE__ */ O(o, { className: "h-8 w-20" }) : /* @__PURE__ */ k(D, { children: [/* @__PURE__ */ O("span", {
595
+ className: "text-2xl font-semibold tabular-nums",
596
+ children: w(l.value, l.unit)
597
+ }), /* @__PURE__ */ O("span", {
598
+ className: i("text-xs", l.change === null || l.change === 0 ? "text-muted-foreground" : l.worse ? "text-failed" : "text-settled"),
599
+ children: oe(l)
600
+ })] })
601
+ })]
602
+ })
603
+ });
604
+ }
605
+ function X({ title: e, query: t }) {
606
+ let r = n().adminQueries.widgetMetrics, { data: i, isPending: a } = E(r(t));
607
+ return /* @__PURE__ */ O(q, {
608
+ title: e,
609
+ children: /* @__PURE__ */ O("div", {
610
+ className: "h-56",
611
+ children: a || !i ? /* @__PURE__ */ O(J, {}) : /* @__PURE__ */ O(te, {
612
+ viz: "line",
613
+ result: i,
614
+ query: t
615
+ })
616
+ })
617
+ });
618
+ }
619
+ function Ce({ scope: t }) {
620
+ let { text: o } = e(), s = n().adminQueries.widgetMetrics, { data: c, isPending: l } = E(s(se(t))), u = ce(c), d = (e) => U("attempts", e, t, c?.range);
621
+ return /* @__PURE__ */ O(q, {
622
+ title: o("Decline reasons"),
623
+ children: l ? /* @__PURE__ */ O(J, {}) : u.length === 0 ? /* @__PURE__ */ O(Y, { label: o("No declines in this range.") }) : /* @__PURE__ */ k(v, { children: [/* @__PURE__ */ O(h, { children: /* @__PURE__ */ k(_, {
624
+ className: "hover:bg-transparent",
625
+ children: [
626
+ /* @__PURE__ */ O(p, { children: /* @__PURE__ */ O(a, { id: "Category / reason" }) }),
627
+ /* @__PURE__ */ O(p, { children: /* @__PURE__ */ O(a, { id: "Code" }) }),
628
+ /* @__PURE__ */ O(p, {
629
+ className: "text-right",
630
+ children: /* @__PURE__ */ O(a, { id: "Declines" })
631
+ }),
632
+ /* @__PURE__ */ O(p, {
633
+ className: "text-right",
634
+ children: /* @__PURE__ */ O(a, { id: "Share" })
635
+ }),
636
+ /* @__PURE__ */ O(p, {
637
+ className: "text-right",
638
+ children: /* @__PURE__ */ O(a, { id: "Previous period" })
639
+ })
640
+ ]
641
+ }) }), /* @__PURE__ */ O(m, { children: u.map((e) => /* @__PURE__ */ k(ne.Fragment, { children: [/* @__PURE__ */ k(_, {
642
+ className: "bg-muted/30",
643
+ children: [
644
+ /* @__PURE__ */ O(g, {
645
+ colSpan: 2,
646
+ className: "font-medium",
647
+ children: /* @__PURE__ */ O(r, {
648
+ className: "hover:underline",
649
+ to: d({ category: [e.category] }),
650
+ children: e.category
651
+ })
652
+ }),
653
+ /* @__PURE__ */ O(g, {
654
+ className: "text-right tabular-nums",
655
+ children: e.count
656
+ }),
657
+ /* @__PURE__ */ O(g, {
658
+ className: "text-right tabular-nums",
659
+ children: G(e.share)
660
+ }),
661
+ /* @__PURE__ */ O(g, {})
662
+ ]
663
+ }), e.rows.map((e) => /* @__PURE__ */ k(_, { children: [
664
+ /* @__PURE__ */ O(g, {
665
+ className: "pl-6",
666
+ children: /* @__PURE__ */ O(r, {
667
+ className: "hover:underline",
668
+ to: d({
669
+ category: [e.category],
670
+ reason: e.reason ? [e.reason] : []
671
+ }),
672
+ children: e.reason || "—"
673
+ })
674
+ }),
675
+ /* @__PURE__ */ O(g, { children: e.code ? /* @__PURE__ */ O(r, {
676
+ className: "font-mono text-xs hover:underline",
677
+ to: d({
678
+ category: [e.category],
679
+ response_code: [e.code]
680
+ }),
681
+ children: e.code
682
+ }) : "—" }),
683
+ /* @__PURE__ */ O(g, {
684
+ className: "text-right tabular-nums",
685
+ children: e.count
686
+ }),
687
+ /* @__PURE__ */ O(g, {
688
+ className: "text-right tabular-nums",
689
+ children: G(e.share)
690
+ }),
691
+ /* @__PURE__ */ O(g, {
692
+ className: i("text-right tabular-nums", e.count > e.previous ? "text-failed" : "text-muted-foreground"),
693
+ children: e.previous
694
+ })
695
+ ] }, `${e.reason}|${e.code}`))] }, e.category)) })] })
696
+ });
697
+ }
698
+ function we({ scope: t }) {
699
+ let { text: n } = e(), r = le(t);
700
+ return /* @__PURE__ */ k("div", {
701
+ className: "grid gap-4 lg:grid-cols-2",
702
+ children: [/* @__PURE__ */ O(Z, {
703
+ title: n("New cards by AVS result"),
704
+ dimension: "avs_result",
705
+ query: r.avs,
706
+ scope: t
707
+ }), /* @__PURE__ */ O(Z, {
708
+ title: n("New cards by CVV result"),
709
+ dimension: "cvv_result",
710
+ query: r.cvv,
711
+ scope: t
712
+ })]
713
+ });
714
+ }
715
+ function Z({ title: e, dimension: t, query: i, scope: o }) {
716
+ let s = n().adminQueries.widgetMetrics, { data: c, isPending: l } = E(s(i)), u = ue(c);
717
+ return /* @__PURE__ */ O(q, {
718
+ title: e,
719
+ children: l ? /* @__PURE__ */ O(J, {}) : u.length === 0 ? /* @__PURE__ */ O(Y, {}) : /* @__PURE__ */ k(v, { children: [/* @__PURE__ */ O(h, { children: /* @__PURE__ */ k(_, {
720
+ className: "hover:bg-transparent",
721
+ children: [
722
+ /* @__PURE__ */ O(p, { children: /* @__PURE__ */ O(a, { id: "Result" }) }),
723
+ /* @__PURE__ */ O(p, {
724
+ className: "text-right",
725
+ children: /* @__PURE__ */ O(a, { id: "Attempts" })
726
+ }),
727
+ /* @__PURE__ */ O(p, {
728
+ className: "text-right",
729
+ children: /* @__PURE__ */ O(a, { id: "Declined" })
730
+ })
731
+ ]
732
+ }) }), /* @__PURE__ */ O(m, { children: u.map((e) => /* @__PURE__ */ k(_, { children: [
733
+ /* @__PURE__ */ O(g, {
734
+ className: "font-mono text-xs",
735
+ children: e.result || "none"
736
+ }),
737
+ /* @__PURE__ */ O(g, {
738
+ className: "text-right tabular-nums",
739
+ children: /* @__PURE__ */ O(r, {
740
+ className: "hover:underline",
741
+ to: U("attempts", {
742
+ ...j,
743
+ [t]: e.result ? [e.result] : []
744
+ }, o, c?.range),
745
+ children: e.attempts
746
+ })
747
+ }),
748
+ /* @__PURE__ */ O(g, {
749
+ className: "text-right tabular-nums",
750
+ children: /* @__PURE__ */ O(r, {
751
+ className: "hover:underline",
752
+ to: U("attempts", {
753
+ ...j,
754
+ [t]: e.result ? [e.result] : [],
755
+ category: M
756
+ }, o, c?.range),
757
+ children: G(e.failureRate)
758
+ })
759
+ })
760
+ ] }, e.result)) })] })
761
+ });
762
+ }
763
+ function Q({ scope: t }) {
764
+ let { text: r } = e(), i = n().adminQueries.widgetMetrics, a = V(t), o = E(i(a.rate)), s = E(i(a.byAttempt)), c = E(i(a.byDays)), l = o.isPending || s.isPending || c.isPending;
765
+ return /* @__PURE__ */ k("div", {
766
+ className: "grid gap-4 lg:grid-cols-2",
767
+ children: [/* @__PURE__ */ O(q, {
768
+ title: r("Dunning recovery by retry (share of failed cycles)"),
769
+ children: l ? /* @__PURE__ */ O(J, {}) : /* @__PURE__ */ O($, {
770
+ curves: H(o.data, s.data, "recovery_attempt"),
771
+ steps: z.map((e) => `#${e}`),
772
+ scope: t,
773
+ range: o.data?.range
774
+ })
775
+ }), /* @__PURE__ */ O(q, {
776
+ title: r("Dunning recovery by days since the first failure"),
777
+ children: l ? /* @__PURE__ */ O(J, {}) : /* @__PURE__ */ O($, {
778
+ curves: H(o.data, c.data, "days_to_recover"),
779
+ steps: B.map((e) => `≤ ${e}d`),
780
+ scope: t,
781
+ range: o.data?.range
782
+ })
783
+ })]
784
+ });
785
+ }
786
+ function $({ curves: t, steps: n, scope: i, range: o }) {
787
+ let { text: s } = e();
788
+ return t.length === 0 ? /* @__PURE__ */ O(Y, { label: s("No recovered cycles.") }) : /* @__PURE__ */ k(v, { children: [/* @__PURE__ */ O(h, { children: /* @__PURE__ */ k(_, {
789
+ className: "hover:bg-transparent",
790
+ children: [/* @__PURE__ */ O(p, { children: /* @__PURE__ */ O(a, { id: "Owner" }) }), n.map((e) => /* @__PURE__ */ O(p, {
791
+ className: "text-right",
792
+ children: e
793
+ }, e))]
794
+ }) }), /* @__PURE__ */ O(m, { children: t.map((e) => /* @__PURE__ */ k(_, { children: [/* @__PURE__ */ O(g, { children: /* @__PURE__ */ O(r, {
795
+ className: "hover:underline",
796
+ to: U("cycles", {
797
+ owner: [e.owner],
798
+ first_outcome: N,
799
+ outcome: ["collected"]
800
+ }, i, o),
801
+ children: ye(e.owner)
802
+ }) }), e.points.map((e, t) => /* @__PURE__ */ O(g, {
803
+ className: "text-right tabular-nums",
804
+ children: G(e)
805
+ }, n[t]))] }, e.owner)) })] });
806
+ }
807
+ function Te({ scope: t, pspKey: i }) {
808
+ let { text: o } = e(), s = n().adminQueries.widgetMetrics, { data: c, isPending: l } = E(s(de(t))), u = fe(c);
809
+ return /* @__PURE__ */ O(q, {
810
+ title: o("Missed rebills"),
811
+ children: l ? /* @__PURE__ */ O(J, {}) : u.length === 0 ? /* @__PURE__ */ O(Y, { label: o("No missed rebills in this range.") }) : /* @__PURE__ */ k(v, { children: [/* @__PURE__ */ O(h, { children: /* @__PURE__ */ k(_, {
812
+ className: "hover:bg-transparent",
813
+ children: [
814
+ /* @__PURE__ */ O(p, { children: /* @__PURE__ */ O(a, { id: "Reason" }) }),
815
+ /* @__PURE__ */ O(p, { children: "PSP" }),
816
+ /* @__PURE__ */ O(p, {
817
+ className: "text-right",
818
+ children: /* @__PURE__ */ O(a, { id: "Cycles" })
819
+ })
820
+ ]
821
+ }) }), /* @__PURE__ */ O(m, { children: u.map((e) => /* @__PURE__ */ k(_, { children: [
822
+ /* @__PURE__ */ O(g, { children: e.reason }),
823
+ /* @__PURE__ */ O(g, {
824
+ className: "text-xs",
825
+ children: i(e.psp)
826
+ }),
827
+ /* @__PURE__ */ O(g, {
828
+ className: "text-right tabular-nums",
829
+ children: /* @__PURE__ */ O(r, {
830
+ className: "hover:underline",
831
+ to: U("cycles", {
832
+ first_outcome: ["missed"],
833
+ miss_reason: [e.reason]
834
+ }, t, c?.range, e.psp || void 0),
835
+ children: e.count
836
+ })
837
+ })
838
+ ] }, `${e.reason}|${e.psp}`)) })] })
839
+ });
840
+ }
841
+ function Ee({ scope: t, pspKey: i }) {
842
+ let { text: o } = e(), s = n().adminQueries.widgetMetrics, { data: c, isPending: l } = E(s(pe(t))), u = me(c), d = (e, n) => U("attempts", {
843
+ source: ["provider_schedule"],
844
+ observed_via: [n]
845
+ }, t, c?.range, e || void 0);
846
+ return /* @__PURE__ */ O(q, {
847
+ title: o("Provider charges seen by webhook"),
848
+ children: l ? /* @__PURE__ */ O(J, {}) : u.length === 0 ? /* @__PURE__ */ O(Y, { label: o("No provider-scheduled charges in this range.") }) : /* @__PURE__ */ k(v, { children: [/* @__PURE__ */ O(h, { children: /* @__PURE__ */ k(_, {
849
+ className: "hover:bg-transparent",
850
+ children: [
851
+ /* @__PURE__ */ O(p, { children: "PSP" }),
852
+ /* @__PURE__ */ O(p, {
853
+ className: "text-right",
854
+ children: /* @__PURE__ */ O(a, { id: "Webhook" })
855
+ }),
856
+ /* @__PURE__ */ O(p, {
857
+ className: "text-right",
858
+ children: /* @__PURE__ */ O(a, { id: "Pull" })
859
+ }),
860
+ /* @__PURE__ */ O(p, {
861
+ className: "text-right",
862
+ children: /* @__PURE__ */ O(a, { id: "Coverage" })
863
+ })
864
+ ]
865
+ }) }), /* @__PURE__ */ O(m, { children: u.map((e) => /* @__PURE__ */ k(_, { children: [
866
+ /* @__PURE__ */ O(g, {
867
+ className: "text-xs",
868
+ children: i(e.psp)
869
+ }),
870
+ /* @__PURE__ */ O(g, {
871
+ className: "text-right tabular-nums",
872
+ children: /* @__PURE__ */ O(r, {
873
+ className: "hover:underline",
874
+ to: d(e.psp, "webhook"),
875
+ children: e.webhook
876
+ })
877
+ }),
878
+ /* @__PURE__ */ O(g, {
879
+ className: "text-right tabular-nums",
880
+ children: /* @__PURE__ */ O(r, {
881
+ className: "hover:underline",
882
+ to: d(e.psp, "pull"),
883
+ children: e.pull
884
+ })
885
+ }),
886
+ /* @__PURE__ */ O(g, {
887
+ className: "text-right tabular-nums",
888
+ children: G(e.coverage)
889
+ })
890
+ ] }, e.psp)) })] })
891
+ });
892
+ }
893
+ function De({ scope: t }) {
894
+ let { id: r, text: o } = e(), s = n().adminQueries.widgetMetrics, c = he(t), l = E(s(c.months)), u = E(s(c.reasons)), d = E(s(c.recorded)), f = ge(d.data), y = _e(l.data, f), b = ve(u.data).slice(0, 10);
895
+ return /* @__PURE__ */ k("section", {
896
+ className: "flex flex-col gap-3",
897
+ "aria-labelledby": r("nmi-history"),
898
+ children: [/* @__PURE__ */ k("div", {
899
+ className: "flex flex-col gap-1",
900
+ children: [/* @__PURE__ */ O("h2", {
901
+ id: r("nmi-history"),
902
+ className: "text-lg font-semibold tracking-tight",
903
+ children: /* @__PURE__ */ O(a, { id: "NMI history (before OpenRails recorded attempts)" })
904
+ }), /* @__PURE__ */ k("p", {
905
+ className: "max-w-4xl text-sm text-muted-foreground",
906
+ children: [
907
+ /* @__PURE__ */ O(a, { id: "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." }),
908
+ " ",
909
+ f ? `OpenRails recorded its own attempts from ${T(f, "month")}; from then on the panels above measure them.` : "OpenRails recorded no NMI attempt in this range."
910
+ ]
911
+ })]
912
+ }), /* @__PURE__ */ k("div", {
913
+ className: "grid gap-4 xl:grid-cols-3",
914
+ children: [/* @__PURE__ */ O(q, {
915
+ title: o("Refusal rate by month"),
916
+ className: "xl:col-span-2",
917
+ children: l.isPending || d.isPending ? /* @__PURE__ */ O(J, {}) : y.length === 0 ? /* @__PURE__ */ O(Y, { label: o("No NMI history yet: it is read daily.") }) : /* @__PURE__ */ k(v, { children: [/* @__PURE__ */ O(h, { children: /* @__PURE__ */ k(_, {
918
+ className: "hover:bg-transparent",
919
+ children: [/* @__PURE__ */ O(p, { children: /* @__PURE__ */ O(a, { id: "Month" }) }), W.map((e) => /* @__PURE__ */ O(p, {
920
+ className: "text-right",
921
+ children: e.label
922
+ }, e.value))]
923
+ }) }), /* @__PURE__ */ O(m, { children: y.map((e) => /* @__PURE__ */ k(_, {
924
+ className: i(e.recorded && "text-muted-foreground"),
925
+ children: [/* @__PURE__ */ O(g, { children: /* @__PURE__ */ k("span", {
926
+ className: "flex items-center gap-2",
927
+ children: [T(e.month, "month"), e.month === f && /* @__PURE__ */ O(ee, {
928
+ variant: "outline",
929
+ children: /* @__PURE__ */ O(a, { id: "OpenRails starts" })
930
+ })]
931
+ }) }), W.map((t) => {
932
+ let n = e.kinds[t.value];
933
+ return /* @__PURE__ */ O(g, {
934
+ className: "text-right tabular-nums",
935
+ children: n ? /* @__PURE__ */ k(D, { children: [G(n.refusalRate), /* @__PURE__ */ k("span", {
936
+ className: "ml-1 text-xs text-muted-foreground",
937
+ children: [/* @__PURE__ */ O(a, { id: "of " }), n.authorizations.toLocaleString()]
938
+ })] }) : "—"
939
+ }, t.value);
940
+ })]
941
+ }, e.month)) })] })
942
+ }), /* @__PURE__ */ O(q, {
943
+ title: o("Top refusal reasons"),
944
+ children: u.isPending ? /* @__PURE__ */ O(J, {}) : b.length === 0 ? /* @__PURE__ */ O(Y, { label: o("No refusals in NMI's history.") }) : /* @__PURE__ */ k(v, { children: [/* @__PURE__ */ O(h, { children: /* @__PURE__ */ k(_, {
945
+ className: "hover:bg-transparent",
946
+ children: [
947
+ /* @__PURE__ */ O(p, { children: /* @__PURE__ */ O(a, { id: "Kind / reason" }) }),
948
+ /* @__PURE__ */ O(p, {
949
+ className: "text-right",
950
+ children: /* @__PURE__ */ O(a, { id: "Refused" })
951
+ }),
952
+ /* @__PURE__ */ O(p, {
953
+ className: "text-right",
954
+ children: /* @__PURE__ */ O(a, { id: "Share" })
955
+ })
956
+ ]
957
+ }) }), /* @__PURE__ */ O(m, { children: b.map((e) => /* @__PURE__ */ k(_, { children: [
958
+ /* @__PURE__ */ k(g, { children: [/* @__PURE__ */ k("span", {
959
+ className: "block text-xs text-muted-foreground",
960
+ children: [
961
+ W.find((t) => t.value === e.kind)?.label ?? e.kind,
962
+ " ",
963
+ "· ",
964
+ e.category
965
+ ]
966
+ }), e.reason] }),
967
+ /* @__PURE__ */ O(g, {
968
+ className: "text-right tabular-nums",
969
+ children: e.count.toLocaleString()
970
+ }),
971
+ /* @__PURE__ */ O(g, {
972
+ className: "text-right tabular-nums",
973
+ children: G(e.share)
974
+ })
975
+ ] }, `${e.kind}|${e.category}|${e.reason}`)) })] })
976
+ })]
977
+ })]
978
+ });
979
+ }
980
+ //#endregion
981
+ export { be as PaymentHealthPage };
982
+
983
+ //# sourceMappingURL=admin-health-B4jN2LwR.js.map