@openrails/billing-ui 0.242.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 (260) 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 +2171 -176
  236. package/dist/client/generated/wire.d.ts +1273 -0
  237. package/dist/{hooks-Uiw-zW3H.js → hooks-Ckd8F2JF.js} +7 -7
  238. package/dist/hooks-Ckd8F2JF.js.map +1 -0
  239. package/dist/index.d.ts +1 -1
  240. package/dist/index.js +11 -11
  241. package/dist/index.js.map +1 -1
  242. package/dist/lib/{offer-label.d.ts → price-label.d.ts} +1 -1
  243. package/dist/locales/de.js +1 -1
  244. package/dist/locales/de.js.map +1 -1
  245. package/dist/locales/en.d.ts +1 -1
  246. package/dist/locales/en.js +1 -1
  247. package/dist/locales/en.js.map +1 -1
  248. package/dist/locales/es.js +1 -1
  249. package/dist/locales/es.js.map +1 -1
  250. package/dist/locales/ja.js +1 -1
  251. package/dist/locales/ja.js.map +1 -1
  252. package/dist/locales/ko.js +1 -1
  253. package/dist/locales/ko.js.map +1 -1
  254. package/dist/locales/zh.js +1 -1
  255. package/dist/locales/zh.js.map +1 -1
  256. package/dist/{offers.d.ts → product-list.d.ts} +5 -5
  257. package/dist/react.js +1 -1
  258. package/dist/styles.css +1 -1
  259. package/package.json +28 -6
  260. package/dist/hooks-Uiw-zW3H.js.map +0 -1
@@ -0,0 +1,1434 @@
1
+ import { E as e, S as t, f as n, l as r, p as i, w as a } from "./admin-utils-BK4Vh1o_.js";
2
+ import { t as o } from "./admin-button-CTL3DgOt.js";
3
+ import { t as s } from "./admin-input-CcfQfJFN.js";
4
+ import { a as c, i as l, l as u, n as d, u as f } from "./admin-capabilities-BuigAgtm.js";
5
+ import { n as p, o as m, s as h, t as g } from "./admin-format-DoohJ7Fg.js";
6
+ import { n as _ } from "./admin-confirm-katGq0Qo.js";
7
+ import { t as v } from "./admin-form-field-errors-hbUMIriS.js";
8
+ import { a as y, i as b, n as x, r as S, t as C } from "./admin-select-DBgprVW6.js";
9
+ import { a as w, n as ee, o as te, r as T, s as E, t as ne } from "./admin-table-CH9TrXJf.js";
10
+ import { t as D } from "./admin-badge-DR5-1qd8.js";
11
+ import { a as O, i as k, n as A, o as j, r as M, s as N, t as P } from "./admin-dialog-BjuKI5Hp.js";
12
+ import { t as F } from "./admin-label-BiEN5cjb.js";
13
+ import { t as re } from "./admin-switch-BJUxLCsa.js";
14
+ import { n as I } from "./admin-dialog-width-BPrgdYlj.js";
15
+ import { i as L, n as R, r as ie, t as ae } from "./admin-tabs-528FJMjt.js";
16
+ import { t as z } from "./admin-typed-confirm-dialog-DU7m9-O7.js";
17
+ import * as B from "react";
18
+ import { useMutation as V, useQuery as H, useQueryClient as U } from "@tanstack/react-query";
19
+ import { Fragment as oe, jsx as W, jsxs as G } from "react/jsx-runtime";
20
+ import { HugeiconsIcon as se } from "@hugeicons/react";
21
+ import { Add01Icon as ce, Delete02Icon as le } from "@hugeicons/core-free-icons";
22
+ import { useForm as K } from "@tanstack/react-form";
23
+ //#region src/admin/pages/settings/configuration-edit.ts
24
+ function q(e) {
25
+ let { toast: n, toastApiError: r, toastStaleEdit: a, adminMutations: o } = i(), [s, c] = B.useState(null), l = U(), u = V(o.updateMerchantConfiguration(l));
26
+ return {
27
+ editing: s !== null,
28
+ open: () => {
29
+ e && c(e.revision);
30
+ },
31
+ close: () => c(null),
32
+ save: async (e, i, o) => {
33
+ if (s !== null) try {
34
+ await u.mutateAsync({
35
+ ...e,
36
+ expected_revision: s
37
+ }), n.success(i), c(null);
38
+ } catch (e) {
39
+ if (e instanceof t && e.revisionMismatch) {
40
+ a("The configuration"), c(null);
41
+ return;
42
+ }
43
+ r(e, o), e instanceof t && e.merchantConfigReadOnly && c(null);
44
+ }
45
+ }
46
+ };
47
+ }
48
+ //#endregion
49
+ //#region src/admin/pages/settings/setting-fields.tsx
50
+ function J() {
51
+ let { adminQueries: e } = i(), { data: t } = H(e.config());
52
+ return !t || t.capabilities.features?.merchant_config_edits ? null : /* @__PURE__ */ W("p", {
53
+ className: "rounded-md border px-3 py-2 text-sm text-muted-foreground",
54
+ children: /* @__PURE__ */ W(a, { id: "Read-only: this merchant's configuration comes from a file. Change it there." })
55
+ });
56
+ }
57
+ function Y({ edits: e, editing: t, form: n, saving: r, canSave: i = !0, onEdit: s, onCancel: c }) {
58
+ return e ? t ? /* @__PURE__ */ G("div", {
59
+ className: "flex items-center gap-2",
60
+ children: [/* @__PURE__ */ W(o, {
61
+ type: "button",
62
+ variant: "outline",
63
+ size: "sm",
64
+ disabled: r,
65
+ onClick: c,
66
+ children: /* @__PURE__ */ W(a, { id: "Cancel" })
67
+ }), /* @__PURE__ */ W(o, {
68
+ type: "submit",
69
+ size: "sm",
70
+ form: n,
71
+ disabled: !i || r,
72
+ children: r ? "Saving…" : "Save"
73
+ })]
74
+ }) : /* @__PURE__ */ W(o, {
75
+ type: "button",
76
+ variant: "outline",
77
+ size: "sm",
78
+ onClick: s,
79
+ children: /* @__PURE__ */ W(a, { id: "Edit" })
80
+ }) : null;
81
+ }
82
+ function X({ label: e, value: t }) {
83
+ return /* @__PURE__ */ G("div", {
84
+ className: "grid gap-1.5 md:grid-cols-[11rem_minmax(0,1fr)] md:gap-6",
85
+ children: [/* @__PURE__ */ W("dt", {
86
+ className: "text-sm text-muted-foreground",
87
+ children: e
88
+ }), /* @__PURE__ */ W("dd", {
89
+ className: t ? "min-w-0 text-sm break-words" : "text-sm text-muted-foreground",
90
+ children: t || "Not set"
91
+ })]
92
+ });
93
+ }
94
+ function Z({ label: t, id: n, children: r }) {
95
+ let { id: i } = e();
96
+ return /* @__PURE__ */ G("div", {
97
+ className: "grid gap-2 md:grid-cols-[11rem_minmax(0,1fr)] md:items-center md:gap-6",
98
+ children: [/* @__PURE__ */ W(F, {
99
+ htmlFor: i(n),
100
+ children: t
101
+ }), /* @__PURE__ */ W("div", {
102
+ className: "min-w-0",
103
+ children: r
104
+ })]
105
+ });
106
+ }
107
+ //#endregion
108
+ //#region src/admin/pages/settings/notifications.tsx
109
+ function ue() {
110
+ let { adminQueries: e } = i(), t = H(e.merchantConfiguration("Load settings")), n = H(e.webhooks()), r = f(), o = n.data?.data ?? [];
111
+ return /* @__PURE__ */ G("div", {
112
+ className: "flex flex-col gap-10",
113
+ children: [
114
+ /* @__PURE__ */ W(J, {}),
115
+ t.data ? /* @__PURE__ */ W(de, {
116
+ configuration: t.data,
117
+ edits: r
118
+ }) : /* @__PURE__ */ W("p", {
119
+ className: "text-sm text-muted-foreground",
120
+ children: /* @__PURE__ */ W(a, { id: "Loading…" })
121
+ }),
122
+ /* @__PURE__ */ W(pe, {
123
+ webhooks: o,
124
+ loading: n.isPending,
125
+ edits: r
126
+ })
127
+ ]
128
+ });
129
+ }
130
+ function de({ configuration: t, edits: n }) {
131
+ let { id: r, text: i } = e(), o = t.settings.alert_email ?? "", c = q(t), l = K({
132
+ defaultValues: { email: o },
133
+ onSubmit: ({ value: e }) => c.save({ settings: { alert_email: e.email.trim() } }, e.email.trim() ? "Alert email saved" : "Alert email cleared", "Save alert email")
134
+ });
135
+ return /* @__PURE__ */ G("section", {
136
+ className: "grid gap-5",
137
+ children: [/* @__PURE__ */ G("div", {
138
+ className: "flex flex-wrap items-start justify-between gap-4",
139
+ children: [/* @__PURE__ */ G("div", {
140
+ className: "grid gap-1",
141
+ children: [/* @__PURE__ */ W("h2", {
142
+ className: "text-base font-semibold",
143
+ children: /* @__PURE__ */ W(a, { id: "Email delivery" })
144
+ }), /* @__PURE__ */ W("p", {
145
+ className: "text-sm text-muted-foreground",
146
+ children: /* @__PURE__ */ W(a, { id: "Send email alerts to this address." })
147
+ })]
148
+ }), /* @__PURE__ */ W(l.Subscribe, {
149
+ selector: (e) => e.isSubmitting,
150
+ children: (e) => /* @__PURE__ */ W(Y, {
151
+ edits: n,
152
+ editing: c.editing,
153
+ form: "alert-email-form",
154
+ saving: e,
155
+ onEdit: () => {
156
+ l.reset({ email: o }), c.open();
157
+ },
158
+ onCancel: c.close
159
+ })
160
+ })]
161
+ }), c.editing ? /* @__PURE__ */ W("form", {
162
+ id: r("alert-email-form"),
163
+ onSubmit: (e) => {
164
+ e.preventDefault(), e.stopPropagation(), l.handleSubmit();
165
+ },
166
+ children: /* @__PURE__ */ W(l.Field, {
167
+ name: "email",
168
+ children: (e) => /* @__PURE__ */ W(Z, {
169
+ label: i("Alert email"),
170
+ id: "alert-email",
171
+ children: /* @__PURE__ */ W(s, {
172
+ id: r("alert-email"),
173
+ type: "email",
174
+ placeholder: i("alerts@example.com"),
175
+ value: e.state.value,
176
+ onBlur: e.handleBlur,
177
+ onChange: (t) => e.handleChange(t.target.value)
178
+ })
179
+ })
180
+ })
181
+ }) : /* @__PURE__ */ W("dl", { children: /* @__PURE__ */ W(X, {
182
+ label: i("Alert email"),
183
+ value: o
184
+ }) })]
185
+ });
186
+ }
187
+ var fe = [
188
+ {
189
+ value: "generic",
190
+ label: "Generic (your own receiver)"
191
+ },
192
+ {
193
+ value: "discord",
194
+ label: "Discord"
195
+ },
196
+ {
197
+ value: "slack",
198
+ label: "Slack"
199
+ }
200
+ ];
201
+ function pe({ webhooks: e, loading: t, edits: n }) {
202
+ return /* @__PURE__ */ G("section", {
203
+ className: "grid gap-5",
204
+ children: [/* @__PURE__ */ G("div", {
205
+ className: "flex flex-wrap items-start justify-between gap-4",
206
+ children: [/* @__PURE__ */ G("div", {
207
+ className: "grid max-w-2xl gap-1",
208
+ children: [/* @__PURE__ */ W("h2", {
209
+ className: "text-base font-semibold",
210
+ children: /* @__PURE__ */ W(a, { id: "Webhooks" })
211
+ }), /* @__PURE__ */ W("p", {
212
+ className: "text-sm text-pretty text-muted-foreground",
213
+ children: /* @__PURE__ */ W(a, { id: "Send alerts to Discord, Slack, or your own endpoint." })
214
+ })]
215
+ }), n && /* @__PURE__ */ W(he, {})]
216
+ }), t ? /* @__PURE__ */ W("p", {
217
+ className: "text-sm text-muted-foreground",
218
+ children: /* @__PURE__ */ W(a, { id: "Loading…" })
219
+ }) : e.length === 0 ? /* @__PURE__ */ W("p", {
220
+ className: "py-2 text-sm text-muted-foreground",
221
+ children: /* @__PURE__ */ W(a, { id: "No webhooks configured." })
222
+ }) : /* @__PURE__ */ G(ne, {
223
+ className: "min-w-[36rem]",
224
+ children: [/* @__PURE__ */ W(te, { children: /* @__PURE__ */ G(E, {
225
+ className: "hover:bg-transparent",
226
+ children: [
227
+ /* @__PURE__ */ W(w, {
228
+ className: "text-muted-foreground",
229
+ children: /* @__PURE__ */ W(a, { id: "Name" })
230
+ }),
231
+ /* @__PURE__ */ W(w, {
232
+ className: "text-muted-foreground",
233
+ children: /* @__PURE__ */ W(a, { id: "Format" })
234
+ }),
235
+ /* @__PURE__ */ W(w, {
236
+ className: "text-muted-foreground",
237
+ children: "URL"
238
+ }),
239
+ n && /* @__PURE__ */ W(w, {
240
+ className: "text-right text-muted-foreground",
241
+ children: /* @__PURE__ */ W(a, { id: "Action" })
242
+ })
243
+ ]
244
+ }) }), /* @__PURE__ */ W(ee, { children: e.map((e) => /* @__PURE__ */ W(me, {
245
+ webhook: e,
246
+ edits: n
247
+ }, e.id)) })]
248
+ })]
249
+ });
250
+ }
251
+ function me({ webhook: t, edits: n }) {
252
+ let { toast: r, toastApiError: s, adminMutations: c } = i(), { text: l } = e(), [u, d] = B.useState(!1), f = U(), p = V(c.deleteWebhook(f)), m = t.name ?? t.destination_host;
253
+ return /* @__PURE__ */ G(E, {
254
+ className: t.enabled ? void 0 : "opacity-60",
255
+ children: [
256
+ /* @__PURE__ */ W(T, {
257
+ className: "py-3 font-medium",
258
+ children: m
259
+ }),
260
+ /* @__PURE__ */ W(T, {
261
+ className: "py-3",
262
+ children: /* @__PURE__ */ G("span", {
263
+ className: "flex flex-wrap gap-1",
264
+ children: [/* @__PURE__ */ W(D, {
265
+ variant: "secondary",
266
+ children: t.format
267
+ }), !t.enabled && /* @__PURE__ */ W(D, {
268
+ variant: "outline",
269
+ children: /* @__PURE__ */ W(a, { id: "disabled" })
270
+ })]
271
+ })
272
+ }),
273
+ /* @__PURE__ */ W(T, {
274
+ className: "max-w-[22rem] truncate py-3 text-xs text-muted-foreground",
275
+ title: t.destination_host,
276
+ children: t.destination_host
277
+ }),
278
+ n && /* @__PURE__ */ W(T, {
279
+ className: "py-3 text-right",
280
+ children: /* @__PURE__ */ G("div", {
281
+ className: "flex justify-end gap-1",
282
+ children: [
283
+ /* @__PURE__ */ W(he, { webhook: t }),
284
+ /* @__PURE__ */ W(o, {
285
+ variant: "ghost",
286
+ size: "icon",
287
+ "aria-label": l("Delete webhook"),
288
+ onClick: () => d(!0),
289
+ children: /* @__PURE__ */ W(se, {
290
+ icon: le,
291
+ className: "size-4 text-muted-foreground"
292
+ })
293
+ }),
294
+ /* @__PURE__ */ W(z, {
295
+ open: u,
296
+ onOpenChange: d,
297
+ title: `Delete "${m}"?`,
298
+ description: l("Operational notifications will stop delivering to this webhook. This cannot be undone."),
299
+ confirmationWord: "DELETE",
300
+ actionLabel: "Delete webhook",
301
+ onConfirm: async () => {
302
+ try {
303
+ await p.mutateAsync(t.id), r.success("Webhook deleted");
304
+ } catch (e) {
305
+ s(e, "Delete webhook");
306
+ }
307
+ }
308
+ })
309
+ ]
310
+ })
311
+ })
312
+ ]
313
+ });
314
+ }
315
+ function he({ webhook: t }) {
316
+ let { toast: n, toastApiError: r, adminMutations: c } = i(), { id: l, text: u } = e(), [d, f] = B.useState(!1), p = U(), m = V(c.createWebhook(p)), h = V(c.updateWebhook(p)), g = () => ({
317
+ name: t?.name ?? "",
318
+ url: "",
319
+ format: t?.format ?? "generic",
320
+ enabled: t?.enabled ?? !0
321
+ }), _ = K({
322
+ defaultValues: g(),
323
+ onSubmit: async ({ value: e }) => {
324
+ let i = e.url.trim();
325
+ try {
326
+ t ? await h.mutateAsync({
327
+ id: t.id,
328
+ webhook: {
329
+ name: e.name.trim() || null,
330
+ format: e.format,
331
+ enabled: e.enabled,
332
+ ...i ? { url: i } : {}
333
+ }
334
+ }) : await m.mutateAsync({
335
+ name: e.name.trim(),
336
+ url: i,
337
+ format: e.format
338
+ }), n.success(t ? "Webhook saved" : "Webhook added"), w(!1);
339
+ } catch (e) {
340
+ r(e, t ? "Save webhook" : "Add webhook");
341
+ }
342
+ }
343
+ }), w = (e) => {
344
+ e ? _.reset(g()) : _.reset(), f(e);
345
+ };
346
+ return /* @__PURE__ */ G(P, {
347
+ open: d,
348
+ onOpenChange: w,
349
+ children: [/* @__PURE__ */ W(N, { render: /* @__PURE__ */ G(o, {
350
+ size: "sm",
351
+ variant: "outline",
352
+ children: [
353
+ !t && /* @__PURE__ */ W(se, {
354
+ icon: ce,
355
+ className: "size-4"
356
+ }),
357
+ " ",
358
+ t ? "Edit" : "Add webhook"
359
+ ]
360
+ }) }), /* @__PURE__ */ G(A, {
361
+ className: I,
362
+ children: [/* @__PURE__ */ G(O, { children: [/* @__PURE__ */ W(j, { children: t ? `Edit ${t.name ?? t.destination_host}` : "Add webhook" }), /* @__PURE__ */ W(M, { children: t ? "The current URL is never shown. Paste a new one to replace it, or leave it blank to keep it." : "Paste a webhook address from Discord, Slack, or your own alert receiver." })] }), /* @__PURE__ */ G("form", {
363
+ onSubmit: (e) => {
364
+ e.preventDefault(), e.stopPropagation(), _.handleSubmit();
365
+ },
366
+ className: "grid gap-4",
367
+ children: [/* @__PURE__ */ G("div", {
368
+ className: "grid gap-3",
369
+ children: [
370
+ /* @__PURE__ */ W(_.Field, {
371
+ name: "name",
372
+ validators: { onChange: ({ value: e }) => t || e.trim() ? void 0 : "Enter a webhook name" },
373
+ children: (e) => /* @__PURE__ */ G("div", {
374
+ className: "grid gap-1.5",
375
+ children: [
376
+ /* @__PURE__ */ W(F, {
377
+ htmlFor: l("wh-name"),
378
+ children: /* @__PURE__ */ W(a, { id: "Name" })
379
+ }),
380
+ /* @__PURE__ */ W(s, {
381
+ id: l("wh-name"),
382
+ placeholder: u("e.g. #billing-alerts"),
383
+ value: e.state.value,
384
+ onBlur: e.handleBlur,
385
+ onChange: (t) => e.handleChange(t.target.value),
386
+ "aria-invalid": e.state.meta.errors.length > 0
387
+ }),
388
+ /* @__PURE__ */ W(v, { errors: e.state.meta.errors })
389
+ ]
390
+ })
391
+ }),
392
+ /* @__PURE__ */ W(_.Field, {
393
+ name: "format",
394
+ children: (e) => /* @__PURE__ */ G("div", {
395
+ className: "grid gap-1.5",
396
+ children: [/* @__PURE__ */ W(F, {
397
+ htmlFor: l("wh-format"),
398
+ children: /* @__PURE__ */ W(a, { id: "Format" })
399
+ }), /* @__PURE__ */ G(C, {
400
+ value: e.state.value,
401
+ onValueChange: (t) => e.handleChange(t),
402
+ children: [/* @__PURE__ */ W(b, {
403
+ id: l("wh-format"),
404
+ className: "w-full",
405
+ children: /* @__PURE__ */ W(y, {})
406
+ }), /* @__PURE__ */ W(x, { children: fe.map((e) => /* @__PURE__ */ W(S, {
407
+ value: e.value,
408
+ children: e.label
409
+ }, e.value)) })]
410
+ })]
411
+ })
412
+ }),
413
+ /* @__PURE__ */ W(_.Field, {
414
+ name: "url",
415
+ validators: { onChange: ({ value: e }) => {
416
+ if (!e.trim()) return t ? void 0 : "Enter a webhook URL";
417
+ try {
418
+ new URL(e);
419
+ return;
420
+ } catch {
421
+ return "Enter a valid webhook URL";
422
+ }
423
+ } },
424
+ children: (e) => /* @__PURE__ */ G("div", {
425
+ className: "grid gap-1.5",
426
+ children: [
427
+ /* @__PURE__ */ W(F, {
428
+ htmlFor: l("wh-url"),
429
+ children: /* @__PURE__ */ W(a, { id: "Webhook URL" })
430
+ }),
431
+ /* @__PURE__ */ W(s, {
432
+ id: l("wh-url"),
433
+ type: "url",
434
+ autoComplete: "off",
435
+ className: "text-xs",
436
+ placeholder: t ? "unchanged" : "https://discord.com/api/webhooks/…",
437
+ value: e.state.value,
438
+ onBlur: e.handleBlur,
439
+ onChange: (t) => e.handleChange(t.target.value),
440
+ "aria-invalid": e.state.meta.errors.length > 0
441
+ }),
442
+ /* @__PURE__ */ W(v, { errors: e.state.meta.errors })
443
+ ]
444
+ })
445
+ }),
446
+ t && /* @__PURE__ */ W(_.Field, {
447
+ name: "enabled",
448
+ children: (e) => /* @__PURE__ */ G("div", {
449
+ className: "flex items-center gap-2",
450
+ children: [/* @__PURE__ */ W(re, {
451
+ id: l("wh-enabled"),
452
+ checked: e.state.value,
453
+ onCheckedChange: e.handleChange
454
+ }), /* @__PURE__ */ W(F, {
455
+ htmlFor: l("wh-enabled"),
456
+ children: /* @__PURE__ */ W(a, { id: "Enabled" })
457
+ })]
458
+ })
459
+ })
460
+ ]
461
+ }), /* @__PURE__ */ W(k, { children: /* @__PURE__ */ W(_.Subscribe, {
462
+ selector: (e) => [
463
+ e.values.name,
464
+ e.values.url,
465
+ e.isDirty,
466
+ e.canSubmit,
467
+ e.isSubmitting
468
+ ],
469
+ children: ([e, n, r, i, a]) => /* @__PURE__ */ W(o, {
470
+ type: "submit",
471
+ disabled: (t ? !r : !e.trim() || !n.trim()) || !i || a,
472
+ children: a ? "Saving…" : t ? "Save" : "Add webhook"
473
+ })
474
+ }) })]
475
+ })]
476
+ })]
477
+ });
478
+ }
479
+ //#endregion
480
+ //#region src/admin/pages/settings/index.tsx
481
+ var Q = "flex-none px-0 after:bg-primary group-data-horizontal/tabs:after:bottom-[-1px]";
482
+ function ge() {
483
+ let [e, t] = r(), i = u(), o = l(), s = n().props.settingsTabs ?? [], c = s.map((e) => e.value), f = d(null, i, o, c), p = d(e.get("tab"), i, o, c);
484
+ return /* @__PURE__ */ G(ae, {
485
+ value: p,
486
+ onValueChange: (n) => {
487
+ let r = new URLSearchParams(e);
488
+ !n || n === f ? r.delete("tab") : r.set("tab", n), t(r);
489
+ },
490
+ className: "flex flex-col gap-4",
491
+ children: [
492
+ /* @__PURE__ */ W("div", {
493
+ className: "overflow-x-auto",
494
+ children: /* @__PURE__ */ G(ie, {
495
+ variant: "line",
496
+ className: "w-max min-w-full justify-start gap-6 rounded-none p-0",
497
+ children: [
498
+ i && /* @__PURE__ */ W(L, {
499
+ value: "merchant",
500
+ className: Q,
501
+ children: /* @__PURE__ */ W(a, { id: "Merchant" })
502
+ }),
503
+ i && /* @__PURE__ */ W(L, {
504
+ value: "notifications",
505
+ className: Q,
506
+ children: /* @__PURE__ */ W(a, { id: "Notifications" })
507
+ }),
508
+ i && /* @__PURE__ */ W(L, {
509
+ value: "psps",
510
+ className: Q,
511
+ children: /* @__PURE__ */ W(a, { id: "PSPs" })
512
+ }),
513
+ o && /* @__PURE__ */ W(L, {
514
+ value: "customer-controls",
515
+ className: Q,
516
+ children: /* @__PURE__ */ W(a, { id: "Customer controls" })
517
+ }),
518
+ s.map((e) => /* @__PURE__ */ W(L, {
519
+ value: e.value,
520
+ className: Q,
521
+ children: e.title
522
+ }, e.value))
523
+ ]
524
+ })
525
+ }),
526
+ i && /* @__PURE__ */ W(R, {
527
+ value: "merchant",
528
+ children: /* @__PURE__ */ W(_e, {})
529
+ }),
530
+ i && /* @__PURE__ */ W(R, {
531
+ value: "notifications",
532
+ children: /* @__PURE__ */ W(ue, {})
533
+ }),
534
+ i && /* @__PURE__ */ W(R, {
535
+ value: "psps",
536
+ children: /* @__PURE__ */ W(be, {})
537
+ }),
538
+ o && /* @__PURE__ */ W(R, {
539
+ value: "customer-controls",
540
+ children: /* @__PURE__ */ W(Ae, {})
541
+ }),
542
+ s.map((e) => /* @__PURE__ */ W(R, {
543
+ value: e.value,
544
+ children: e.element
545
+ }, e.value))
546
+ ]
547
+ });
548
+ }
549
+ function _e() {
550
+ let { adminQueries: e } = i(), { data: t } = H(e.merchantConfiguration("Load settings")), n = f();
551
+ return t ? /* @__PURE__ */ G("div", {
552
+ className: "grid gap-10",
553
+ children: [
554
+ /* @__PURE__ */ W(J, {}),
555
+ /* @__PURE__ */ W(ve, {
556
+ configuration: t,
557
+ edits: n
558
+ }),
559
+ /* @__PURE__ */ W(ye, {
560
+ configuration: t,
561
+ edits: n
562
+ })
563
+ ]
564
+ }) : /* @__PURE__ */ W("p", {
565
+ className: "text-sm text-muted-foreground",
566
+ children: /* @__PURE__ */ W(a, { id: "Loading…" })
567
+ });
568
+ }
569
+ function ve({ configuration: t, edits: n }) {
570
+ let { id: r, text: i } = e(), o = t.settings.profile, c = () => ({
571
+ displayName: t.display_name,
572
+ fromEmail: o?.from_email ?? "",
573
+ supportURL: o?.support_url ?? "",
574
+ logoURL: o?.logo_url ?? ""
575
+ }), l = q(t), u = K({
576
+ defaultValues: c(),
577
+ onSubmit: ({ value: e }) => l.save({
578
+ display_name: e.displayName.trim(),
579
+ settings: { profile: {
580
+ from_email: e.fromEmail || void 0,
581
+ support_url: e.supportURL || void 0,
582
+ logo_url: e.logoURL || void 0
583
+ } }
584
+ }, "Profile saved", "Save profile")
585
+ });
586
+ return /* @__PURE__ */ G("section", {
587
+ className: "grid gap-5",
588
+ children: [/* @__PURE__ */ G("div", {
589
+ className: "flex flex-wrap items-start justify-between gap-4",
590
+ children: [/* @__PURE__ */ G("div", {
591
+ className: "grid gap-1",
592
+ children: [/* @__PURE__ */ W("h2", {
593
+ className: "text-base font-semibold",
594
+ children: /* @__PURE__ */ W(a, { id: "Merchant profile" })
595
+ }), /* @__PURE__ */ W("p", {
596
+ className: "text-sm text-pretty text-muted-foreground",
597
+ children: /* @__PURE__ */ W(a, { id: "Customer-facing merchant details used on invoices and emails." })
598
+ })]
599
+ }), /* @__PURE__ */ W(u.Subscribe, {
600
+ selector: (e) => [e.canSubmit, e.isSubmitting],
601
+ children: ([e, t]) => /* @__PURE__ */ W(Y, {
602
+ edits: n,
603
+ editing: l.editing,
604
+ form: "merchant-profile-form",
605
+ saving: t,
606
+ canSave: e,
607
+ onEdit: () => {
608
+ u.reset(c()), l.open();
609
+ },
610
+ onCancel: l.close
611
+ })
612
+ })]
613
+ }), l.editing ? /* @__PURE__ */ G("form", {
614
+ id: r("merchant-profile-form"),
615
+ onSubmit: (e) => {
616
+ e.preventDefault(), e.stopPropagation(), u.handleSubmit();
617
+ },
618
+ className: "grid gap-4",
619
+ children: [
620
+ /* @__PURE__ */ W(u.Field, {
621
+ name: "displayName",
622
+ validators: { onChange: ({ value: e }) => e.trim() ? void 0 : "Enter the merchant's name" },
623
+ children: (e) => /* @__PURE__ */ W(Z, {
624
+ label: i("Display name"),
625
+ id: "s-name",
626
+ children: /* @__PURE__ */ G("div", {
627
+ className: "grid gap-1.5",
628
+ children: [/* @__PURE__ */ W(s, {
629
+ id: r("s-name"),
630
+ value: e.state.value,
631
+ onBlur: e.handleBlur,
632
+ onChange: (t) => e.handleChange(t.target.value),
633
+ autoComplete: "organization",
634
+ "aria-invalid": e.state.meta.errors.length > 0
635
+ }), /* @__PURE__ */ W(v, { errors: e.state.meta.errors })]
636
+ })
637
+ })
638
+ }),
639
+ /* @__PURE__ */ W(u.Field, {
640
+ name: "fromEmail",
641
+ children: (e) => /* @__PURE__ */ W(Z, {
642
+ label: i("From email"),
643
+ id: "s-email",
644
+ children: /* @__PURE__ */ W(s, {
645
+ id: r("s-email"),
646
+ type: "email",
647
+ value: e.state.value,
648
+ onBlur: e.handleBlur,
649
+ onChange: (t) => e.handleChange(t.target.value),
650
+ autoComplete: "email"
651
+ })
652
+ })
653
+ }),
654
+ /* @__PURE__ */ W(u.Field, {
655
+ name: "supportURL",
656
+ children: (e) => /* @__PURE__ */ W(Z, {
657
+ label: i("Support URL"),
658
+ id: "s-support",
659
+ children: /* @__PURE__ */ W(s, {
660
+ id: r("s-support"),
661
+ type: "url",
662
+ value: e.state.value,
663
+ onBlur: e.handleBlur,
664
+ onChange: (t) => e.handleChange(t.target.value),
665
+ placeholder: i("https://example.com/support")
666
+ })
667
+ })
668
+ }),
669
+ /* @__PURE__ */ W(u.Field, {
670
+ name: "logoURL",
671
+ children: (e) => /* @__PURE__ */ W(Z, {
672
+ label: i("Logo URL"),
673
+ id: "s-logo",
674
+ children: /* @__PURE__ */ W(s, {
675
+ id: r("s-logo"),
676
+ type: "url",
677
+ value: e.state.value,
678
+ onBlur: e.handleBlur,
679
+ onChange: (t) => e.handleChange(t.target.value),
680
+ placeholder: i("https://example.com/logo.png")
681
+ })
682
+ })
683
+ })
684
+ ]
685
+ }) : /* @__PURE__ */ G("dl", {
686
+ className: "grid gap-4",
687
+ children: [
688
+ /* @__PURE__ */ W(X, {
689
+ label: i("Display name"),
690
+ value: t.display_name
691
+ }),
692
+ /* @__PURE__ */ W(X, {
693
+ label: i("From email"),
694
+ value: o?.from_email
695
+ }),
696
+ /* @__PURE__ */ W(X, {
697
+ label: i("Support URL"),
698
+ value: o?.support_url
699
+ }),
700
+ /* @__PURE__ */ W(X, {
701
+ label: i("Logo URL"),
702
+ value: o?.logo_url
703
+ })
704
+ ]
705
+ })]
706
+ });
707
+ }
708
+ function ye({ configuration: t, edits: n }) {
709
+ let { id: r, text: i } = e(), o = t.settings.reprice_notice_window_days ?? 30, c = q(t), l = K({
710
+ defaultValues: { days: String(o) },
711
+ onSubmit: ({ value: e }) => c.save({ settings: { reprice_notice_window_days: Number(e.days) } }, "Notice window saved", "Save notice window")
712
+ });
713
+ return /* @__PURE__ */ G("section", {
714
+ className: "grid gap-5",
715
+ children: [/* @__PURE__ */ G("div", {
716
+ className: "flex flex-wrap items-start justify-between gap-4",
717
+ children: [/* @__PURE__ */ G("div", {
718
+ className: "grid max-w-2xl gap-1",
719
+ children: [/* @__PURE__ */ W("h2", {
720
+ className: "text-base font-semibold",
721
+ children: /* @__PURE__ */ W(a, { id: "Pricing policies" })
722
+ }), /* @__PURE__ */ W("p", {
723
+ className: "text-sm text-pretty text-muted-foreground",
724
+ children: /* @__PURE__ */ W(a, { id: "Set how much notice customers receive before a price increase." })
725
+ })]
726
+ }), /* @__PURE__ */ W(l.Subscribe, {
727
+ selector: (e) => [e.canSubmit, e.isSubmitting],
728
+ children: ([e, t]) => /* @__PURE__ */ W(Y, {
729
+ edits: n,
730
+ editing: c.editing,
731
+ form: "notice-window-form",
732
+ saving: t,
733
+ canSave: e,
734
+ onEdit: () => {
735
+ l.reset({ days: String(o) }), c.open();
736
+ },
737
+ onCancel: c.close
738
+ })
739
+ })]
740
+ }), c.editing ? /* @__PURE__ */ W("form", {
741
+ id: r("notice-window-form"),
742
+ onSubmit: (e) => {
743
+ e.preventDefault(), e.stopPropagation(), l.handleSubmit();
744
+ },
745
+ children: /* @__PURE__ */ W(l.Field, {
746
+ name: "days",
747
+ validators: { onChange: ({ value: e }) => {
748
+ let t = Number(e);
749
+ return e.trim() && Number.isInteger(t) && t >= 0 ? void 0 : "Enter a whole number of days";
750
+ } },
751
+ children: (e) => /* @__PURE__ */ W(Z, {
752
+ label: i("Notice period (days)"),
753
+ id: "s-notice-window",
754
+ children: /* @__PURE__ */ G("div", {
755
+ className: "grid gap-1.5",
756
+ children: [/* @__PURE__ */ W(s, {
757
+ id: r("s-notice-window"),
758
+ type: "number",
759
+ step: "1",
760
+ min: "0",
761
+ value: e.state.value,
762
+ onBlur: e.handleBlur,
763
+ onChange: (t) => e.handleChange(t.target.value),
764
+ "aria-invalid": e.state.meta.errors.length > 0
765
+ }), /* @__PURE__ */ W(v, { errors: e.state.meta.errors })]
766
+ })
767
+ })
768
+ })
769
+ }) : /* @__PURE__ */ W("dl", { children: /* @__PURE__ */ W(X, {
770
+ label: i("Notice period"),
771
+ value: `${o} ${o === 1 ? "day" : "days"}`
772
+ }) })]
773
+ });
774
+ }
775
+ function be() {
776
+ let { selectedMerchant: e, adminQueries: t } = i(), n = H(t.psps()), r = H(t.rails()), o = f();
777
+ if (n.isPending || r.isPending) return /* @__PURE__ */ W("p", {
778
+ className: "text-sm text-muted-foreground",
779
+ children: /* @__PURE__ */ W(a, { id: "Loading…" })
780
+ });
781
+ let s = r.data ?? [];
782
+ return /* @__PURE__ */ G("div", {
783
+ className: "grid gap-6",
784
+ children: [/* @__PURE__ */ W(J, {}), /* @__PURE__ */ G("section", {
785
+ className: "grid gap-5",
786
+ children: [/* @__PURE__ */ G("div", {
787
+ className: "flex flex-wrap items-start justify-between gap-4",
788
+ children: [/* @__PURE__ */ G("div", {
789
+ className: "grid gap-1",
790
+ children: [/* @__PURE__ */ W("h2", {
791
+ className: "text-base font-semibold",
792
+ children: /* @__PURE__ */ W(a, { id: "PSPs" })
793
+ }), /* @__PURE__ */ W("p", {
794
+ className: "text-sm text-muted-foreground",
795
+ children: /* @__PURE__ */ W(a, { id: "The accounts this merchant takes payments through, one or more per rail." })
796
+ })]
797
+ }), o && /* @__PURE__ */ W(ke, { railDefinitions: s }, e() ?? "")]
798
+ }), n.data?.data?.length ? /* @__PURE__ */ G(ne, {
799
+ className: "min-w-[44rem]",
800
+ children: [/* @__PURE__ */ W(te, { children: /* @__PURE__ */ G(E, {
801
+ className: "hover:bg-transparent",
802
+ children: [
803
+ /* @__PURE__ */ W(w, {
804
+ className: "text-muted-foreground",
805
+ children: "PSP"
806
+ }),
807
+ /* @__PURE__ */ W(w, {
808
+ className: "text-muted-foreground",
809
+ children: /* @__PURE__ */ W(a, { id: "Environment" })
810
+ }),
811
+ /* @__PURE__ */ W(w, {
812
+ className: "text-muted-foreground",
813
+ children: /* @__PURE__ */ W(a, { id: "Credentials" })
814
+ }),
815
+ /* @__PURE__ */ W(w, {
816
+ className: "text-muted-foreground",
817
+ children: /* @__PURE__ */ W(a, { id: "State" })
818
+ }),
819
+ o && /* @__PURE__ */ W(w, {
820
+ className: "text-right text-muted-foreground",
821
+ children: /* @__PURE__ */ W(a, { id: "Action" })
822
+ })
823
+ ]
824
+ }) }), /* @__PURE__ */ W(ee, { children: n.data.data.map((e) => /* @__PURE__ */ W(Se, {
825
+ psp: e,
826
+ railDefinitions: s,
827
+ edits: o
828
+ }, e.id)) })]
829
+ }) : /* @__PURE__ */ W("p", {
830
+ className: "py-2 text-sm text-muted-foreground",
831
+ children: /* @__PURE__ */ W(a, { id: "No PSPs configured." })
832
+ })]
833
+ })]
834
+ });
835
+ }
836
+ function xe(e) {
837
+ return e.validated_at ? `Validated ${m(e.validated_at)}` : e.configured ? "Configured" : "Not configured";
838
+ }
839
+ function Se({ psp: n, railDefinitions: r, edits: s }) {
840
+ let { toast: c, toastApiError: l, toastStaleEdit: u, adminMutations: d, selectedMerchant: f } = i(), { text: p } = e(), m = U(), h = V(d.updatePSP(m)), [g, v] = B.useState(!1), y = _(), b = r.find((e) => e.rail === n.rail), x = b?.display_name ?? n.rail, S = n.credentials ?? {}, C = async (e) => {
841
+ if (!(!e && !await y({
842
+ title: `Archive ${n.key}?`,
843
+ description: "New checkout stops routing to it. Existing subscriptions, refunds and webhooks keep using it.",
844
+ confirmLabel: "Archive PSP"
845
+ }))) try {
846
+ await h.mutateAsync({
847
+ id: n.id,
848
+ psp: {
849
+ archived: !0,
850
+ expected_revision: n.revision,
851
+ ...e ? { allow_last: !0 } : {}
852
+ }
853
+ }), c.success("PSP archived");
854
+ } catch (r) {
855
+ if (r instanceof t && r.code === "psp_last_active") {
856
+ e ? l(r, "Archive PSP") : v(!0);
857
+ return;
858
+ }
859
+ if (r instanceof t && r.revisionMismatch) {
860
+ u(`PSP ${n.key}`);
861
+ return;
862
+ }
863
+ l(r, "Archive PSP");
864
+ }
865
+ };
866
+ return /* @__PURE__ */ G(E, {
867
+ className: n.archived ? "opacity-60" : void 0,
868
+ children: [
869
+ /* @__PURE__ */ W(T, {
870
+ className: "py-3",
871
+ children: /* @__PURE__ */ G("div", {
872
+ className: "grid min-w-0 leading-tight",
873
+ children: [/* @__PURE__ */ W("span", {
874
+ className: "font-medium",
875
+ children: n.key
876
+ }), /* @__PURE__ */ G("span", {
877
+ className: "truncate text-xs text-muted-foreground",
878
+ children: [
879
+ x,
880
+ " · ",
881
+ n.account_id
882
+ ]
883
+ })]
884
+ })
885
+ }),
886
+ /* @__PURE__ */ W(T, {
887
+ className: "py-3 capitalize",
888
+ children: n.environment
889
+ }),
890
+ /* @__PURE__ */ W(T, {
891
+ className: "py-3",
892
+ children: Object.keys(S).length > 0 ? /* @__PURE__ */ W("span", {
893
+ className: "flex flex-wrap gap-1",
894
+ children: Object.entries(S).map(([e, t]) => /* @__PURE__ */ W(D, {
895
+ variant: "secondary",
896
+ className: t.configured ? "" : "bg-held-surface text-held",
897
+ title: xe(t),
898
+ children: e
899
+ }, e))
900
+ }) : /* @__PURE__ */ W("span", {
901
+ className: "text-sm text-muted-foreground",
902
+ children: /* @__PURE__ */ W(a, { id: "None required" })
903
+ })
904
+ }),
905
+ /* @__PURE__ */ W(T, {
906
+ className: "py-3",
907
+ children: n.archived && n.open_obligations === 0 ? /* @__PURE__ */ W(D, {
908
+ variant: "secondary",
909
+ children: /* @__PURE__ */ W(a, { id: "archived" })
910
+ }) : n.archived ? /* @__PURE__ */ G(D, {
911
+ variant: "secondary",
912
+ className: "bg-held-surface text-held",
913
+ children: [
914
+ /* @__PURE__ */ W(a, { id: "draining (" }),
915
+ n.open_obligations,
916
+ ")"
917
+ ]
918
+ }) : /* @__PURE__ */ W(D, {
919
+ variant: "secondary",
920
+ className: "bg-settled-surface text-settled",
921
+ children: /* @__PURE__ */ W(a, { id: "active" })
922
+ })
923
+ }),
924
+ s && /* @__PURE__ */ W(T, {
925
+ className: "py-3 text-right",
926
+ children: !n.archived && /* @__PURE__ */ G("div", {
927
+ className: "flex justify-end gap-2",
928
+ children: [
929
+ /* @__PURE__ */ W(Ce, {
930
+ psp: n,
931
+ credentialKeys: b?.credential_keys ?? Object.keys(S)
932
+ }, `${f() ?? ""}:${n.id}`),
933
+ /* @__PURE__ */ W(o, {
934
+ variant: "outline",
935
+ size: "sm",
936
+ disabled: h.isPending,
937
+ onClick: () => C(!1),
938
+ children: /* @__PURE__ */ W(a, { id: "Archive" })
939
+ }),
940
+ /* @__PURE__ */ W(z, {
941
+ open: g,
942
+ onOpenChange: v,
943
+ title: `Archive the last active ${x} PSP?`,
944
+ description: p("New checkout on this rail is refused until another PSP is armed. Existing subscriptions, refunds and webhooks keep using this one."),
945
+ confirmationWord: "ARCHIVE",
946
+ actionLabel: "Archive PSP",
947
+ onConfirm: () => C(!0)
948
+ })
949
+ ]
950
+ })
951
+ })
952
+ ]
953
+ });
954
+ }
955
+ function Ce({ psp: n, credentialKeys: r }) {
956
+ let { toast: c, toastApiError: l, toastStaleEdit: u, adminMutations: d, selectedMerchant: f } = i(), { id: p } = e(), [h, g] = B.useState(!1), [_] = B.useState(() => f() ?? ""), v = B.useRef(n.revision), y = U(), b = V(d.updatePSP(y)), x = n.credentials ?? {}, S = K({
957
+ defaultValues: { credentials: {} },
958
+ onSubmit: async ({ value: e }) => {
959
+ let r = Object.fromEntries(Object.entries(e.credentials).filter(([, e]) => e.trim()));
960
+ try {
961
+ if ((f() ?? "") !== _) throw Error("Merchant changed; reopen this form");
962
+ await b.mutateAsync({
963
+ id: n.id,
964
+ psp: {
965
+ expected_revision: v.current,
966
+ credentials: r
967
+ }
968
+ }), c.success(`${n.key} credentials validated and rotated`), C(!1);
969
+ } catch (e) {
970
+ if (e instanceof t && e.revisionMismatch) {
971
+ u(`PSP ${n.key}`), C(!1);
972
+ return;
973
+ }
974
+ l(e, "Rotate credentials");
975
+ } finally {
976
+ b.reset();
977
+ }
978
+ }
979
+ }), C = (e) => {
980
+ e || S.reset(), e && (v.current = n.revision), g(e);
981
+ };
982
+ return /* @__PURE__ */ G(P, {
983
+ open: h,
984
+ onOpenChange: C,
985
+ children: [/* @__PURE__ */ W(N, { render: /* @__PURE__ */ W(o, {
986
+ variant: "outline",
987
+ size: "sm",
988
+ children: /* @__PURE__ */ W(a, { id: "Rotate" })
989
+ }) }), /* @__PURE__ */ G(A, {
990
+ className: I,
991
+ children: [/* @__PURE__ */ G(O, { children: [/* @__PURE__ */ G(j, { children: [
992
+ /* @__PURE__ */ W(a, { id: "Rotate " }),
993
+ n.key,
994
+ /* @__PURE__ */ W(a, { id: " credentials · " }),
995
+ n.account_id
996
+ ] }), /* @__PURE__ */ W(M, { children: /* @__PURE__ */ W(a, { id: "Current credentials are never shown. A new one is validated against the live provider before it is stored; if that check fails, nothing is written. Leave a field blank to keep the credential it holds now." }) })] }), /* @__PURE__ */ G("form", {
997
+ onSubmit: (e) => {
998
+ e.preventDefault(), e.stopPropagation(), S.handleSubmit();
999
+ },
1000
+ className: "grid gap-4",
1001
+ children: [/* @__PURE__ */ W(S.Field, {
1002
+ name: "credentials",
1003
+ children: (e) => /* @__PURE__ */ G("div", {
1004
+ className: "grid gap-3",
1005
+ children: [r.map((t) => {
1006
+ let r = x[t];
1007
+ return /* @__PURE__ */ G($, {
1008
+ label: t,
1009
+ id: `rot-${n.id}-${t}`,
1010
+ children: [/* @__PURE__ */ W(s, {
1011
+ id: p(`rot-${n.id}-${t}`),
1012
+ type: "password",
1013
+ autoComplete: "new-password",
1014
+ placeholder: r?.configured ? "unchanged" : "not configured",
1015
+ value: e.state.value[t] ?? "",
1016
+ onChange: (n) => e.handleChange({
1017
+ ...e.state.value,
1018
+ [t]: n.target.value
1019
+ })
1020
+ }), r?.validated_at && /* @__PURE__ */ G("p", {
1021
+ className: "text-xs text-muted-foreground",
1022
+ children: [/* @__PURE__ */ W(a, { id: "Last validated " }), m(r.validated_at)]
1023
+ })]
1024
+ }, t);
1025
+ }), /* @__PURE__ */ W("p", {
1026
+ className: "text-xs text-muted-foreground",
1027
+ children: /* @__PURE__ */ W(a, { id: "Once this succeeds, the new credential is used for the next charge and every one after it. Previous webhook signing secrets remain accepted while their required overlap is active." })
1028
+ })]
1029
+ })
1030
+ }), /* @__PURE__ */ W(k, { children: /* @__PURE__ */ W(S.Subscribe, {
1031
+ selector: (e) => [e.values.credentials, e.isSubmitting],
1032
+ children: ([e, t]) => /* @__PURE__ */ W(o, {
1033
+ type: "submit",
1034
+ disabled: t || !Object.values(e).some((e) => e.trim()),
1035
+ children: t ? "Validating…" : "Validate & rotate"
1036
+ })
1037
+ }) })]
1038
+ })]
1039
+ })]
1040
+ });
1041
+ }
1042
+ function we(e) {
1043
+ switch (e) {
1044
+ case "nmi": return "The Gateway ID shown in your NMI dashboard.";
1045
+ case "stripe": return "Your Stripe account ID. It starts with acct_.";
1046
+ case "ccbill": return "Your account and sub-account joined with a dash, such as 999999-0000.";
1047
+ case "solana": return "Taken from your signing key, so whatever you enter here is ignored.";
1048
+ default: return;
1049
+ }
1050
+ }
1051
+ var Te = {
1052
+ nmi: "NMI",
1053
+ ccbill: "CCBill",
1054
+ stripe: "Stripe",
1055
+ solana: "Solana"
1056
+ };
1057
+ function Ee(e, t) {
1058
+ let n = Te[e] ?? e;
1059
+ return !t || t.toLowerCase() === n.toLowerCase() ? n : `${t} (${n})`;
1060
+ }
1061
+ var De = {
1062
+ api: "API",
1063
+ id: "ID",
1064
+ url: "URL"
1065
+ };
1066
+ function Oe(e) {
1067
+ return e.split(/[_-]+/).filter(Boolean).map((e, t) => De[e.toLowerCase()] || (t > 0 ? e.toLowerCase() : e.charAt(0).toUpperCase() + e.slice(1).toLowerCase())).join(" ");
1068
+ }
1069
+ function ke({ railDefinitions: t }) {
1070
+ let { toast: n, toastApiError: r, adminMutations: c, selectedMerchant: l } = i(), { text: u, id: d } = e(), [f, p] = B.useState(!1), [m] = B.useState(() => l() ?? ""), h = U(), g = V(c.createPSP(h)), _ = K({
1071
+ defaultValues: {
1072
+ rail: "",
1073
+ key: "",
1074
+ accountID: "",
1075
+ credentials: {}
1076
+ },
1077
+ onSubmit: async ({ value: e }) => {
1078
+ let t = Object.fromEntries(Object.entries(e.credentials).filter(([, e]) => e !== ""));
1079
+ try {
1080
+ if ((l() ?? "") !== m) throw Error("Merchant changed; reopen this form");
1081
+ await g.mutateAsync({
1082
+ key: e.key.trim().toLowerCase(),
1083
+ rail: e.rail,
1084
+ account_id: e.accountID.trim(),
1085
+ ...Object.keys(t).length ? { credentials: t } : {}
1086
+ }), _.reset(), n.success("PSP added"), p(!1);
1087
+ } catch (e) {
1088
+ r(e, "Add PSP");
1089
+ } finally {
1090
+ g.reset();
1091
+ }
1092
+ }
1093
+ }), w = (e) => {
1094
+ e || _.reset(), p(e);
1095
+ };
1096
+ return /* @__PURE__ */ G(P, {
1097
+ open: f,
1098
+ onOpenChange: w,
1099
+ children: [/* @__PURE__ */ W(N, { render: /* @__PURE__ */ W(o, {
1100
+ size: "sm",
1101
+ children: /* @__PURE__ */ W(a, { id: "Add PSP" })
1102
+ }) }), /* @__PURE__ */ G(A, {
1103
+ className: I,
1104
+ children: [/* @__PURE__ */ G(O, { children: [/* @__PURE__ */ W(j, { children: /* @__PURE__ */ W(a, { id: "Add a PSP" }) }), /* @__PURE__ */ W(M, { children: /* @__PURE__ */ W(a, { id: "Connect the account that will take money for you. Credentials go straight into the secret store and are never shown again." }) })] }), /* @__PURE__ */ G("form", {
1105
+ onSubmit: (e) => {
1106
+ e.preventDefault(), e.stopPropagation(), _.handleSubmit();
1107
+ },
1108
+ className: "grid gap-4",
1109
+ children: [/* @__PURE__ */ G("div", {
1110
+ className: "grid gap-3",
1111
+ children: [
1112
+ /* @__PURE__ */ W(_.Field, {
1113
+ name: "rail",
1114
+ validators: { onChange: ({ value: e }) => e ? void 0 : "Choose a payment rail" },
1115
+ children: (e) => /* @__PURE__ */ G($, {
1116
+ label: u("Payment rail"),
1117
+ id: "pv-rail",
1118
+ children: [/* @__PURE__ */ G(C, {
1119
+ items: t.map((e) => ({
1120
+ value: e.rail,
1121
+ label: Ee(e.rail, e.display_name)
1122
+ })),
1123
+ value: e.state.value || null,
1124
+ onValueChange: (t) => {
1125
+ e.handleChange(t ?? ""), _.setFieldValue("credentials", {});
1126
+ },
1127
+ children: [/* @__PURE__ */ W(b, {
1128
+ id: d("pv-rail"),
1129
+ className: "w-full",
1130
+ "aria-invalid": e.state.meta.errors.length > 0,
1131
+ children: /* @__PURE__ */ W(y, { placeholder: u("Pick a rail…") })
1132
+ }), /* @__PURE__ */ W(x, { children: t.map((e) => /* @__PURE__ */ W(S, {
1133
+ value: e.rail,
1134
+ children: Ee(e.rail, e.display_name)
1135
+ }, e.rail)) })]
1136
+ }), /* @__PURE__ */ W(v, { errors: e.state.meta.errors })]
1137
+ })
1138
+ }),
1139
+ /* @__PURE__ */ W(_.Field, {
1140
+ name: "key",
1141
+ validators: { onChange: ({ value: e }) => /^[a-z0-9][a-z0-9_-]{0,62}$/.test(e.trim().toLowerCase()) ? void 0 : "Lowercase letters, digits, - or _" },
1142
+ children: (e) => /* @__PURE__ */ G($, {
1143
+ label: u("Key"),
1144
+ id: "pv-key",
1145
+ hint: "Your name for this PSP, such as mobius. Prices and checkout name it by this key.",
1146
+ children: [/* @__PURE__ */ W(s, {
1147
+ id: d("pv-key"),
1148
+ value: e.state.value,
1149
+ onBlur: e.handleBlur,
1150
+ onChange: (t) => e.handleChange(t.target.value),
1151
+ "aria-invalid": e.state.meta.errors.length > 0
1152
+ }), /* @__PURE__ */ W(v, { errors: e.state.meta.errors })]
1153
+ })
1154
+ }),
1155
+ /* @__PURE__ */ W(_.Subscribe, {
1156
+ selector: (e) => e.values.rail,
1157
+ children: (e) => /* @__PURE__ */ W(_.Field, {
1158
+ name: "accountID",
1159
+ validators: { onChange: ({ value: e }) => e.trim() ? void 0 : "Enter the provider account ID" },
1160
+ children: (t) => /* @__PURE__ */ G($, {
1161
+ label: u("Account ID"),
1162
+ id: "pv-acct",
1163
+ hint: we(e),
1164
+ children: [/* @__PURE__ */ W(s, {
1165
+ id: d("pv-acct"),
1166
+ value: t.state.value,
1167
+ onBlur: t.handleBlur,
1168
+ onChange: (e) => t.handleChange(e.target.value),
1169
+ "aria-invalid": t.state.meta.errors.length > 0
1170
+ }), /* @__PURE__ */ W(v, { errors: t.state.meta.errors })]
1171
+ })
1172
+ })
1173
+ }),
1174
+ /* @__PURE__ */ W(_.Subscribe, {
1175
+ selector: (e) => e.values.rail,
1176
+ children: (e) => {
1177
+ let n = t.find((t) => t.rail === e);
1178
+ return /* @__PURE__ */ W(_.Field, {
1179
+ name: "credentials",
1180
+ children: (e) => /* @__PURE__ */ W(oe, { children: n?.credential_keys.map((t) => /* @__PURE__ */ W($, {
1181
+ label: Oe(t),
1182
+ id: `pv-credential-${t}`,
1183
+ children: /* @__PURE__ */ W(s, {
1184
+ id: d(`pv-credential-${t}`),
1185
+ type: "password",
1186
+ autoComplete: "new-password",
1187
+ value: e.state.value[t] ?? "",
1188
+ onChange: (n) => e.handleChange({
1189
+ ...e.state.value,
1190
+ [t]: n.target.value
1191
+ })
1192
+ })
1193
+ }, t)) })
1194
+ });
1195
+ }
1196
+ })
1197
+ ]
1198
+ }), /* @__PURE__ */ W(k, { children: /* @__PURE__ */ W(_.Subscribe, {
1199
+ selector: (e) => [
1200
+ e.values.rail,
1201
+ e.values.key,
1202
+ e.values.accountID,
1203
+ e.canSubmit,
1204
+ e.isSubmitting
1205
+ ],
1206
+ children: ([e, t, n, r, i]) => /* @__PURE__ */ G(oe, { children: [/* @__PURE__ */ W(o, {
1207
+ type: "button",
1208
+ variant: "outline",
1209
+ onClick: () => w(!1),
1210
+ children: /* @__PURE__ */ W(a, { id: "Cancel" })
1211
+ }), /* @__PURE__ */ W(o, {
1212
+ type: "submit",
1213
+ disabled: !e || !t.trim() || !n.trim() || !r || i,
1214
+ children: i ? "Saving…" : "Add PSP"
1215
+ })] })
1216
+ }) })]
1217
+ })]
1218
+ })]
1219
+ });
1220
+ }
1221
+ function Ae() {
1222
+ let { toast: t, toastApiError: n, adminMutations: r } = i(), { text: l, id: u } = e(), [d, f] = B.useState(), m = V(r.lookupCustomerControls()), _ = V(r.setCreditLimit()), y = c(), b = K({
1223
+ defaultValues: { newLimit: "" },
1224
+ onSubmit: async ({ value: e }) => {
1225
+ if (!d) return;
1226
+ let r = p(d.currency), i = r === void 0 ? null : g(e.newLimit, r);
1227
+ if (!(i === null || i.startsWith("-"))) try {
1228
+ await _.mutateAsync({
1229
+ customerId: d.customerID,
1230
+ currency: d.currency,
1231
+ amount: i
1232
+ }), f((e) => e && {
1233
+ ...e,
1234
+ creditLimit: i
1235
+ }), b.reset(), t.success("Credit limit updated");
1236
+ } catch (e) {
1237
+ n(e, "Set credit limit");
1238
+ }
1239
+ }
1240
+ }), x = K({
1241
+ defaultValues: {
1242
+ customerID: "",
1243
+ currency: "usd"
1244
+ },
1245
+ onSubmit: async ({ value: e }) => {
1246
+ let t = e.customerID.trim(), r = e.currency.trim().toLowerCase();
1247
+ try {
1248
+ let e = await m.mutateAsync({
1249
+ customerId: t,
1250
+ currency: r
1251
+ });
1252
+ f({
1253
+ customerID: t,
1254
+ ...e
1255
+ }), b.reset();
1256
+ } catch (e) {
1257
+ n(e, "Lookup customer controls"), f(void 0);
1258
+ }
1259
+ }
1260
+ });
1261
+ return /* @__PURE__ */ G("div", {
1262
+ className: "grid gap-10",
1263
+ children: [/* @__PURE__ */ G("section", {
1264
+ className: "grid gap-5",
1265
+ children: [/* @__PURE__ */ G("div", {
1266
+ className: "grid gap-1",
1267
+ children: [/* @__PURE__ */ W("h2", {
1268
+ className: "text-base font-semibold",
1269
+ children: /* @__PURE__ */ W(a, { id: "Customer lookup" })
1270
+ }), /* @__PURE__ */ W("p", {
1271
+ className: "text-sm text-muted-foreground",
1272
+ children: /* @__PURE__ */ W(a, { id: "Find a customer by ID and currency." })
1273
+ })]
1274
+ }), /* @__PURE__ */ G("form", {
1275
+ onSubmit: (e) => {
1276
+ e.preventDefault(), e.stopPropagation(), x.handleSubmit();
1277
+ },
1278
+ className: "grid gap-4 md:grid-cols-[minmax(0,1fr)_10rem_auto] md:items-end",
1279
+ children: [
1280
+ /* @__PURE__ */ W(x.Field, {
1281
+ name: "customerID",
1282
+ validators: { onChange: ({ value: e }) => e.trim() ? void 0 : "Enter a customer ID" },
1283
+ children: (e) => /* @__PURE__ */ G($, {
1284
+ label: l("Customer ID"),
1285
+ id: "customer-controls-id",
1286
+ children: [/* @__PURE__ */ W(s, {
1287
+ id: u("customer-controls-id"),
1288
+ placeholder: l("Customer UUID"),
1289
+ value: e.state.value,
1290
+ onBlur: e.handleBlur,
1291
+ onChange: (t) => e.handleChange(t.target.value),
1292
+ "aria-invalid": e.state.meta.errors.length > 0
1293
+ }), /* @__PURE__ */ W(v, { errors: e.state.meta.errors })]
1294
+ })
1295
+ }),
1296
+ /* @__PURE__ */ W(x.Field, {
1297
+ name: "currency",
1298
+ validators: { onChange: ({ value: e }) => e.trim() ? void 0 : "Enter a currency" },
1299
+ children: (e) => /* @__PURE__ */ G($, {
1300
+ label: l("Currency"),
1301
+ id: "customer-controls-currency",
1302
+ children: [/* @__PURE__ */ W(s, {
1303
+ id: u("customer-controls-currency"),
1304
+ placeholder: l("USD"),
1305
+ value: e.state.value,
1306
+ onBlur: e.handleBlur,
1307
+ onChange: (t) => e.handleChange(t.target.value),
1308
+ "aria-invalid": e.state.meta.errors.length > 0
1309
+ }), /* @__PURE__ */ W(v, { errors: e.state.meta.errors })]
1310
+ })
1311
+ }),
1312
+ /* @__PURE__ */ W(x.Subscribe, {
1313
+ selector: (e) => [
1314
+ e.values.customerID,
1315
+ e.values.currency,
1316
+ e.canSubmit,
1317
+ e.isSubmitting
1318
+ ],
1319
+ children: ([e, t, n, r]) => /* @__PURE__ */ W(o, {
1320
+ type: "submit",
1321
+ variant: "outline",
1322
+ disabled: !e.trim() || !t.trim() || !n || r,
1323
+ children: r ? "Looking up…" : "Look up"
1324
+ })
1325
+ })
1326
+ ]
1327
+ })]
1328
+ }), d && /* @__PURE__ */ G("section", {
1329
+ className: "grid gap-5",
1330
+ children: [
1331
+ /* @__PURE__ */ G("div", {
1332
+ className: "grid gap-1",
1333
+ children: [/* @__PURE__ */ W("h2", {
1334
+ className: "text-base font-semibold",
1335
+ children: /* @__PURE__ */ W(a, { id: "Credit and trust" })
1336
+ }), /* @__PURE__ */ G("p", {
1337
+ className: "text-sm text-muted-foreground",
1338
+ children: [
1339
+ /* @__PURE__ */ W("span", {
1340
+ className: "font-mono text-xs break-all text-foreground",
1341
+ children: d.customerID
1342
+ }),
1343
+ " ",
1344
+ "· ",
1345
+ d.currency.toUpperCase()
1346
+ ]
1347
+ })]
1348
+ }),
1349
+ /* @__PURE__ */ G("dl", {
1350
+ className: "grid gap-4",
1351
+ children: [/* @__PURE__ */ W(X, {
1352
+ label: l("Trust level"),
1353
+ value: d.trustLevel || "Default"
1354
+ }), /* @__PURE__ */ W(X, {
1355
+ label: l("Credit limit"),
1356
+ value: d.creditLimit === "0" ? "Off" : h(d.creditLimit, d.currency)
1357
+ })]
1358
+ }),
1359
+ y && /* @__PURE__ */ W("form", {
1360
+ onSubmit: (e) => {
1361
+ e.preventDefault(), e.stopPropagation(), b.handleSubmit();
1362
+ },
1363
+ children: /* @__PURE__ */ W(Z, {
1364
+ label: `New limit (${d.currency.toUpperCase()})`,
1365
+ id: "customer-controls-limit",
1366
+ children: /* @__PURE__ */ W(b.Field, {
1367
+ name: "newLimit",
1368
+ validators: { onChange: ({ value: e }) => {
1369
+ let t = p(d.currency), n = t === void 0 ? null : g(e, t);
1370
+ return e !== "" && n !== null && !n.startsWith("-") ? void 0 : "Enter a valid amount";
1371
+ } },
1372
+ children: (e) => /* @__PURE__ */ G("div", {
1373
+ className: "grid gap-1.5",
1374
+ children: [
1375
+ /* @__PURE__ */ G("div", {
1376
+ className: "flex gap-2",
1377
+ children: [/* @__PURE__ */ W(s, {
1378
+ id: u("customer-controls-limit"),
1379
+ placeholder: "0.00",
1380
+ type: "number",
1381
+ step: "any",
1382
+ min: "0",
1383
+ value: e.state.value,
1384
+ onBlur: e.handleBlur,
1385
+ onChange: (t) => e.handleChange(t.target.value),
1386
+ "aria-invalid": e.state.meta.errors.length > 0
1387
+ }), /* @__PURE__ */ W(b.Subscribe, {
1388
+ selector: (e) => [
1389
+ e.values.newLimit,
1390
+ e.canSubmit,
1391
+ e.isSubmitting
1392
+ ],
1393
+ children: ([e, t, n]) => /* @__PURE__ */ W(o, {
1394
+ type: "submit",
1395
+ disabled: !e || !t || n,
1396
+ children: n ? "Updating…" : "Update"
1397
+ })
1398
+ })]
1399
+ }),
1400
+ /* @__PURE__ */ W(v, { errors: e.state.meta.errors }),
1401
+ /* @__PURE__ */ W("p", {
1402
+ className: "text-xs text-muted-foreground",
1403
+ children: /* @__PURE__ */ W(a, { id: "Enter 0 to turn credit off." })
1404
+ })
1405
+ ]
1406
+ })
1407
+ })
1408
+ })
1409
+ })
1410
+ ]
1411
+ })]
1412
+ });
1413
+ }
1414
+ function $({ label: t, id: n, hint: r, children: i }) {
1415
+ let { id: a } = e();
1416
+ return /* @__PURE__ */ G("div", {
1417
+ className: "grid gap-1.5",
1418
+ children: [
1419
+ /* @__PURE__ */ W(F, {
1420
+ htmlFor: a(n),
1421
+ children: t
1422
+ }),
1423
+ r ? /* @__PURE__ */ W("p", {
1424
+ className: "text-[13px] text-muted-foreground",
1425
+ children: r
1426
+ }) : null,
1427
+ i
1428
+ ]
1429
+ });
1430
+ }
1431
+ //#endregion
1432
+ export { ge as SettingsPage };
1433
+
1434
+ //# sourceMappingURL=admin-settings-Bmoy95uO.js.map