@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,1312 @@
1
+ import { E as e, c as t, f as n, p as r, r as i, s as a, w as o } from "./admin-utils-BK4Vh1o_.js";
2
+ import { t as s } from "./admin-button-CTL3DgOt.js";
3
+ import { t as c } from "./admin-input-CcfQfJFN.js";
4
+ import { a as l } from "./admin-capabilities-BuigAgtm.js";
5
+ import { t as u } from "./admin-auth-DQGHtt0j.js";
6
+ import { a as d, i as f, n as p, o as m, s as h, t as g, u as _ } from "./admin-format-DoohJ7Fg.js";
7
+ import { t as v } from "./admin-form-field-errors-hbUMIriS.js";
8
+ import { a as y, i as b, n as x, r as S, t as C } from "./admin-select-DBgprVW6.js";
9
+ import { n as w, r as T } from "./admin-dom-uMmZzRvU.js";
10
+ import { a as E, n as D, o as O, r as k, s as A, t as j } from "./admin-table-CH9TrXJf.js";
11
+ import { t as M } from "./admin-linked-table-row-BsaUruCN.js";
12
+ import { t as N } from "./admin-badge-DR5-1qd8.js";
13
+ import { t as P } from "./admin-status-badge-BFPgo71d.js";
14
+ import { a as F, i as I, n as L, o as R, r as z, s as ee, t as B } from "./admin-dialog-BjuKI5Hp.js";
15
+ import { t as V } from "./admin-label-BiEN5cjb.js";
16
+ import { n as te } from "./admin-dialog-width-BPrgdYlj.js";
17
+ import { a as H, o as U, r as W, t as G } from "./admin-card-bzAks3-3.js";
18
+ import { n as ne, t as re } from "./admin-invoice-profile-model-Cgjy3zV8.js";
19
+ import { t as ie } from "./admin-dunning-B2zgtrOo.js";
20
+ import * as K from "react";
21
+ import { useState as ae } from "react";
22
+ import { useMutation as q, useQuery as J, useQueryClient as Y } from "@tanstack/react-query";
23
+ import { Fragment as oe, jsx as X, jsxs as Z } from "react/jsx-runtime";
24
+ import { HugeiconsIcon as Q } from "@hugeicons/react";
25
+ import { Add01Icon as se, ArrowLeft01Icon as ce, Delete02Icon as le } from "@hugeicons/core-free-icons";
26
+ import { useForm as ue } from "@tanstack/react-form";
27
+ //#region src/admin/pages/customers/invoice-profile.tsx
28
+ function de({ customerId: e }) {
29
+ let { orderQueries: t } = r(), n = l(), a = J(t.profile(e));
30
+ return /* @__PURE__ */ Z(G, { children: [/* @__PURE__ */ X(H, { children: /* @__PURE__ */ X(U, { children: /* @__PURE__ */ X(o, { id: "Invoice profile" }) }) }), /* @__PURE__ */ Z(W, { children: [/* @__PURE__ */ X(i, {
31
+ className: "text-sm underline",
32
+ to: `/orders?customer_id=${e}&origin=usage`,
33
+ children: /* @__PURE__ */ X(o, { id: "View customer usage orders" })
34
+ }), a.isPending ? /* @__PURE__ */ X("p", { children: /* @__PURE__ */ X(o, { id: "Loading invoice profile…" }) }) : a.error ? /* @__PURE__ */ X("p", {
35
+ role: "alert",
36
+ className: "text-destructive",
37
+ children: a.error.message
38
+ }) : /* @__PURE__ */ X(fe, {
39
+ customerId: e,
40
+ profile: a.data,
41
+ readOnly: !n
42
+ }, e)] })] });
43
+ }
44
+ function fe({ customerId: t, profile: n, readOnly: i = !1 }) {
45
+ let { id: a, text: l } = e(), { invoiceProfileMutation: u } = r(), [d, f] = ae(() => ne(n)), [p, m] = ae(null), [h, g] = ae(!1), _ = Y(), v = q(u(_, t)), y = (e) => {
46
+ f((t) => ({
47
+ ...t,
48
+ ...e
49
+ })), g(!1);
50
+ };
51
+ async function b() {
52
+ m(null), g(!1);
53
+ try {
54
+ await v.mutateAsync(re(d, n)), g(!0);
55
+ } catch (e) {
56
+ m(e instanceof Error ? e.message : "Invoice profile update failed.");
57
+ }
58
+ }
59
+ return /* @__PURE__ */ Z("form", {
60
+ className: "mt-4 space-y-4",
61
+ onSubmit: (e) => {
62
+ e.preventDefault(), v.isPending || b();
63
+ },
64
+ children: [
65
+ /* @__PURE__ */ X("p", {
66
+ className: "text-sm text-muted-foreground",
67
+ children: /* @__PURE__ */ X(o, { id: "Terms and billing facts for future usage orders. Billed orders keep their original snapshots. Tax details are recorded; no tax is calculated." })
68
+ }),
69
+ /* @__PURE__ */ Z("fieldset", {
70
+ disabled: i || v.isPending,
71
+ className: "space-y-4",
72
+ children: [
73
+ /* @__PURE__ */ Z("div", {
74
+ className: "grid gap-3 sm:grid-cols-2",
75
+ children: [/* @__PURE__ */ Z("div", { children: [/* @__PURE__ */ X(V, {
76
+ htmlFor: a("invoice-profile-terms"),
77
+ children: /* @__PURE__ */ X(o, { id: "Payment terms (days)" })
78
+ }), /* @__PURE__ */ X(c, {
79
+ id: a("invoice-profile-terms"),
80
+ type: "number",
81
+ min: 0,
82
+ step: 1,
83
+ value: d.terms,
84
+ onChange: (e) => y({ terms: e.target.value })
85
+ })] }), /* @__PURE__ */ Z("div", { children: [/* @__PURE__ */ X(V, {
86
+ htmlFor: a("invoice-profile-method"),
87
+ children: /* @__PURE__ */ X(o, { id: "Collection method" })
88
+ }), /* @__PURE__ */ Z("select", {
89
+ id: a("invoice-profile-method"),
90
+ className: "h-9 w-full rounded-md border bg-background px-2",
91
+ value: d.method,
92
+ onChange: (e) => y({ method: e.target.value }),
93
+ children: [/* @__PURE__ */ X("option", {
94
+ value: "charge_automatically",
95
+ children: /* @__PURE__ */ X(o, { id: "Saved payment method" })
96
+ }), /* @__PURE__ */ X("option", {
97
+ value: "send_invoice",
98
+ children: /* @__PURE__ */ X(o, { id: "Manual remittance" })
99
+ })]
100
+ })] })]
101
+ }),
102
+ /* @__PURE__ */ Z("div", { children: [/* @__PURE__ */ X(V, {
103
+ htmlFor: a("invoice-profile-po"),
104
+ children: /* @__PURE__ */ X(o, { id: "Purchase order" })
105
+ }), /* @__PURE__ */ X(c, {
106
+ id: a("invoice-profile-po"),
107
+ value: d.po,
108
+ onChange: (e) => y({ po: e.target.value })
109
+ })] }),
110
+ /* @__PURE__ */ Z("div", { children: [/* @__PURE__ */ X(V, {
111
+ htmlFor: a("invoice-profile-memo"),
112
+ children: /* @__PURE__ */ X(o, { id: "Invoice memo" })
113
+ }), /* @__PURE__ */ X(c, {
114
+ id: a("invoice-profile-memo"),
115
+ value: d.memo,
116
+ onChange: (e) => y({ memo: e.target.value })
117
+ })] }),
118
+ /* @__PURE__ */ Z("div", {
119
+ className: "space-y-2",
120
+ children: [
121
+ /* @__PURE__ */ X("p", {
122
+ className: "text-sm font-medium",
123
+ children: /* @__PURE__ */ X(o, { id: "Billing contacts" })
124
+ }),
125
+ d.contacts.map((e, t) => /* @__PURE__ */ Z("div", {
126
+ className: "flex gap-2",
127
+ children: [
128
+ /* @__PURE__ */ X(c, {
129
+ "aria-label": `Contact ${t + 1} name`,
130
+ placeholder: l("Name"),
131
+ value: e.name,
132
+ onChange: (e) => y({ contacts: d.contacts.map((n, r) => r === t ? {
133
+ ...n,
134
+ name: e.target.value
135
+ } : n) })
136
+ }),
137
+ /* @__PURE__ */ X(c, {
138
+ "aria-label": `Contact ${t + 1} email`,
139
+ type: "email",
140
+ placeholder: l("Email"),
141
+ value: e.email,
142
+ onChange: (e) => y({ contacts: d.contacts.map((n, r) => r === t ? {
143
+ ...n,
144
+ email: e.target.value
145
+ } : n) })
146
+ }),
147
+ /* @__PURE__ */ X(s, {
148
+ type: "button",
149
+ variant: "outline",
150
+ "aria-label": `Remove contact ${t + 1}`,
151
+ onClick: () => y({ contacts: d.contacts.filter((e, n) => n !== t) }),
152
+ children: /* @__PURE__ */ X(o, { id: "Remove" })
153
+ })
154
+ ]
155
+ }, t)),
156
+ /* @__PURE__ */ X(s, {
157
+ type: "button",
158
+ variant: "outline",
159
+ onClick: () => y({ contacts: [...d.contacts, {
160
+ name: "",
161
+ email: ""
162
+ }] }),
163
+ children: /* @__PURE__ */ X(o, { id: "Add contact" })
164
+ })
165
+ ]
166
+ }),
167
+ /* @__PURE__ */ Z("div", {
168
+ className: "space-y-2",
169
+ children: [
170
+ /* @__PURE__ */ X("p", {
171
+ className: "text-sm font-medium",
172
+ children: /* @__PURE__ */ X(o, { id: "Tax details" })
173
+ }),
174
+ d.tax.map((e, t) => /* @__PURE__ */ Z("div", {
175
+ className: "flex gap-2",
176
+ children: [
177
+ /* @__PURE__ */ X(c, {
178
+ "aria-label": `Tax detail ${t + 1} name`,
179
+ placeholder: l("Name, such as tax_id"),
180
+ value: e.key,
181
+ onChange: (e) => y({ tax: d.tax.map((n, r) => r === t ? {
182
+ ...n,
183
+ key: e.target.value
184
+ } : n) })
185
+ }),
186
+ /* @__PURE__ */ X(c, {
187
+ "aria-label": `Tax detail ${t + 1} value`,
188
+ placeholder: l("Value"),
189
+ value: e.value,
190
+ onChange: (e) => y({ tax: d.tax.map((n, r) => r === t ? {
191
+ ...n,
192
+ value: e.target.value
193
+ } : n) })
194
+ }),
195
+ /* @__PURE__ */ X(s, {
196
+ type: "button",
197
+ variant: "outline",
198
+ "aria-label": `Remove tax detail ${t + 1}`,
199
+ onClick: () => y({ tax: d.tax.filter((e, n) => n !== t) }),
200
+ children: /* @__PURE__ */ X(o, { id: "Remove" })
201
+ })
202
+ ]
203
+ }, t)),
204
+ /* @__PURE__ */ X(s, {
205
+ type: "button",
206
+ variant: "outline",
207
+ onClick: () => y({ tax: [...d.tax, {
208
+ key: "",
209
+ value: ""
210
+ }] }),
211
+ children: /* @__PURE__ */ X(o, { id: "Add tax detail" })
212
+ })
213
+ ]
214
+ })
215
+ ]
216
+ }),
217
+ p && /* @__PURE__ */ X("p", {
218
+ role: "alert",
219
+ className: "text-destructive",
220
+ children: p
221
+ }),
222
+ h && /* @__PURE__ */ X("p", {
223
+ role: "status",
224
+ className: "text-sm",
225
+ children: /* @__PURE__ */ X(o, { id: "Invoice profile saved. Billed orders were not changed." })
226
+ }),
227
+ !i && /* @__PURE__ */ X(s, {
228
+ type: "submit",
229
+ disabled: v.isPending,
230
+ children: v.isPending ? "Saving…" : "Save invoice profile"
231
+ })
232
+ ]
233
+ });
234
+ }
235
+ //#endregion
236
+ //#region src/admin/pages/customers/default-card-badges.tsx
237
+ function pe({ currencies: e = [] }) {
238
+ return /* @__PURE__ */ X(oe, { children: e.map((e) => /* @__PURE__ */ Z(N, {
239
+ variant: "secondary",
240
+ className: "mt-1 mr-1",
241
+ children: [/* @__PURE__ */ X(o, { id: "Default · " }), e]
242
+ }, e)) });
243
+ }
244
+ //#endregion
245
+ //#region src/admin/pages/customers/credit-form.ts
246
+ function me(e, t = Date.now()) {
247
+ let n = g(e.amount, e.decimals);
248
+ if (n === null || BigInt(n) <= 0n) throw Error(`Enter a positive amount with at most ${e.decimals} decimal places, within the supported range.`);
249
+ let r = e.currency.trim();
250
+ if (!r) throw Error("Select a currency.");
251
+ let i;
252
+ if (e.expires) {
253
+ let n = new Date(e.expires).getTime();
254
+ if (!Number.isFinite(n) || n <= t) throw Error("Expiry must be a valid future date.");
255
+ i = new Date(n).toISOString();
256
+ }
257
+ return {
258
+ amount: n,
259
+ currency: r,
260
+ source: "admin",
261
+ source_id: e.sourceID,
262
+ expires_at: i,
263
+ description: e.description.trim() || void 0
264
+ };
265
+ }
266
+ function he(e) {
267
+ return (e.state === "active" || e.state === "scheduled") && /^\d+$/.test(e.remaining_amount) && BigInt(e.remaining_amount) > 0n;
268
+ }
269
+ function ge(e, t) {
270
+ if (!he(e)) throw Error("This grant has no remaining credit to revoke.");
271
+ if (t = t.trim(), !t || t.length > 500) throw Error("Enter a reason of up to 500 characters.");
272
+ return {
273
+ grant: e.id,
274
+ reason: t
275
+ };
276
+ }
277
+ //#endregion
278
+ //#region src/admin/pages/customers/credits.tsx
279
+ var $ = (e) => e instanceof Error ? e.message : "The request failed. Try again.";
280
+ function _e({ customerId: e, currencies: t }) {
281
+ let { activeMerchant: n } = u(), r = n?.slug ?? "";
282
+ return /* @__PURE__ */ X(ve, {
283
+ merchant: r,
284
+ customer: e,
285
+ initialCurrency: t[0] ?? "USD"
286
+ }, `${r}:${e}`);
287
+ }
288
+ function ve({ merchant: t, customer: n, initialCurrency: i }) {
289
+ let { id: a, text: u } = e(), { creditQueries: d } = r(), f = l(), [g, v] = K.useState(i), [y, b] = K.useState(i), x = T(g, 25), S = T(g, 25), [C, M] = K.useState(!1), [N, P] = K.useState(null), F = J(d.grants(t, n, g, x.size, x.cursor)), I = J(d.transactions(t, n, g, S.size, S.cursor)), L = p(g);
290
+ return /* @__PURE__ */ Z(G, { children: [
291
+ /* @__PURE__ */ Z(H, {
292
+ className: "gap-3",
293
+ children: [
294
+ /* @__PURE__ */ Z("div", {
295
+ className: "flex items-center justify-between gap-3",
296
+ children: [/* @__PURE__ */ X(U, {
297
+ className: "text-sm",
298
+ children: /* @__PURE__ */ X(o, { id: "Credits" })
299
+ }), f && /* @__PURE__ */ X(s, {
300
+ size: "sm",
301
+ disabled: L === void 0,
302
+ onClick: () => M(!0),
303
+ children: /* @__PURE__ */ X(o, { id: "Grant credit" })
304
+ })]
305
+ }),
306
+ /* @__PURE__ */ Z("form", {
307
+ className: "flex max-w-sm items-end gap-2",
308
+ onSubmit: (e) => {
309
+ e.preventDefault();
310
+ let t = y.trim();
311
+ t && v(t.toUpperCase());
312
+ },
313
+ children: [/* @__PURE__ */ Z("div", {
314
+ className: "grid gap-1",
315
+ children: [/* @__PURE__ */ X(V, {
316
+ htmlFor: a("credit-currency"),
317
+ children: /* @__PURE__ */ X(o, { id: "Currency" })
318
+ }), /* @__PURE__ */ X(c, {
319
+ id: a("credit-currency"),
320
+ value: y,
321
+ onChange: (e) => b(e.target.value),
322
+ placeholder: u("USD")
323
+ })]
324
+ }), /* @__PURE__ */ X(s, {
325
+ type: "submit",
326
+ variant: "outline",
327
+ size: "sm",
328
+ children: /* @__PURE__ */ X(o, { id: "View" })
329
+ })]
330
+ }),
331
+ L === void 0 && /* @__PURE__ */ Z("p", {
332
+ className: "text-xs text-muted-foreground",
333
+ children: [g, /* @__PURE__ */ X(o, { id: " is not a supported currency." })]
334
+ })
335
+ ]
336
+ }),
337
+ /* @__PURE__ */ Z(W, {
338
+ className: "grid gap-6",
339
+ children: [/* @__PURE__ */ Z("section", {
340
+ "aria-label": u("Credit grants"),
341
+ children: [
342
+ /* @__PURE__ */ Z("h3", {
343
+ className: "mb-2 text-sm font-medium",
344
+ children: [/* @__PURE__ */ X(o, { id: "Grants · " }), g]
345
+ }),
346
+ F.isPending ? /* @__PURE__ */ X("p", {
347
+ className: "text-sm text-muted-foreground",
348
+ children: /* @__PURE__ */ X(o, { id: "Loading grants…" })
349
+ }) : F.error ? /* @__PURE__ */ X("p", {
350
+ role: "alert",
351
+ className: "text-sm text-destructive",
352
+ children: $(F.error)
353
+ }) : F.data?.data.length ? /* @__PURE__ */ X("div", {
354
+ className: "overflow-x-auto",
355
+ children: /* @__PURE__ */ Z(j, { children: [/* @__PURE__ */ X(O, { children: /* @__PURE__ */ Z(A, { children: [
356
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Grant" }) }),
357
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Original" }) }),
358
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Remaining" }) }),
359
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Spent" }) }),
360
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Expired" }) }),
361
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Revoked" }) }),
362
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "State" }) }),
363
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Expires" }) }),
364
+ /* @__PURE__ */ X(E, {})
365
+ ] }) }), /* @__PURE__ */ X(D, { children: F.data.data.map((e) => /* @__PURE__ */ Z(A, { children: [
366
+ /* @__PURE__ */ Z(k, { children: [
367
+ /* @__PURE__ */ X("span", {
368
+ title: e.id,
369
+ children: _(e.id)
370
+ }),
371
+ /* @__PURE__ */ X("div", {
372
+ className: "text-xs text-muted-foreground",
373
+ children: m(e.created_at)
374
+ }),
375
+ /* @__PURE__ */ X("div", {
376
+ className: "text-xs text-muted-foreground",
377
+ children: e.description ?? e.source_type
378
+ })
379
+ ] }),
380
+ [
381
+ e.amount,
382
+ e.remaining_amount,
383
+ e.spent_amount,
384
+ e.expired_amount,
385
+ e.revoked_amount
386
+ ].map((t, n) => /* @__PURE__ */ X(k, {
387
+ className: "tabular-nums",
388
+ children: h(t, e.currency)
389
+ }, n)),
390
+ /* @__PURE__ */ X(k, { children: e.state }),
391
+ /* @__PURE__ */ X(k, { children: e.expires_at ? m(e.expires_at) : "No expiry" }),
392
+ /* @__PURE__ */ X(k, { children: f && /* @__PURE__ */ X(s, {
393
+ size: "sm",
394
+ variant: "outline",
395
+ disabled: !he(e),
396
+ onClick: () => P(e),
397
+ children: /* @__PURE__ */ X(o, { id: "Revoke" })
398
+ }) })
399
+ ] }, e.id)) })] })
400
+ }) : /* @__PURE__ */ X("p", {
401
+ className: "text-sm text-muted-foreground",
402
+ children: /* @__PURE__ */ X(o, { id: "No credit grants in this currency." })
403
+ }),
404
+ /* @__PURE__ */ X(w, {
405
+ pages: x,
406
+ rows: F.data?.data?.length ?? 0,
407
+ nextCursor: F.data?.next_cursor,
408
+ busy: F.isFetching
409
+ })
410
+ ]
411
+ }), /* @__PURE__ */ Z("section", {
412
+ "aria-label": u("Credit transaction ledger"),
413
+ children: [
414
+ /* @__PURE__ */ Z("h3", {
415
+ className: "mb-2 text-sm font-medium",
416
+ children: [/* @__PURE__ */ X(o, { id: "Transaction ledger · " }), g]
417
+ }),
418
+ I.isPending ? /* @__PURE__ */ X("p", {
419
+ className: "text-sm text-muted-foreground",
420
+ children: /* @__PURE__ */ X(o, { id: "Loading transactions…" })
421
+ }) : I.error ? /* @__PURE__ */ X("p", {
422
+ role: "alert",
423
+ className: "text-sm text-destructive",
424
+ children: $(I.error)
425
+ }) : I.data?.data.length ? /* @__PURE__ */ Z(j, { children: [/* @__PURE__ */ X(O, { children: /* @__PURE__ */ Z(A, { children: [
426
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Date" }) }),
427
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Type" }) }),
428
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Amount" }) }),
429
+ /* @__PURE__ */ X(E, { children: /* @__PURE__ */ X(o, { id: "Source" }) })
430
+ ] }) }), /* @__PURE__ */ X(D, { children: I.data.data.map((e) => /* @__PURE__ */ Z(A, { children: [
431
+ /* @__PURE__ */ X(k, {
432
+ title: e.id,
433
+ children: m(e.created_at)
434
+ }),
435
+ /* @__PURE__ */ X(k, { children: e.type.replaceAll("_", " ") }),
436
+ /* @__PURE__ */ X(k, {
437
+ className: "tabular-nums",
438
+ children: h(e.amount, e.currency)
439
+ }),
440
+ /* @__PURE__ */ X(k, { children: e.source || "—" })
441
+ ] }, e.id)) })] }) : /* @__PURE__ */ X("p", {
442
+ className: "text-sm text-muted-foreground",
443
+ children: /* @__PURE__ */ X(o, { id: "No transactions in this currency." })
444
+ }),
445
+ /* @__PURE__ */ X(w, {
446
+ pages: S,
447
+ rows: I.data?.data?.length ?? 0,
448
+ nextCursor: I.data?.next_cursor,
449
+ busy: I.isFetching
450
+ })
451
+ ]
452
+ })]
453
+ }),
454
+ C && L !== void 0 && /* @__PURE__ */ X(ye, {
455
+ merchant: t,
456
+ customer: n,
457
+ currency: g,
458
+ decimals: L,
459
+ onClose: () => M(!1)
460
+ }),
461
+ N && /* @__PURE__ */ X(be, {
462
+ merchant: t,
463
+ customer: n,
464
+ grant: N,
465
+ onClose: () => P(null)
466
+ })
467
+ ] });
468
+ }
469
+ function ye({ merchant: t, customer: n, currency: i, decimals: a, onClose: l }) {
470
+ let { toast: u, creditMutations: d } = r(), { id: f } = e(), p = Y(), m = q(d.grant(p, t, n)), [h, g] = K.useState(""), [_, v] = K.useState(""), [y, b] = K.useState(""), [x] = K.useState(() => crypto.randomUUID()), [S, C] = K.useState("");
471
+ return /* @__PURE__ */ X(B, {
472
+ open: !0,
473
+ onOpenChange: (e) => {
474
+ !e && !m.isPending && l();
475
+ },
476
+ children: /* @__PURE__ */ Z(L, { children: [/* @__PURE__ */ Z(F, { children: [/* @__PURE__ */ X(R, { children: /* @__PURE__ */ X(o, { id: "Grant credit" }) }), /* @__PURE__ */ Z(z, { children: [
477
+ /* @__PURE__ */ X(o, { id: "Add credit in " }),
478
+ i,
479
+ /* @__PURE__ */ X(o, { id: " to this customer." })
480
+ ] })] }), /* @__PURE__ */ Z("form", {
481
+ className: "grid gap-4",
482
+ onSubmit: async (e) => {
483
+ e.preventDefault(), C("");
484
+ try {
485
+ let e = me({
486
+ amount: h,
487
+ currency: i,
488
+ decimals: a,
489
+ expires: _,
490
+ description: y,
491
+ sourceID: x
492
+ });
493
+ await m.mutateAsync(e), u.success("Credit granted"), l();
494
+ } catch (e) {
495
+ C($(e));
496
+ }
497
+ },
498
+ children: [
499
+ /* @__PURE__ */ Z("div", {
500
+ className: "grid gap-1",
501
+ children: [/* @__PURE__ */ Z(V, {
502
+ htmlFor: f("grant-amount"),
503
+ children: [
504
+ /* @__PURE__ */ X(o, { id: "Amount (" }),
505
+ i,
506
+ ")"
507
+ ]
508
+ }), /* @__PURE__ */ X(c, {
509
+ id: f("grant-amount"),
510
+ inputMode: "decimal",
511
+ value: h,
512
+ onChange: (e) => g(e.target.value),
513
+ autoFocus: !0
514
+ })]
515
+ }),
516
+ /* @__PURE__ */ Z("div", {
517
+ className: "grid gap-1",
518
+ children: [/* @__PURE__ */ X(V, {
519
+ htmlFor: f("grant-expiry"),
520
+ children: /* @__PURE__ */ X(o, { id: "Expires (optional)" })
521
+ }), /* @__PURE__ */ X(c, {
522
+ id: f("grant-expiry"),
523
+ type: "datetime-local",
524
+ value: _,
525
+ onChange: (e) => v(e.target.value)
526
+ })]
527
+ }),
528
+ /* @__PURE__ */ Z("div", {
529
+ className: "grid gap-1",
530
+ children: [/* @__PURE__ */ X(V, {
531
+ htmlFor: f("grant-description"),
532
+ children: /* @__PURE__ */ X(o, { id: "Description (optional)" })
533
+ }), /* @__PURE__ */ X(c, {
534
+ id: f("grant-description"),
535
+ value: y,
536
+ onChange: (e) => b(e.target.value),
537
+ maxLength: 500
538
+ })]
539
+ }),
540
+ S && /* @__PURE__ */ X("p", {
541
+ role: "alert",
542
+ className: "text-sm text-destructive",
543
+ children: S
544
+ }),
545
+ /* @__PURE__ */ Z(I, { children: [/* @__PURE__ */ X(s, {
546
+ type: "button",
547
+ variant: "outline",
548
+ disabled: m.isPending,
549
+ onClick: l,
550
+ children: /* @__PURE__ */ X(o, { id: "Cancel" })
551
+ }), /* @__PURE__ */ X(s, {
552
+ type: "submit",
553
+ disabled: m.isPending,
554
+ children: m.isPending ? "Granting…" : "Grant credit"
555
+ })] })
556
+ ]
557
+ })] })
558
+ });
559
+ }
560
+ function be({ merchant: t, customer: n, grant: i, onClose: a }) {
561
+ let { toast: l, creditMutations: u } = r(), { id: d } = e(), f = Y(), p = q(u.revoke(f, t, n)), [m, g] = K.useState(""), [_, v] = K.useState("");
562
+ return /* @__PURE__ */ X(B, {
563
+ open: !0,
564
+ onOpenChange: (e) => {
565
+ !e && !p.isPending && a();
566
+ },
567
+ children: /* @__PURE__ */ Z(L, { children: [/* @__PURE__ */ Z(F, { children: [/* @__PURE__ */ X(R, { children: /* @__PURE__ */ X(o, { id: "Revoke remaining credit" }) }), /* @__PURE__ */ Z(z, { children: [
568
+ /* @__PURE__ */ X(o, { id: "Revoke the unspent remainder of" }),
569
+ " ",
570
+ h(i.remaining_amount, i.currency),
571
+ /* @__PURE__ */ X(o, { id: ". Active holds may prevent revocation. Payment refunds are managed separately." })
572
+ ] })] }), /* @__PURE__ */ Z("form", {
573
+ className: "grid gap-4",
574
+ onSubmit: async (e) => {
575
+ e.preventDefault(), v("");
576
+ try {
577
+ let e = await p.mutateAsync(ge(i, m));
578
+ l.success(e.replayed ? "Credit was already revoked" : `${h(e.revoked_amount, e.currency)} revoked`), a();
579
+ } catch (e) {
580
+ v($(e));
581
+ }
582
+ },
583
+ children: [
584
+ /* @__PURE__ */ Z("div", {
585
+ className: "grid gap-1",
586
+ children: [/* @__PURE__ */ X(V, {
587
+ htmlFor: d("revoke-reason"),
588
+ children: /* @__PURE__ */ X(o, { id: "Reason" })
589
+ }), /* @__PURE__ */ X(c, {
590
+ id: d("revoke-reason"),
591
+ value: m,
592
+ onChange: (e) => g(e.target.value),
593
+ maxLength: 500,
594
+ autoFocus: !0
595
+ })]
596
+ }),
597
+ _ && /* @__PURE__ */ X("p", {
598
+ role: "alert",
599
+ className: "text-sm text-destructive",
600
+ children: _
601
+ }),
602
+ /* @__PURE__ */ Z(I, { children: [/* @__PURE__ */ X(s, {
603
+ type: "button",
604
+ variant: "outline",
605
+ disabled: p.isPending,
606
+ onClick: a,
607
+ children: /* @__PURE__ */ X(o, { id: "Cancel" })
608
+ }), /* @__PURE__ */ X(s, {
609
+ type: "submit",
610
+ variant: "destructive",
611
+ disabled: !he(i) || p.isPending,
612
+ children: p.isPending ? "Revoking…" : "Revoke credit"
613
+ })] })
614
+ ]
615
+ })] })
616
+ });
617
+ }
618
+ //#endregion
619
+ //#region src/admin/pages/customers/grant-duration.ts
620
+ var xe = [
621
+ {
622
+ value: "1",
623
+ label: "1 day",
624
+ days: 1
625
+ },
626
+ {
627
+ value: "7",
628
+ label: "7 days",
629
+ days: 7
630
+ },
631
+ {
632
+ value: "30",
633
+ label: "30 days",
634
+ days: 30
635
+ },
636
+ {
637
+ value: "365",
638
+ label: "365 days",
639
+ days: 365
640
+ },
641
+ {
642
+ value: "until",
643
+ label: "Until a date"
644
+ },
645
+ {
646
+ value: "never",
647
+ label: "Never expires"
648
+ }
649
+ ], Se = (e) => e.toISOString().slice(0, 10);
650
+ function Ce(e, t, n = /* @__PURE__ */ new Date()) {
651
+ if (e === "never") return {};
652
+ if (e === "until") {
653
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(t) || t < Se(n)) return null;
654
+ let e = /* @__PURE__ */ new Date(`${t}T00:00:00Z`);
655
+ return e.setUTCDate(e.getUTCDate() + 1), { endsAt: e.toISOString() };
656
+ }
657
+ let r = xe.find((t) => t.value === e);
658
+ return r && "days" in r ? { hours: r.days * 24 } : null;
659
+ }
660
+ //#endregion
661
+ //#region src/admin/pages/customers/detail.tsx
662
+ function we() {
663
+ let { text: c } = e(), { props: u } = n(), { adminQueries: d } = r(), f = l(), { customerId: p = "" } = t(), g = a(), { data: _, isPending: v } = J(d.customer(p));
664
+ return v ? /* @__PURE__ */ X("p", {
665
+ className: "text-sm text-muted-foreground",
666
+ children: /* @__PURE__ */ X(o, { id: "Loading…" })
667
+ }) : _ ? /* @__PURE__ */ Z("div", {
668
+ className: "flex min-w-0 flex-col gap-4",
669
+ children: [
670
+ /* @__PURE__ */ Z("div", {
671
+ className: "flex items-center gap-3",
672
+ children: [
673
+ /* @__PURE__ */ X(s, {
674
+ variant: "ghost",
675
+ size: "icon",
676
+ onClick: () => g(-1),
677
+ "aria-label": c("Back"),
678
+ children: /* @__PURE__ */ X(Q, {
679
+ icon: ce,
680
+ className: "size-4"
681
+ })
682
+ }),
683
+ /* @__PURE__ */ Z("div", {
684
+ className: "min-w-0",
685
+ children: [/* @__PURE__ */ X("h2", {
686
+ className: "truncate text-base font-semibold",
687
+ children: _.contact?.name || _.contact?.email || "Customer"
688
+ }), /* @__PURE__ */ Z("p", {
689
+ className: "truncate text-xs text-muted-foreground",
690
+ children: [
691
+ _.id,
692
+ /* @__PURE__ */ X(o, { id: " · since " }),
693
+ m(_.created_at),
694
+ /* @__PURE__ */ X(o, { id: " · last seen" }),
695
+ " ",
696
+ m(_.last_seen_at)
697
+ ]
698
+ })]
699
+ }),
700
+ f && /* @__PURE__ */ X("div", {
701
+ className: "ml-auto flex gap-2",
702
+ children: /* @__PURE__ */ X(je, { customerId: p })
703
+ })
704
+ ]
705
+ }),
706
+ /* @__PURE__ */ X(Me, { contact: _.contact }),
707
+ u.userHref && /* @__PURE__ */ X("a", {
708
+ className: "underline",
709
+ href: u.userHref(_.id),
710
+ children: /* @__PURE__ */ X(o, { id: "View user account" })
711
+ }),
712
+ u.customerPanels?.(_),
713
+ _.balances.length > 0 && /* @__PURE__ */ X("div", {
714
+ className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-4",
715
+ children: _.balances.map((e) => /* @__PURE__ */ Z(G, { children: [/* @__PURE__ */ X(H, {
716
+ className: "pb-1",
717
+ children: /* @__PURE__ */ Z(U, {
718
+ className: "text-xs font-normal text-muted-foreground uppercase",
719
+ children: [e.currency, /* @__PURE__ */ X(o, { id: " balance" })]
720
+ })
721
+ }), /* @__PURE__ */ Z(W, { children: [/* @__PURE__ */ X("p", {
722
+ className: "text-lg font-semibold",
723
+ children: h(e.balance_amount, e.currency)
724
+ }), /* @__PURE__ */ Z("p", {
725
+ className: "text-xs text-muted-foreground",
726
+ children: [
727
+ /* @__PURE__ */ X(o, { id: "held " }),
728
+ h(e.held_amount, e.currency),
729
+ /* @__PURE__ */ X(o, { id: " · owed" }),
730
+ " ",
731
+ h(e.owed_amount, e.currency)
732
+ ]
733
+ })] })] }, e.currency))
734
+ }),
735
+ _.balances.some((e) => BigInt(e.owed_amount) > 0n) && /* @__PURE__ */ X("p", {
736
+ className: "text-sm",
737
+ children: /* @__PURE__ */ X(i, {
738
+ className: "underline-offset-2 hover:underline",
739
+ to: `/orders?customer_id=${_.id}&origin=usage&overdue=true`,
740
+ children: /* @__PURE__ */ X(o, { id: "Overdue usage orders" })
741
+ })
742
+ }),
743
+ /* @__PURE__ */ X(_e, {
744
+ customerId: p,
745
+ currencies: _.balances.map((e) => e.currency)
746
+ }),
747
+ /* @__PURE__ */ X(de, { customerId: p }),
748
+ /* @__PURE__ */ Z("div", {
749
+ className: "grid gap-4 lg:grid-cols-3 lg:items-start",
750
+ children: [/* @__PURE__ */ Z("div", {
751
+ className: "grid gap-4 lg:col-span-2",
752
+ children: [
753
+ /* @__PURE__ */ X(Te, { customerId: p }),
754
+ /* @__PURE__ */ X(Ee, { customerId: p }),
755
+ /* @__PURE__ */ X(De, { customerId: p })
756
+ ]
757
+ }), /* @__PURE__ */ Z("div", {
758
+ className: "grid gap-4",
759
+ children: [/* @__PURE__ */ X(Oe, { customerId: p }), /* @__PURE__ */ X(ke, { customerId: p })]
760
+ })]
761
+ })
762
+ ]
763
+ }) : /* @__PURE__ */ X("p", {
764
+ className: "text-sm text-muted-foreground",
765
+ children: /* @__PURE__ */ X(o, { id: "Customer not found." })
766
+ });
767
+ }
768
+ function Te({ customerId: e }) {
769
+ let { adminQueries: t } = r(), n = T(e, 25), { data: a, isFetching: s } = J(t.customerSubscriptions(e, n.size, n.cursor)), c = a?.data ?? [];
770
+ return /* @__PURE__ */ Z(G, { children: [/* @__PURE__ */ X(H, { children: /* @__PURE__ */ X(U, {
771
+ className: "text-sm",
772
+ children: /* @__PURE__ */ X(o, { id: "Subscriptions" })
773
+ }) }), /* @__PURE__ */ Z(W, {
774
+ className: "grid gap-3",
775
+ children: [c.length === 0 ? /* @__PURE__ */ X("p", {
776
+ className: "text-sm text-muted-foreground",
777
+ children: /* @__PURE__ */ X(o, { id: "No subscriptions." })
778
+ }) : /* @__PURE__ */ Z(j, { children: [/* @__PURE__ */ X(O, { children: /* @__PURE__ */ Z(A, {
779
+ className: "hover:bg-transparent",
780
+ children: [
781
+ /* @__PURE__ */ X(E, {
782
+ className: "text-muted-foreground",
783
+ children: /* @__PURE__ */ X(o, { id: "Subscription" })
784
+ }),
785
+ /* @__PURE__ */ X(E, {
786
+ className: "text-muted-foreground",
787
+ children: /* @__PURE__ */ X(o, { id: "Status" })
788
+ }),
789
+ /* @__PURE__ */ X(E, {
790
+ className: "text-muted-foreground",
791
+ children: /* @__PURE__ */ X(o, { id: "Rail" })
792
+ }),
793
+ /* @__PURE__ */ X(E, {
794
+ className: "text-muted-foreground",
795
+ children: /* @__PURE__ */ X(o, { id: "Period ends" })
796
+ }),
797
+ /* @__PURE__ */ X(E, {
798
+ className: "text-muted-foreground",
799
+ children: /* @__PURE__ */ X(o, { id: "Dunning" })
800
+ })
801
+ ]
802
+ }) }), /* @__PURE__ */ X(D, { children: c.map((e) => /* @__PURE__ */ Z(M, {
803
+ to: `/subscriptions/${e.id}`,
804
+ children: [
805
+ /* @__PURE__ */ X(k, { children: /* @__PURE__ */ X(i, {
806
+ className: "text-xs underline-offset-2 hover:underline",
807
+ to: `/subscriptions/${e.id}`,
808
+ children: _(e.id, 13)
809
+ }) }),
810
+ /* @__PURE__ */ X(k, { children: /* @__PURE__ */ X(P, { status: e.status }) }),
811
+ /* @__PURE__ */ X(k, { children: e.rail }),
812
+ /* @__PURE__ */ X(k, {
813
+ className: "tabular-nums",
814
+ children: m(e.current_period_ends_at)
815
+ }),
816
+ /* @__PURE__ */ X(k, {
817
+ className: "text-xs",
818
+ children: e.dunning ? ie(e.dunning) : "—"
819
+ })
820
+ ]
821
+ }, e.id)) })] }), /* @__PURE__ */ X(w, {
822
+ pages: n,
823
+ rows: a?.data?.length ?? 0,
824
+ nextCursor: a?.next_cursor,
825
+ busy: s
826
+ })]
827
+ })] });
828
+ }
829
+ function Ee({ customerId: e }) {
830
+ let { adminQueries: t } = r(), n = T(e, 25), { data: a, isFetching: s } = J(t.customerPayments(e, n.size, n.cursor)), c = a?.data ?? [];
831
+ return /* @__PURE__ */ Z(G, { children: [/* @__PURE__ */ X(H, { children: /* @__PURE__ */ X(U, {
832
+ className: "text-sm",
833
+ children: /* @__PURE__ */ X(o, { id: "Payments" })
834
+ }) }), /* @__PURE__ */ Z(W, {
835
+ className: "grid gap-3",
836
+ children: [c.length === 0 ? /* @__PURE__ */ X("p", {
837
+ className: "text-sm text-muted-foreground",
838
+ children: /* @__PURE__ */ X(o, { id: "No payments." })
839
+ }) : /* @__PURE__ */ Z(j, { children: [/* @__PURE__ */ X(O, { children: /* @__PURE__ */ Z(A, {
840
+ className: "hover:bg-transparent",
841
+ children: [
842
+ /* @__PURE__ */ X(E, {
843
+ className: "text-muted-foreground",
844
+ children: /* @__PURE__ */ X(o, { id: "Payment" })
845
+ }),
846
+ /* @__PURE__ */ X(E, {
847
+ className: "text-muted-foreground",
848
+ children: /* @__PURE__ */ X(o, { id: "Status" })
849
+ }),
850
+ /* @__PURE__ */ X(E, {
851
+ className: "text-muted-foreground",
852
+ children: /* @__PURE__ */ X(o, { id: "Amount" })
853
+ }),
854
+ /* @__PURE__ */ X(E, {
855
+ className: "text-muted-foreground",
856
+ children: /* @__PURE__ */ X(o, { id: "Kind" })
857
+ }),
858
+ /* @__PURE__ */ X(E, {
859
+ className: "text-muted-foreground",
860
+ children: /* @__PURE__ */ X(o, { id: "Rail" })
861
+ }),
862
+ /* @__PURE__ */ X(E, {
863
+ className: "text-muted-foreground",
864
+ children: /* @__PURE__ */ X(o, { id: "Purchased" })
865
+ })
866
+ ]
867
+ }) }), /* @__PURE__ */ X(D, { children: c.map((e) => /* @__PURE__ */ Z(M, {
868
+ to: `/payments/${e.id}`,
869
+ children: [
870
+ /* @__PURE__ */ X(k, { children: /* @__PURE__ */ X(i, {
871
+ className: "text-xs underline-offset-2 hover:underline",
872
+ to: `/payments/${e.id}`,
873
+ children: _(e.id, 13)
874
+ }) }),
875
+ /* @__PURE__ */ X(k, { children: /* @__PURE__ */ X(P, { status: e.status }) }),
876
+ /* @__PURE__ */ X(k, {
877
+ className: "tabular-nums",
878
+ children: h(e.amount, e.currency)
879
+ }),
880
+ /* @__PURE__ */ X(k, { children: e.kind }),
881
+ /* @__PURE__ */ X(k, { children: e.rail ?? e.channel }),
882
+ /* @__PURE__ */ X(k, {
883
+ className: "tabular-nums",
884
+ children: m(e.created_at)
885
+ })
886
+ ]
887
+ }, e.id)) })] }), /* @__PURE__ */ X(w, {
888
+ pages: n,
889
+ rows: a?.data?.length ?? 0,
890
+ nextCursor: a?.next_cursor,
891
+ busy: s
892
+ })]
893
+ })] });
894
+ }
895
+ function De({ customerId: e }) {
896
+ let { adminQueries: t, queryKeys: n } = r(), i = Y(), a = T(e, 25), { data: c, isFetching: l } = J(t.customerPaymentMethodsPage(e, a.size, a.cursor)), u = c?.data ?? [];
897
+ return /* @__PURE__ */ Z(G, { children: [/* @__PURE__ */ Z(H, { children: [/* @__PURE__ */ X(U, {
898
+ className: "text-sm",
899
+ children: /* @__PURE__ */ X(o, { id: "Payment methods" })
900
+ }), /* @__PURE__ */ X(s, {
901
+ variant: "ghost",
902
+ size: "sm",
903
+ onClick: () => void i.invalidateQueries({ queryKey: [...n.customer(e), "payment-methods"] }),
904
+ children: /* @__PURE__ */ X(o, { id: "Refresh payment methods" })
905
+ })] }), /* @__PURE__ */ Z(W, {
906
+ className: "grid gap-3",
907
+ children: [u.length === 0 ? /* @__PURE__ */ X("p", {
908
+ className: "text-sm text-muted-foreground",
909
+ children: /* @__PURE__ */ X(o, { id: "No payment methods on file." })
910
+ }) : /* @__PURE__ */ X("div", {
911
+ className: "flex flex-wrap gap-3",
912
+ children: u.map((e) => /* @__PURE__ */ Z("div", {
913
+ className: "rounded-md border p-3 text-sm",
914
+ children: [
915
+ /* @__PURE__ */ X("p", {
916
+ className: "font-medium",
917
+ children: f(e.card)
918
+ }),
919
+ /* @__PURE__ */ Z("p", {
920
+ className: "text-xs text-muted-foreground",
921
+ children: [
922
+ e.rail,
923
+ /* @__PURE__ */ X(o, { id: " · exp " }),
924
+ d(e.card)
925
+ ]
926
+ }),
927
+ /* @__PURE__ */ X(pe, { currencies: e.default_currencies ?? [] }),
928
+ e.health.expiry_status && e.health.expiry_status !== "valid" && /* @__PURE__ */ X(N, {
929
+ variant: "secondary",
930
+ className: "bg-held-surface text-held mt-1",
931
+ children: e.health.expiry_status
932
+ })
933
+ ]
934
+ }, e.id))
935
+ }), /* @__PURE__ */ X(w, {
936
+ pages: a,
937
+ rows: c?.data?.length ?? 0,
938
+ nextCursor: c?.next_cursor,
939
+ busy: l
940
+ })]
941
+ })] });
942
+ }
943
+ function Oe({ customerId: e }) {
944
+ let { adminQueries: t } = r(), n = T(e, 25), { data: i, isFetching: a } = J(t.customerEntitlements(e, n.size, n.cursor)), s = i?.data ?? [];
945
+ return /* @__PURE__ */ Z(G, { children: [/* @__PURE__ */ X(H, { children: /* @__PURE__ */ X(U, {
946
+ className: "text-sm",
947
+ children: /* @__PURE__ */ X(o, { id: "Entitlements" })
948
+ }) }), /* @__PURE__ */ Z(W, {
949
+ className: "grid gap-3",
950
+ children: [
951
+ /* @__PURE__ */ X("p", {
952
+ className: "text-xs text-muted-foreground",
953
+ children: /* @__PURE__ */ X(o, { id: "The keys of the products this customer holds now." })
954
+ }),
955
+ s.length === 0 ? /* @__PURE__ */ X("p", {
956
+ className: "text-sm text-muted-foreground",
957
+ children: /* @__PURE__ */ X(o, { id: "No entitlements." })
958
+ }) : /* @__PURE__ */ X("div", {
959
+ className: "flex flex-wrap gap-2",
960
+ children: s.map((e) => /* @__PURE__ */ X(N, {
961
+ variant: "secondary",
962
+ children: e.entitlement
963
+ }, e.entitlement))
964
+ }),
965
+ /* @__PURE__ */ X(w, {
966
+ pages: n,
967
+ rows: i?.data?.length ?? 0,
968
+ nextCursor: i?.next_cursor,
969
+ busy: a
970
+ })
971
+ ]
972
+ })] });
973
+ }
974
+ function ke({ customerId: t }) {
975
+ let { text: n } = e(), { adminQueries: i } = r(), a = l(), s = T(t, 25), { data: c, isFetching: u } = J(i.customerProductAccess(t, s.size, s.cursor)), d = c?.data ?? [];
976
+ return /* @__PURE__ */ Z(G, { children: [/* @__PURE__ */ X(H, { children: /* @__PURE__ */ X(U, {
977
+ className: "text-sm",
978
+ children: /* @__PURE__ */ X(o, { id: "Product access" })
979
+ }) }), /* @__PURE__ */ Z(W, {
980
+ className: "grid gap-3",
981
+ children: [d.length === 0 ? /* @__PURE__ */ X("p", {
982
+ className: "text-sm text-muted-foreground",
983
+ children: /* @__PURE__ */ X(o, { id: "No product access." })
984
+ }) : /* @__PURE__ */ X("div", {
985
+ className: "grid gap-4",
986
+ children: d.map((e) => /* @__PURE__ */ Z("div", {
987
+ className: "flex min-w-0 items-start gap-3",
988
+ children: [/* @__PURE__ */ Z("div", {
989
+ className: "min-w-0 flex-1",
990
+ children: [
991
+ /* @__PURE__ */ Z("div", {
992
+ className: "flex min-w-0 items-center gap-2",
993
+ children: [/* @__PURE__ */ X("p", {
994
+ className: "truncate text-sm font-medium",
995
+ children: e.product_name || _(e.product_id, 13)
996
+ }), /* @__PURE__ */ X(P, { status: e.status })]
997
+ }),
998
+ /* @__PURE__ */ X("p", {
999
+ className: "mt-1 text-xs text-muted-foreground",
1000
+ children: e.source_type === "grant" ? `Granted (${e.grant_reason ?? "staff"})${e.note ? `: ${e.note}` : ""}` : e.source_type
1001
+ }),
1002
+ /* @__PURE__ */ X("p", {
1003
+ className: "text-xs text-muted-foreground tabular-nums",
1004
+ children: e.ends_at ? `Ends ${m(e.ends_at)}` : "No end date"
1005
+ })
1006
+ ]
1007
+ }), a && /* @__PURE__ */ X(Ae, {
1008
+ customerId: t,
1009
+ grantId: e.id,
1010
+ label: n("Revoke product access")
1011
+ })]
1012
+ }, e.id))
1013
+ }), /* @__PURE__ */ X(w, {
1014
+ pages: s,
1015
+ rows: c?.data?.length ?? 0,
1016
+ nextCursor: c?.next_cursor,
1017
+ busy: u
1018
+ })]
1019
+ })] });
1020
+ }
1021
+ function Ae({ customerId: t, grantId: n, label: i }) {
1022
+ let { toast: a, toastApiError: l, adminMutations: u } = r(), { id: d } = e(), f = Y(), p = q(u.revokeCustomerProductAccess(f, t)), [m, h] = K.useState(!1), [g, _] = K.useState("");
1023
+ return /* @__PURE__ */ Z(B, {
1024
+ open: m,
1025
+ onOpenChange: h,
1026
+ children: [/* @__PURE__ */ X(ee, { render: /* @__PURE__ */ X(s, {
1027
+ variant: "ghost",
1028
+ size: "icon",
1029
+ "aria-label": i,
1030
+ children: /* @__PURE__ */ X(Q, {
1031
+ icon: le,
1032
+ className: "size-4 text-destructive"
1033
+ })
1034
+ }) }), /* @__PURE__ */ Z(L, {
1035
+ className: te,
1036
+ children: [
1037
+ /* @__PURE__ */ Z(F, { children: [/* @__PURE__ */ X(R, { children: /* @__PURE__ */ X(o, { id: "Take the product back" }) }), /* @__PURE__ */ X(z, { children: /* @__PURE__ */ X(o, { id: "The customer loses its entitlements now. The grant stays on record with your reason." }) })] }),
1038
+ /* @__PURE__ */ Z("div", {
1039
+ className: "flex flex-col gap-1.5",
1040
+ children: [/* @__PURE__ */ X(V, {
1041
+ htmlFor: d("revoke-access-reason"),
1042
+ children: /* @__PURE__ */ X(o, { id: "Reason" })
1043
+ }), /* @__PURE__ */ X(c, {
1044
+ id: d("revoke-access-reason"),
1045
+ value: g,
1046
+ onChange: (e) => _(e.target.value),
1047
+ maxLength: 500
1048
+ })]
1049
+ }),
1050
+ /* @__PURE__ */ Z(I, { children: [/* @__PURE__ */ X(s, {
1051
+ variant: "outline",
1052
+ onClick: () => h(!1),
1053
+ children: /* @__PURE__ */ X(o, { id: "Cancel" })
1054
+ }), /* @__PURE__ */ X(s, {
1055
+ variant: "destructive",
1056
+ disabled: !g.trim() || p.isPending,
1057
+ onClick: async () => {
1058
+ try {
1059
+ await p.mutateAsync({
1060
+ grantId: n,
1061
+ reason: g.trim()
1062
+ }), a.success("Product access revoked"), h(!1);
1063
+ } catch (e) {
1064
+ l(e, i);
1065
+ }
1066
+ },
1067
+ children: p.isPending ? "Revoking…" : "Revoke"
1068
+ })] })
1069
+ ]
1070
+ })]
1071
+ });
1072
+ }
1073
+ function je({ customerId: t }) {
1074
+ let { toast: n, toastApiError: i, adminMutations: a, adminQueries: l } = r(), { id: u, text: d } = e(), [f, p] = K.useState(!1), m = Y(), h = q(a.grantCustomerProductAccess(m, t)), { data: g } = J({
1075
+ ...l.allProducts(),
1076
+ enabled: f
1077
+ }), _ = ue({
1078
+ defaultValues: {
1079
+ productId: "",
1080
+ duration: "30",
1081
+ until: "",
1082
+ note: ""
1083
+ },
1084
+ onSubmit: async ({ value: e }) => {
1085
+ let t = Ce(e.duration, e.until);
1086
+ if (t) try {
1087
+ await h.mutateAsync({
1088
+ productId: e.productId,
1089
+ ...t,
1090
+ note: e.note.trim() || void 0
1091
+ }), n.success("Product access granted"), w(!1);
1092
+ } catch (e) {
1093
+ i(e, "Grant product access");
1094
+ }
1095
+ }
1096
+ }), w = (e) => {
1097
+ p(e), e || (_.reset(), h.reset());
1098
+ };
1099
+ return /* @__PURE__ */ Z(B, {
1100
+ open: f,
1101
+ onOpenChange: w,
1102
+ children: [/* @__PURE__ */ X(ee, { render: /* @__PURE__ */ Z(s, {
1103
+ variant: "outline",
1104
+ size: "sm",
1105
+ children: [/* @__PURE__ */ X(Q, {
1106
+ icon: se,
1107
+ className: "size-4"
1108
+ }), /* @__PURE__ */ X(o, { id: " Product access" })]
1109
+ }) }), /* @__PURE__ */ Z(L, {
1110
+ className: te,
1111
+ children: [/* @__PURE__ */ Z(F, { children: [/* @__PURE__ */ X(R, { children: /* @__PURE__ */ X(o, { id: "Grant product access" }) }), /* @__PURE__ */ X(z, { children: /* @__PURE__ */ X(o, { id: "Give this customer one of your products without a payment. They hold its keys while the grant lasts, including keys you add to the product later." }) })] }), /* @__PURE__ */ Z("form", {
1112
+ onSubmit: (e) => {
1113
+ e.preventDefault(), e.stopPropagation(), _.handleSubmit();
1114
+ },
1115
+ className: "grid gap-4",
1116
+ children: [/* @__PURE__ */ Z("div", {
1117
+ className: "grid gap-3",
1118
+ children: [
1119
+ /* @__PURE__ */ X(_.Field, {
1120
+ name: "productId",
1121
+ validators: { onChange: ({ value: e }) => e ? void 0 : "Pick a product" },
1122
+ children: (e) => /* @__PURE__ */ Z("div", {
1123
+ className: "grid gap-1.5",
1124
+ children: [
1125
+ /* @__PURE__ */ X(V, {
1126
+ htmlFor: u("pa-product"),
1127
+ children: /* @__PURE__ */ X(o, { id: "Product" })
1128
+ }),
1129
+ /* @__PURE__ */ Z(C, {
1130
+ value: e.state.value,
1131
+ onValueChange: (t) => e.handleChange(t ?? ""),
1132
+ children: [/* @__PURE__ */ X(b, {
1133
+ className: "w-full",
1134
+ id: u("pa-product"),
1135
+ "aria-invalid": e.state.meta.errors.length > 0,
1136
+ children: /* @__PURE__ */ X(y, { placeholder: d("Pick a product") })
1137
+ }), /* @__PURE__ */ X(x, { children: (g?.data ?? []).map((e) => /* @__PURE__ */ Z(S, {
1138
+ value: e.id,
1139
+ children: [
1140
+ e.display_name,
1141
+ " (",
1142
+ e.key,
1143
+ ")"
1144
+ ]
1145
+ }, e.id)) })]
1146
+ }),
1147
+ /* @__PURE__ */ X(v, { errors: e.state.meta.errors })
1148
+ ]
1149
+ })
1150
+ }),
1151
+ /* @__PURE__ */ X(_.Field, {
1152
+ name: "duration",
1153
+ children: (e) => /* @__PURE__ */ Z("div", {
1154
+ className: "grid gap-1.5",
1155
+ children: [
1156
+ /* @__PURE__ */ X(V, {
1157
+ htmlFor: u("pa-duration"),
1158
+ children: /* @__PURE__ */ X(o, { id: "How long it lasts" })
1159
+ }),
1160
+ /* @__PURE__ */ X("p", {
1161
+ className: "text-[13px] text-muted-foreground",
1162
+ children: /* @__PURE__ */ X(o, { id: "Days are added after any access they already have." })
1163
+ }),
1164
+ /* @__PURE__ */ Z(C, {
1165
+ items: xe.map((e) => ({
1166
+ value: e.value,
1167
+ label: e.label
1168
+ })),
1169
+ value: e.state.value,
1170
+ onValueChange: (t) => {
1171
+ t && e.handleChange(t);
1172
+ },
1173
+ children: [/* @__PURE__ */ X(b, {
1174
+ className: "w-full",
1175
+ id: u("pa-duration"),
1176
+ children: /* @__PURE__ */ X(y, {})
1177
+ }), /* @__PURE__ */ X(x, { children: xe.map((e) => /* @__PURE__ */ X(S, {
1178
+ value: e.value,
1179
+ children: e.label
1180
+ }, e.value)) })]
1181
+ })
1182
+ ]
1183
+ })
1184
+ }),
1185
+ /* @__PURE__ */ X(_.Subscribe, {
1186
+ selector: (e) => e.values.duration,
1187
+ children: (e) => e === "until" ? /* @__PURE__ */ X(_.Field, {
1188
+ name: "until",
1189
+ validators: { onChange: ({ value: e }) => Ce("until", e) ? void 0 : "Pick today or a later date" },
1190
+ children: (e) => /* @__PURE__ */ Z("div", {
1191
+ className: "grid gap-1.5",
1192
+ children: [
1193
+ /* @__PURE__ */ X(V, {
1194
+ htmlFor: u("pa-until"),
1195
+ children: /* @__PURE__ */ X(o, { id: "Last day (UTC)" })
1196
+ }),
1197
+ /* @__PURE__ */ X(c, {
1198
+ id: u("pa-until"),
1199
+ type: "date",
1200
+ min: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
1201
+ value: e.state.value,
1202
+ onBlur: e.handleBlur,
1203
+ onChange: (t) => e.handleChange(t.target.value),
1204
+ "aria-invalid": e.state.meta.errors.length > 0
1205
+ }),
1206
+ /* @__PURE__ */ X(v, { errors: e.state.meta.errors })
1207
+ ]
1208
+ })
1209
+ }) : null
1210
+ }),
1211
+ /* @__PURE__ */ X(_.Field, {
1212
+ name: "note",
1213
+ children: (e) => /* @__PURE__ */ Z("div", {
1214
+ className: "grid gap-1.5",
1215
+ children: [/* @__PURE__ */ X(V, {
1216
+ htmlFor: u("pa-note"),
1217
+ children: /* @__PURE__ */ X(o, { id: "Note" })
1218
+ }), /* @__PURE__ */ X(c, {
1219
+ id: u("pa-note"),
1220
+ value: e.state.value,
1221
+ onBlur: e.handleBlur,
1222
+ onChange: (t) => e.handleChange(t.target.value),
1223
+ placeholder: d("Why it was granted")
1224
+ })]
1225
+ })
1226
+ })
1227
+ ]
1228
+ }), /* @__PURE__ */ X(I, { children: /* @__PURE__ */ X(_.Subscribe, {
1229
+ selector: (e) => [
1230
+ e.values.productId,
1231
+ e.canSubmit,
1232
+ e.isSubmitting,
1233
+ Ce(e.values.duration, e.values.until) !== null
1234
+ ],
1235
+ children: ([e, t, n, r]) => /* @__PURE__ */ Z(oe, { children: [/* @__PURE__ */ X(s, {
1236
+ type: "button",
1237
+ variant: "outline",
1238
+ disabled: n,
1239
+ onClick: () => w(!1),
1240
+ children: /* @__PURE__ */ X(o, { id: "Cancel" })
1241
+ }), /* @__PURE__ */ X(s, {
1242
+ type: "submit",
1243
+ disabled: !e || !t || n || !r,
1244
+ children: n ? "Granting…" : "Grant access"
1245
+ })] })
1246
+ }) })]
1247
+ })]
1248
+ })]
1249
+ });
1250
+ }
1251
+ function Me({ contact: e }) {
1252
+ return /* @__PURE__ */ Z(G, { children: [/* @__PURE__ */ X(H, {
1253
+ className: "pb-1",
1254
+ children: /* @__PURE__ */ X(U, {
1255
+ className: "text-sm",
1256
+ children: /* @__PURE__ */ X(o, { id: "Contact" })
1257
+ })
1258
+ }), /* @__PURE__ */ X(W, {
1259
+ className: "text-sm",
1260
+ children: e ? /* @__PURE__ */ Z("dl", {
1261
+ className: "grid grid-cols-[auto_1fr] gap-x-4 gap-y-1",
1262
+ children: [
1263
+ /* @__PURE__ */ X("dt", {
1264
+ className: "text-muted-foreground",
1265
+ children: /* @__PURE__ */ X(o, { id: "Email" })
1266
+ }),
1267
+ /* @__PURE__ */ X("dd", {
1268
+ className: "truncate",
1269
+ children: e.email ?? "—"
1270
+ }),
1271
+ /* @__PURE__ */ X("dt", {
1272
+ className: "text-muted-foreground",
1273
+ children: /* @__PURE__ */ X(o, { id: "Name" })
1274
+ }),
1275
+ /* @__PURE__ */ X("dd", {
1276
+ className: "truncate",
1277
+ children: e.name ?? "—"
1278
+ }),
1279
+ /* @__PURE__ */ X("dt", {
1280
+ className: "text-muted-foreground",
1281
+ children: /* @__PURE__ */ X(o, { id: "Username" })
1282
+ }),
1283
+ /* @__PURE__ */ X("dd", {
1284
+ className: "truncate",
1285
+ children: e.username ?? "—"
1286
+ }),
1287
+ e.active !== null && /* @__PURE__ */ Z(oe, { children: [/* @__PURE__ */ X("dt", {
1288
+ className: "text-muted-foreground",
1289
+ children: /* @__PURE__ */ X(o, { id: "Directory" })
1290
+ }), /* @__PURE__ */ X("dd", { children: /* @__PURE__ */ X(N, {
1291
+ variant: e.active ? "secondary" : "outline",
1292
+ children: e.active ? "Active" : "Deactivated"
1293
+ }) })] }),
1294
+ /* @__PURE__ */ X("dt", {
1295
+ className: "text-muted-foreground",
1296
+ children: /* @__PURE__ */ X(o, { id: "Synced" })
1297
+ }),
1298
+ /* @__PURE__ */ X("dd", {
1299
+ className: "tabular-nums",
1300
+ children: e.synced_at ? m(e.synced_at) : "Live"
1301
+ })
1302
+ ]
1303
+ }) : /* @__PURE__ */ X("p", {
1304
+ className: "text-muted-foreground",
1305
+ children: /* @__PURE__ */ X(o, { id: "Your directory holds no contact for this customer." })
1306
+ })
1307
+ })] });
1308
+ }
1309
+ //#endregion
1310
+ export { we as CustomerDetailPage };
1311
+
1312
+ //# sourceMappingURL=admin-detail-CGOyqs7s.js.map