@openrails/billing-ui 0.242.0 → 0.244.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 (267) 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-CK6CM9I2.js +1199 -0
  143. package/dist/admin-catalog-CK6CM9I2.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-COFcSPQy.js +1721 -0
  189. package/dist/admin-metering-COFcSPQy.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/client.d.ts +13 -6
  235. package/dist/client/generated/error-codes.d.ts +1 -1
  236. package/dist/client/generated/routes.d.ts +2173 -178
  237. package/dist/client/generated/wire.d.ts +1287 -1
  238. package/dist/client/index.d.ts +1 -1
  239. package/dist/client/types.d.ts +14 -2
  240. package/dist/{client-PjivPHmE.js → client-D5Af726I.js} +8 -7
  241. package/dist/client-D5Af726I.js.map +1 -0
  242. package/dist/client.js +1 -1
  243. package/dist/{hooks-Uiw-zW3H.js → hooks-CYjlHS28.js} +8 -8
  244. package/dist/hooks-CYjlHS28.js.map +1 -0
  245. package/dist/index.d.ts +1 -1
  246. package/dist/index.js +12 -12
  247. package/dist/index.js.map +1 -1
  248. package/dist/lib/{offer-label.d.ts → price-label.d.ts} +1 -1
  249. package/dist/locales/de.js +1 -1
  250. package/dist/locales/de.js.map +1 -1
  251. package/dist/locales/en.d.ts +1 -1
  252. package/dist/locales/en.js +1 -1
  253. package/dist/locales/en.js.map +1 -1
  254. package/dist/locales/es.js +1 -1
  255. package/dist/locales/es.js.map +1 -1
  256. package/dist/locales/ja.js +1 -1
  257. package/dist/locales/ja.js.map +1 -1
  258. package/dist/locales/ko.js +1 -1
  259. package/dist/locales/ko.js.map +1 -1
  260. package/dist/locales/zh.js +1 -1
  261. package/dist/locales/zh.js.map +1 -1
  262. package/dist/{offers.d.ts → product-list.d.ts} +5 -5
  263. package/dist/react.js +1 -1
  264. package/dist/styles.css +1 -1
  265. package/package.json +28 -6
  266. package/dist/client-PjivPHmE.js.map +0 -1
  267. package/dist/hooks-Uiw-zW3H.js.map +0 -1
@@ -0,0 +1,1721 @@
1
+ import { E as e, S as t, c 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 { t as l } from "./admin-skeleton-DsM7crYi.js";
5
+ import { s as u } from "./admin-capabilities-BuigAgtm.js";
6
+ import { c as d, d as f, l as p, n as m, o as h, s as g } from "./admin-format-DoohJ7Fg.js";
7
+ import { n as _ } from "./admin-confirm-katGq0Qo.js";
8
+ import { t as v } from "./admin-form-field-errors-hbUMIriS.js";
9
+ import { a as y, i as b, n as x, r as S, t as C } from "./admin-select-DBgprVW6.js";
10
+ import { n as w, r as T } from "./admin-dom-uMmZzRvU.js";
11
+ import { a as E, n as ee, o as te, r as D, s as O, t as k } from "./admin-table-CH9TrXJf.js";
12
+ import { t as ne } from "./admin-linked-table-row-BsaUruCN.js";
13
+ import { t as A } from "./admin-badge-DR5-1qd8.js";
14
+ import { a as re, i as ie, n as ae, o as oe, r as se, s as ce, t as le } from "./admin-dialog-BjuKI5Hp.js";
15
+ import { t as j } from "./admin-label-BiEN5cjb.js";
16
+ import { t as ue } from "./admin-switch-BJUxLCsa.js";
17
+ import { n as de, r as fe } from "./admin-dialog-width-BPrgdYlj.js";
18
+ import * as M from "react";
19
+ import { useMutation as pe, useQuery as me, useQueryClient as he } from "@tanstack/react-query";
20
+ import { Fragment as N, jsx as P, jsxs as F } from "react/jsx-runtime";
21
+ import { HugeiconsIcon as I } from "@hugeicons/react";
22
+ import { Activity01Icon as ge, Add01Icon as L, ArrowLeft01Icon as _e, ArrowRight01Icon as ve, Delete02Icon as R, Edit02Icon as z, InformationCircleIcon as ye, Money03Icon as be, Search01Icon as xe } from "@hugeicons/core-free-icons";
23
+ import { useForm as Se } from "@tanstack/react-form";
24
+ //#region src/admin/pages/catalog/metering-model.ts
25
+ var Ce = class extends Error {
26
+ fieldId;
27
+ constructor(e, t) {
28
+ super(t), this.name = "RateCardFormError", this.fieldId = e;
29
+ }
30
+ };
31
+ function we(e) {
32
+ return e.pending ? "loading" : e.error?.status === 403 ? "permission" : e.error ? "error" : e.count === 0 ? "empty" : "ready";
33
+ }
34
+ function Te(e) {
35
+ return e.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^[-_]+|[-_]+$/g, "");
36
+ }
37
+ function Ee(e) {
38
+ return {
39
+ key: e?.key ?? "",
40
+ eventType: e?.event_type ?? "",
41
+ aggregation: e?.aggregation === "count" ? "count" : "sum",
42
+ valueProperty: e?.value_property ?? "",
43
+ unit: e?.unit ?? "",
44
+ groupBy: Object.entries(e?.group_by ?? {}).map(([e, t]) => ({
45
+ key: e,
46
+ value: t
47
+ }))
48
+ };
49
+ }
50
+ function De(e) {
51
+ let t = Te(e.key);
52
+ if (!t) throw Error("Enter a meter key.");
53
+ let n = e.eventType.trim(), r = e.valueProperty.trim();
54
+ if (e.aggregation === "sum" && !r) throw Error("Sum meters require a value property.");
55
+ let i = Me(e.groupBy, "group");
56
+ return {
57
+ key: t,
58
+ meter: {
59
+ event_type: n,
60
+ aggregation: e.aggregation,
61
+ value_property: e.aggregation === "sum" ? r : "",
62
+ unit: e.unit.trim() || void 0,
63
+ group_by: i
64
+ }
65
+ };
66
+ }
67
+ function Oe(e) {
68
+ let t = e?.price, n = t?.per_unit?.matrix, r = e?.allowance, i = r?.included === void 0 ? "none" : "included", a = t?.currency ?? "USD";
69
+ return {
70
+ productId: e?.product_id ?? "",
71
+ model: t?.model && t.model !== "flat" ? t.model : "per_unit",
72
+ currency: a,
73
+ unitAmount: U(a, t?.per_unit?.unit_amount),
74
+ divideBy: W(t?.per_unit?.divide_by, "1"),
75
+ round: t?.per_unit?.round ?? "half_up",
76
+ maximumAmount: U(a, t?.per_unit?.maximum_amount),
77
+ matrixEnabled: !!n,
78
+ matrixDimension: n?.dimension ?? "",
79
+ matrixCells: Object.entries(n?.cells ?? {}).map(([e, t]) => ({
80
+ key: e,
81
+ unitAmount: U(a, t.unit_amount),
82
+ maximumAmount: U(a, t.maximum_amount)
83
+ })),
84
+ tierMode: "graduated",
85
+ tiers: (t?.tiered?.tiers ?? [{
86
+ up_to: null,
87
+ unit_amount: "0",
88
+ flat_amount: "0"
89
+ }]).map((e) => ({
90
+ upTo: e.up_to === null ? "" : String(e.up_to),
91
+ unitAmount: U(a, e.unit_amount),
92
+ flatAmount: U(a, e.flat_amount)
93
+ })),
94
+ packageAmount: U(a, t?.package?.amount),
95
+ packageSize: W(t?.package?.package_size, "1"),
96
+ freeUnits: W(t?.package?.free_units),
97
+ filters: Object.entries(e?.filter ?? {}).map(([e, t]) => ({
98
+ key: e,
99
+ value: t.join(", ")
100
+ })),
101
+ allowanceMode: i,
102
+ allowanceIncluded: W(r?.included)
103
+ };
104
+ }
105
+ function ke(e) {
106
+ e.productId || H("rate-product", "Select a product.");
107
+ let t = e.currency.trim().toUpperCase();
108
+ m(t) === void 0 && H("rate-currency", `Use a supported currency: ${f.join(", ")}.`);
109
+ let n = Ae(e, t), r = e.model === "dynamic" ? void 0 : je(e);
110
+ return {
111
+ product_id: e.productId,
112
+ filter: Ne(e.filters),
113
+ price: n,
114
+ ...r ? { allowance: r } : {}
115
+ };
116
+ }
117
+ function Ae(e, t) {
118
+ if (e.model === "dynamic") return {
119
+ model: "dynamic",
120
+ currency: t
121
+ };
122
+ if (e.model === "per_unit") {
123
+ let n = Pe(e.divideBy, "Divisor", "rate-divide-by"), r = V(t, e.maximumAmount, "Maximum amount", "rate-maximum");
124
+ if (e.matrixEnabled) {
125
+ let i = e.matrixDimension.trim();
126
+ i || H("matrix-dimension", "Select a matrix dimension."), e.matrixCells.length === 0 && H("matrix-add-cell", "Add at least one matrix cell.");
127
+ let a = {};
128
+ for (let [n, r] of e.matrixCells.entries()) {
129
+ let e = r.key.trim(), i = `matrix-cell-${n}`;
130
+ e || H(`${i}-value`, "Each matrix cell needs a value."), a[e] && H(`${i}-value`, `Duplicate matrix value “${e}”.`), a[e] = {
131
+ unit_amount: B(t, r.unitAmount, `Price for ${e}`, `${i}-unit-price`, !0),
132
+ ...V(t, r.maximumAmount, `Maximum for ${e}`, `${i}-maximum`) === "0" ? {} : { maximum_amount: V(t, r.maximumAmount, `Maximum for ${e}`, `${i}-maximum`) }
133
+ };
134
+ }
135
+ return {
136
+ model: "per_unit",
137
+ currency: t,
138
+ per_unit: {
139
+ divide_by: n,
140
+ round: e.round,
141
+ ...r === "0" ? {} : { maximum_amount: r },
142
+ matrix: {
143
+ dimension: i,
144
+ cells: a
145
+ }
146
+ }
147
+ };
148
+ }
149
+ return {
150
+ model: "per_unit",
151
+ currency: t,
152
+ per_unit: {
153
+ unit_amount: B(t, e.unitAmount, "Unit price", "rate-unit-amount", !0),
154
+ divide_by: n,
155
+ round: e.round,
156
+ ...r === "0" ? {} : { maximum_amount: r }
157
+ }
158
+ };
159
+ }
160
+ if (e.model === "tiered") {
161
+ e.tiers.length === 0 && H("tier-add", "Add at least one tier.");
162
+ let n = e.tiers.map((n, r) => {
163
+ let i = r === e.tiers.length - 1, a = n.upTo.trim();
164
+ return i && a && H(`tier-${r}-limit`, "The final tier must be unbounded."), !i && !a && H(`tier-${r}-limit`, "Only the final tier can be unbounded."), {
165
+ up_to: i ? null : Pe(a, `Tier ${r + 1} limit`, `tier-${r}-limit`),
166
+ unit_amount: B(t, n.unitAmount, `Tier ${r + 1} unit price`, `tier-${r}-unit-price`, !0),
167
+ flat_amount: V(t, n.flatAmount, `Tier ${r + 1} flat amount`, `tier-${r}-flat-amount`)
168
+ };
169
+ });
170
+ for (let e = 1; e < n.length - 1; e += 1) (n[e].up_to ?? 0) <= (n[e - 1].up_to ?? 0) && H(`tier-${e}-limit`, "Tier limits must increase.");
171
+ return {
172
+ model: "tiered",
173
+ currency: t,
174
+ tiered: {
175
+ mode: e.tierMode,
176
+ tiers: n
177
+ }
178
+ };
179
+ }
180
+ return {
181
+ model: "package",
182
+ currency: t,
183
+ package: {
184
+ amount: B(t, e.packageAmount, "Package price", "package-amount"),
185
+ package_size: Pe(e.packageSize, "Package size", "package-size"),
186
+ free_units: Fe(e.freeUnits, "Free units", "package-free")
187
+ }
188
+ };
189
+ }
190
+ function je(e) {
191
+ if (e.allowanceMode !== "none") return { included: Fe(e.allowanceIncluded, "Included allowance", "allowance-included") };
192
+ }
193
+ function Me(e, t) {
194
+ let n = {};
195
+ for (let r of e) {
196
+ let e = r.key.trim(), i = r.value.trim();
197
+ if (!e || !i) throw Error(`Each ${t} row needs both fields.`);
198
+ if (n[e]) throw Error(`Duplicate ${t} key “${e}”.`);
199
+ n[e] = i;
200
+ }
201
+ return n;
202
+ }
203
+ function Ne(e) {
204
+ let t = {};
205
+ for (let [n, r] of e.entries()) {
206
+ let e = r.key.trim(), i = [...new Set(r.value.split(",").map((e) => e.trim()))].filter(Boolean);
207
+ e || H(`filter-${n}-dimension`, "Select a dimension for this filter."), i.length === 0 && H(`filter-${n}-values`, "Enter at least one value for this filter."), t[e] && H(`filter-${n}-dimension`, `Duplicate filter dimension “${e}”.`), t[e] = i;
208
+ }
209
+ return t;
210
+ }
211
+ function B(e, t, n, r, i = !1) {
212
+ let a = d(t, e);
213
+ return (a === null || BigInt(a) < 0n || !i && BigInt(a) === 0n) && H(r, `${n} must be ${i ? "zero or more" : "greater than zero"}.`), a;
214
+ }
215
+ function V(e, t, n, r) {
216
+ return t.trim() ? B(e, t, n, r, !0) : "0";
217
+ }
218
+ function Pe(e, t, n) {
219
+ let r = Number(e);
220
+ return (!Number.isSafeInteger(r) || r <= 0) && H(n, `${t} must be a positive whole number.`), r;
221
+ }
222
+ function Fe(e, t, n) {
223
+ if (!e.trim()) return 0;
224
+ let r = Number(e);
225
+ return (!Number.isSafeInteger(r) || r < 0) && H(n, `${t} must be zero or a positive whole number.`), r;
226
+ }
227
+ function H(e, t) {
228
+ throw new Ce(e, t);
229
+ }
230
+ function U(e, t) {
231
+ return t && t !== "0" ? p(t, e) : "";
232
+ }
233
+ function W(e, t = "") {
234
+ return e ? String(e) : t;
235
+ }
236
+ function Ie(e) {
237
+ if (!e) return "Not priced";
238
+ let { price: t } = e, n = t.currency ?? "";
239
+ return t.model === "dynamic" ? `Event amount · ${n}` : t.model === "per_unit" && t.per_unit ? t.per_unit.matrix ? `${Object.keys(t.per_unit.matrix.cells ?? {}).length} matrix rates · ${n}` : `${g(t.per_unit.unit_amount ?? "0", n)} per ${t.per_unit.divide_by || 1} units` : t.model === "tiered" && t.tiered ? `${t.tiered.tiers?.length ?? 0} ${t.tiered.mode} tiers · ${n}` : t.model === "package" && t.package ? `${g(t.package.amount ?? "0", n)} per ${(t.package.package_size ?? 1).toLocaleString()} units` : `Unsupported price · ${n}`;
240
+ }
241
+ function Le(e, t) {
242
+ return t ? e.has_activity ? "Meter definitions lock after the first event." : null : "Catalog updates are disabled.";
243
+ }
244
+ //#endregion
245
+ //#region src/admin/pages/catalog/meter-form.tsx
246
+ function Re({ meter: t, writesAllowed: n }) {
247
+ let { toast: i, toastApiError: a, adminMutations: l } = r(), { id: u, text: d } = e(), [f, p] = M.useState(!1), [m, h] = M.useState(""), g = he(), _ = pe(l.putUsageMeter(g)), w = t ? Le(t, n) : null, T = Se({
248
+ defaultValues: Ee(t),
249
+ onSubmit: async ({ value: e }) => {
250
+ h("");
251
+ try {
252
+ let n = De(e);
253
+ n.meter.expected_revision = t?.revision ?? 0, await _.mutateAsync(n), i.success(t ? "Meter updated" : "Meter created"), p(!1), T.reset();
254
+ } catch (e) {
255
+ if (e instanceof Error && !("status" in e)) {
256
+ h(e.message);
257
+ return;
258
+ }
259
+ a(e, t ? "Update meter" : "Create meter");
260
+ }
261
+ }
262
+ });
263
+ return w ? /* @__PURE__ */ F(s, {
264
+ variant: "outline",
265
+ size: "sm",
266
+ disabled: !0,
267
+ title: w,
268
+ children: [/* @__PURE__ */ P(I, {
269
+ icon: z,
270
+ className: "size-4"
271
+ }), /* @__PURE__ */ P(o, { id: "Edit definition" })]
272
+ }) : /* @__PURE__ */ F(le, {
273
+ open: f,
274
+ onOpenChange: (e) => {
275
+ p(e), h(""), e || T.reset();
276
+ },
277
+ children: [/* @__PURE__ */ P(ce, { render: /* @__PURE__ */ F(s, {
278
+ variant: t ? "outline" : "default",
279
+ size: "sm",
280
+ children: [/* @__PURE__ */ P(I, {
281
+ icon: t ? z : L,
282
+ className: "size-4"
283
+ }), t ? "Edit definition" : "Create meter"]
284
+ }) }), /* @__PURE__ */ P(ae, {
285
+ className: de,
286
+ children: /* @__PURE__ */ F("form", {
287
+ className: "grid gap-5",
288
+ onSubmit: (e) => {
289
+ e.preventDefault(), e.stopPropagation(), T.handleSubmit();
290
+ },
291
+ children: [
292
+ /* @__PURE__ */ F(re, { children: [/* @__PURE__ */ P(oe, { children: t ? "Edit meter" : "Create meter" }), /* @__PURE__ */ P(se, { children: /* @__PURE__ */ P(o, { id: "Define the event fields OpenRails will aggregate. Your host still reports each event through the usage API." }) })] }),
293
+ /* @__PURE__ */ F("div", {
294
+ className: "grid gap-4",
295
+ children: [
296
+ /* @__PURE__ */ P(T.Field, {
297
+ name: "key",
298
+ validators: { onBlur: ({ value: e }) => e.trim() ? void 0 : "Enter a meter key." },
299
+ children: (e) => /* @__PURE__ */ F("div", {
300
+ className: "grid gap-1.5",
301
+ children: [
302
+ /* @__PURE__ */ P(j, {
303
+ htmlFor: u("meter-key"),
304
+ children: /* @__PURE__ */ P(o, { id: "Key" })
305
+ }),
306
+ /* @__PURE__ */ P(c, {
307
+ id: u("meter-key"),
308
+ value: e.state.value,
309
+ onChange: (t) => e.handleChange(t.target.value),
310
+ onBlur: e.handleBlur,
311
+ disabled: !!t,
312
+ placeholder: d("api-tokens"),
313
+ autoComplete: "off"
314
+ }),
315
+ /* @__PURE__ */ P("p", {
316
+ className: "text-xs text-muted-foreground",
317
+ children: /* @__PURE__ */ P(o, { id: "Stable identifier. It cannot be renamed after creation." })
318
+ }),
319
+ /* @__PURE__ */ P(v, { errors: e.state.meta.errors })
320
+ ]
321
+ })
322
+ }),
323
+ /* @__PURE__ */ F("div", {
324
+ className: "grid gap-4 sm:grid-cols-2",
325
+ children: [/* @__PURE__ */ P(T.Field, {
326
+ name: "eventType",
327
+ children: (e) => /* @__PURE__ */ F("div", {
328
+ className: "grid gap-1.5",
329
+ children: [
330
+ /* @__PURE__ */ P(j, {
331
+ htmlFor: u("meter-event-type"),
332
+ children: /* @__PURE__ */ P(o, { id: "Event type" })
333
+ }),
334
+ /* @__PURE__ */ P(c, {
335
+ id: u("meter-event-type"),
336
+ value: e.state.value,
337
+ onChange: (t) => e.handleChange(t.target.value),
338
+ placeholder: d("token.used"),
339
+ autoComplete: "off"
340
+ }),
341
+ /* @__PURE__ */ P("p", {
342
+ className: "text-xs text-muted-foreground",
343
+ children: /* @__PURE__ */ P(o, { id: "Leave blank to use the meter key." })
344
+ })
345
+ ]
346
+ })
347
+ }), /* @__PURE__ */ P(T.Field, {
348
+ name: "unit",
349
+ children: (e) => /* @__PURE__ */ F("div", {
350
+ className: "grid gap-1.5",
351
+ children: [
352
+ /* @__PURE__ */ P(j, {
353
+ htmlFor: u("meter-unit"),
354
+ children: /* @__PURE__ */ P(o, { id: "Unit" })
355
+ }),
356
+ /* @__PURE__ */ P(c, {
357
+ id: u("meter-unit"),
358
+ value: e.state.value,
359
+ onChange: (t) => e.handleChange(t.target.value),
360
+ placeholder: d("tokens"),
361
+ autoComplete: "off"
362
+ }),
363
+ /* @__PURE__ */ P("p", {
364
+ className: "text-xs text-muted-foreground",
365
+ children: /* @__PURE__ */ P(o, { id: "Human-readable quantity shown in billing." })
366
+ })
367
+ ]
368
+ })
369
+ })]
370
+ }),
371
+ /* @__PURE__ */ F("div", {
372
+ className: "grid gap-4 sm:grid-cols-2",
373
+ children: [/* @__PURE__ */ P(T.Field, {
374
+ name: "aggregation",
375
+ children: (e) => /* @__PURE__ */ F("div", {
376
+ className: "grid gap-1.5",
377
+ children: [/* @__PURE__ */ P(j, {
378
+ htmlFor: u("meter-aggregation"),
379
+ children: /* @__PURE__ */ P(o, { id: "Aggregation" })
380
+ }), /* @__PURE__ */ F(C, {
381
+ value: e.state.value,
382
+ onValueChange: (t) => e.handleChange(t),
383
+ children: [/* @__PURE__ */ P(b, {
384
+ id: u("meter-aggregation"),
385
+ className: "w-full",
386
+ children: /* @__PURE__ */ P(y, {})
387
+ }), /* @__PURE__ */ F(x, { children: [/* @__PURE__ */ P(S, {
388
+ value: "sum",
389
+ children: /* @__PURE__ */ P(o, { id: "Sum a numeric field" })
390
+ }), /* @__PURE__ */ P(S, {
391
+ value: "count",
392
+ children: /* @__PURE__ */ P(o, { id: "Count events" })
393
+ })] })]
394
+ })]
395
+ })
396
+ }), /* @__PURE__ */ P(T.Subscribe, {
397
+ selector: (e) => e.values.aggregation,
398
+ children: (e) => e === "sum" ? /* @__PURE__ */ P(T.Field, {
399
+ name: "valueProperty",
400
+ validators: { onBlur: ({ value: e }) => e.trim() ? void 0 : "Sum meters require a value property." },
401
+ children: (e) => /* @__PURE__ */ F("div", {
402
+ className: "grid gap-1.5",
403
+ children: [
404
+ /* @__PURE__ */ P(j, {
405
+ htmlFor: u("meter-value-property"),
406
+ children: /* @__PURE__ */ P(o, { id: "Value property" })
407
+ }),
408
+ /* @__PURE__ */ P(c, {
409
+ id: u("meter-value-property"),
410
+ value: e.state.value,
411
+ onChange: (t) => e.handleChange(t.target.value),
412
+ onBlur: e.handleBlur,
413
+ placeholder: d("tokens"),
414
+ autoComplete: "off"
415
+ }),
416
+ /* @__PURE__ */ P(v, { errors: e.state.meta.errors })
417
+ ]
418
+ })
419
+ }) : /* @__PURE__ */ P("div", {
420
+ className: "self-end rounded-lg bg-muted/50 px-3 py-2 text-xs text-muted-foreground",
421
+ children: /* @__PURE__ */ P(o, { id: "Count uses one unit for every matching event." })
422
+ })
423
+ })]
424
+ }),
425
+ /* @__PURE__ */ P(T.Field, {
426
+ name: "groupBy",
427
+ mode: "array",
428
+ children: (e) => /* @__PURE__ */ F("fieldset", {
429
+ className: "grid gap-2",
430
+ children: [/* @__PURE__ */ F("div", {
431
+ className: "flex items-center justify-between gap-3",
432
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P(j, { children: /* @__PURE__ */ P(o, { id: "Dimensions" }) }), /* @__PURE__ */ P("p", {
433
+ className: "text-xs text-muted-foreground",
434
+ children: /* @__PURE__ */ P(o, { id: "Register event properties used by filters or matrix rates." })
435
+ })] }), /* @__PURE__ */ F(s, {
436
+ type: "button",
437
+ variant: "outline",
438
+ size: "sm",
439
+ onClick: () => e.pushValue({
440
+ key: "",
441
+ value: ""
442
+ }),
443
+ children: [/* @__PURE__ */ P(I, {
444
+ icon: L,
445
+ className: "size-4"
446
+ }), /* @__PURE__ */ P(o, { id: "Add dimension" })]
447
+ })]
448
+ }), e.state.value.map((t, n) => /* @__PURE__ */ F("div", {
449
+ className: "grid grid-cols-[1fr_1fr_auto] gap-2",
450
+ children: [
451
+ /* @__PURE__ */ P(c, {
452
+ "aria-label": `Dimension ${n + 1} name`,
453
+ value: t.key,
454
+ onChange: (e) => T.setFieldValue(`groupBy[${n}].key`, e.target.value),
455
+ placeholder: d("model"),
456
+ autoComplete: "off"
457
+ }),
458
+ /* @__PURE__ */ P(c, {
459
+ "aria-label": `Dimension ${n + 1} property`,
460
+ value: t.value,
461
+ onChange: (e) => T.setFieldValue(`groupBy[${n}].value`, e.target.value),
462
+ placeholder: d("metadata.model"),
463
+ autoComplete: "off"
464
+ }),
465
+ /* @__PURE__ */ P(s, {
466
+ type: "button",
467
+ variant: "ghost",
468
+ size: "icon",
469
+ "aria-label": `Remove dimension ${n + 1}`,
470
+ onClick: () => e.removeValue(n),
471
+ children: /* @__PURE__ */ P(I, {
472
+ icon: R,
473
+ className: "size-4"
474
+ })
475
+ })
476
+ ]
477
+ }, n))]
478
+ })
479
+ })
480
+ ]
481
+ }),
482
+ m && /* @__PURE__ */ P("p", {
483
+ role: "alert",
484
+ className: "text-sm text-destructive",
485
+ children: m
486
+ }),
487
+ /* @__PURE__ */ F(ie, { children: [/* @__PURE__ */ P(s, {
488
+ type: "button",
489
+ variant: "outline",
490
+ onClick: () => p(!1),
491
+ children: /* @__PURE__ */ P(o, { id: "Cancel" })
492
+ }), /* @__PURE__ */ P(T.Subscribe, {
493
+ selector: (e) => e.isSubmitting,
494
+ children: (e) => /* @__PURE__ */ P(s, {
495
+ type: "submit",
496
+ disabled: e || _.isPending,
497
+ children: e || _.isPending ? "Saving…" : "Save meter"
498
+ })
499
+ })] })
500
+ ]
501
+ })
502
+ })]
503
+ });
504
+ }
505
+ //#endregion
506
+ //#region src/admin/pages/catalog/rate-card-editor.tsx
507
+ var G = M.createContext(null);
508
+ function ze({ meter: t, writesAllowed: n = !1, products: a, productsPending: l = !1, productsError: u = !1, productsForbidden: d = !1 }) {
509
+ let { toast: f, toastApiError: p, adminMutations: m } = r(), { id: h, text: g } = e(), [v, w] = M.useState(!1), [T, E] = M.useState(null), ee = _(), te = he(), D = pe(m.putDefaultUsageRateCard(te)), O = a.filter((e) => !e.archived), k = t.rate_card, ne = D.isPending, A = Se({
510
+ defaultValues: Oe(k),
511
+ onSubmit: async ({ value: e }) => {
512
+ E(null);
513
+ try {
514
+ let t = ke(e);
515
+ if (k && !await ee({
516
+ title: "Replace the default rate?",
517
+ description: "Amounts already charged do not change. New events use the new rate; admitted work keeps its pinned rate.",
518
+ confirmLabel: "Replace rate",
519
+ cancelLabel: "Keep current rate"
520
+ })) return;
521
+ await ue(t);
522
+ } catch (e) {
523
+ if (e instanceof Ce) {
524
+ E({
525
+ fieldId: e.fieldId,
526
+ message: e.message
527
+ }), requestAnimationFrame(() => {
528
+ document.getElementById(h(e.fieldId))?.focus();
529
+ });
530
+ return;
531
+ }
532
+ p(e, "Save rate card");
533
+ }
534
+ }
535
+ }), ue = async (e) => {
536
+ try {
537
+ await D.mutateAsync({
538
+ meter: t,
539
+ rateCard: e
540
+ }), f.success(k ? "Default rate replaced" : "Default rate added"), w(!1);
541
+ } catch (e) {
542
+ p(e, "Save default rate");
543
+ }
544
+ };
545
+ return !n || !t.billing_supported ? null : /* @__PURE__ */ P(G.Provider, {
546
+ value: T,
547
+ children: /* @__PURE__ */ F(le, {
548
+ open: v,
549
+ onOpenChange: (e) => {
550
+ w(e), E(null), e || A.reset();
551
+ },
552
+ children: [/* @__PURE__ */ P(ce, { render: /* @__PURE__ */ F(s, {
553
+ variant: k ? "outline" : "default",
554
+ size: "sm",
555
+ children: [/* @__PURE__ */ P(I, {
556
+ icon: k ? z : be,
557
+ className: "size-4"
558
+ }), k ? "Edit default rate" : "Add default rate"]
559
+ }) }), /* @__PURE__ */ P(ae, {
560
+ className: `${fe} max-h-[calc(100dvh-2rem)] overflow-y-auto`,
561
+ children: /* @__PURE__ */ F("form", {
562
+ className: "grid gap-6",
563
+ onChange: () => E(null),
564
+ onSubmit: (e) => {
565
+ e.preventDefault(), e.stopPropagation(), A.handleSubmit();
566
+ },
567
+ children: [
568
+ /* @__PURE__ */ F(re, { children: [/* @__PURE__ */ P(oe, { children: k ? "Edit default rate" : "Add default rate" }), /* @__PURE__ */ P(se, { children: /* @__PURE__ */ P(o, { id: "Set the price that charges every customer's usage as it is recorded. Money is entered in major currency units." }) })] }),
569
+ /* @__PURE__ */ F("section", {
570
+ className: "grid gap-4",
571
+ children: [/* @__PURE__ */ P("h3", {
572
+ className: "text-sm font-medium",
573
+ children: /* @__PURE__ */ P(o, { id: "Product and model" })
574
+ }), l ? /* @__PURE__ */ P("div", {
575
+ className: "rounded-lg bg-muted/50 p-3 text-sm text-muted-foreground",
576
+ children: /* @__PURE__ */ P(o, { id: "Loading products…" })
577
+ }) : u ? /* @__PURE__ */ P("div", {
578
+ role: "alert",
579
+ className: "rounded-lg bg-muted/50 p-3 text-sm text-destructive",
580
+ children: d ? "Your role cannot read products for this merchant." : "Products could not be loaded. Close this form and try again."
581
+ }) : O.length === 0 ? /* @__PURE__ */ F("div", {
582
+ className: "rounded-lg bg-muted/50 p-3 text-sm",
583
+ children: [/* @__PURE__ */ P("p", { children: /* @__PURE__ */ P(o, { id: "No active products are available." }) }), /* @__PURE__ */ P(i, {
584
+ className: "text-primary underline underline-offset-3",
585
+ to: "/catalog",
586
+ children: /* @__PURE__ */ P(o, { id: "Create or activate a product first" })
587
+ })]
588
+ }) : /* @__PURE__ */ F("div", {
589
+ className: "grid gap-4 sm:grid-cols-3",
590
+ children: [
591
+ /* @__PURE__ */ P(A.Field, {
592
+ name: "productId",
593
+ children: (e) => /* @__PURE__ */ F("div", {
594
+ className: "grid gap-1.5 sm:col-span-2",
595
+ children: [
596
+ /* @__PURE__ */ P(j, {
597
+ htmlFor: h("rate-product"),
598
+ children: /* @__PURE__ */ P(o, { id: "Product" })
599
+ }),
600
+ /* @__PURE__ */ F(C, {
601
+ value: e.state.value || null,
602
+ onValueChange: (t) => e.handleChange(t ?? ""),
603
+ children: [/* @__PURE__ */ P(b, {
604
+ id: h("rate-product"),
605
+ className: "w-full",
606
+ ...Y("rate-product", T),
607
+ children: /* @__PURE__ */ P(y, { placeholder: g("Select product") })
608
+ }), /* @__PURE__ */ P(x, { children: O.map((e) => /* @__PURE__ */ P(S, {
609
+ value: e.id,
610
+ children: e.display_name
611
+ }, e.id)) })]
612
+ }),
613
+ /* @__PURE__ */ P(X, { fieldId: "rate-product" })
614
+ ]
615
+ })
616
+ }),
617
+ /* @__PURE__ */ P(A.Field, {
618
+ name: "currency",
619
+ children: (e) => /* @__PURE__ */ F("div", {
620
+ className: "grid gap-1.5",
621
+ children: [
622
+ /* @__PURE__ */ P(j, {
623
+ htmlFor: h("rate-currency"),
624
+ children: /* @__PURE__ */ P(o, { id: "Currency" })
625
+ }),
626
+ /* @__PURE__ */ P(c, {
627
+ id: h("rate-currency"),
628
+ value: e.state.value,
629
+ onChange: (t) => e.handleChange(t.target.value.toUpperCase()),
630
+ maxLength: 3,
631
+ placeholder: g("USD"),
632
+ className: "uppercase",
633
+ autoComplete: "off",
634
+ ...Y("rate-currency", T)
635
+ }),
636
+ /* @__PURE__ */ P(X, { fieldId: "rate-currency" })
637
+ ]
638
+ })
639
+ }),
640
+ /* @__PURE__ */ P(Be, {
641
+ form: A,
642
+ meter: t
643
+ })
644
+ ]
645
+ })]
646
+ }),
647
+ /* @__PURE__ */ P(A.Subscribe, {
648
+ selector: (e) => e.values.model,
649
+ children: (e) => /* @__PURE__ */ F("section", {
650
+ className: "grid gap-4 border-t pt-5",
651
+ children: [
652
+ /* @__PURE__ */ P("h3", {
653
+ className: "text-sm font-medium",
654
+ children: /* @__PURE__ */ P(o, { id: "Rate" })
655
+ }),
656
+ e === "per_unit" && /* @__PURE__ */ P(Ve, {
657
+ form: A,
658
+ meter: t
659
+ }),
660
+ e === "tiered" && /* @__PURE__ */ P(Ue, { form: A }),
661
+ e === "package" && /* @__PURE__ */ P(We, { form: A }),
662
+ e === "dynamic" && /* @__PURE__ */ P("p", {
663
+ className: "text-sm text-muted-foreground",
664
+ children: /* @__PURE__ */ P(o, { id: "Charge each event’s stated amount when it reports positive units. Missing amounts or zero units charge nothing." })
665
+ })
666
+ ]
667
+ })
668
+ }),
669
+ /* @__PURE__ */ P(Ge, {
670
+ form: A,
671
+ meter: t
672
+ }),
673
+ /* @__PURE__ */ P(A.Subscribe, {
674
+ selector: (e) => e.values.model,
675
+ children: (e) => e !== "dynamic" && /* @__PURE__ */ P(Ke, { form: A })
676
+ }),
677
+ /* @__PURE__ */ P(A.Subscribe, {
678
+ selector: (e) => e.values,
679
+ children: (e) => /* @__PURE__ */ P(qe, { values: e })
680
+ }),
681
+ T && /* @__PURE__ */ P("p", {
682
+ role: "alert",
683
+ className: "text-sm text-destructive",
684
+ children: T.message
685
+ }),
686
+ /* @__PURE__ */ F(ie, { children: [/* @__PURE__ */ P(s, {
687
+ type: "button",
688
+ variant: "outline",
689
+ onClick: () => w(!1),
690
+ children: /* @__PURE__ */ P(o, { id: "Cancel" })
691
+ }), /* @__PURE__ */ P(s, {
692
+ type: "submit",
693
+ disabled: ne || l || u || O.length === 0,
694
+ children: ne ? "Saving…" : k ? "Review replacement" : "Save default rate"
695
+ })] })
696
+ ]
697
+ })
698
+ })]
699
+ })
700
+ });
701
+ }
702
+ function Be({ form: t, meter: n }) {
703
+ let { id: r } = e();
704
+ return /* @__PURE__ */ P(t.Field, {
705
+ name: "model",
706
+ children: (e) => /* @__PURE__ */ F("div", {
707
+ className: "grid gap-1.5 sm:col-span-3",
708
+ children: [/* @__PURE__ */ P(j, {
709
+ htmlFor: r("rate-model"),
710
+ children: /* @__PURE__ */ P(o, { id: "Pricing model" })
711
+ }), /* @__PURE__ */ F(C, {
712
+ value: e.state.value,
713
+ onValueChange: (t) => e.handleChange(t),
714
+ children: [/* @__PURE__ */ P(b, {
715
+ id: r("rate-model"),
716
+ className: "w-full",
717
+ children: /* @__PURE__ */ P(y, {})
718
+ }), /* @__PURE__ */ F(x, { children: [
719
+ /* @__PURE__ */ P(S, {
720
+ value: "per_unit",
721
+ children: /* @__PURE__ */ P(o, { id: "Per unit" })
722
+ }),
723
+ /* @__PURE__ */ P(S, {
724
+ value: "tiered",
725
+ children: /* @__PURE__ */ P(o, { id: "Tiered" })
726
+ }),
727
+ /* @__PURE__ */ P(S, {
728
+ value: "package",
729
+ children: /* @__PURE__ */ P(o, { id: "Package" })
730
+ }),
731
+ /* @__PURE__ */ P(S, {
732
+ value: "dynamic",
733
+ disabled: n.aggregation !== "sum",
734
+ children: /* @__PURE__ */ P(o, { id: "Dynamic (event amount)" })
735
+ })
736
+ ] })]
737
+ })]
738
+ })
739
+ });
740
+ }
741
+ function Ve({ form: t, meter: n }) {
742
+ let { id: r, text: i } = e();
743
+ return /* @__PURE__ */ F(N, { children: [
744
+ /* @__PURE__ */ P(t.Field, {
745
+ name: "matrixEnabled",
746
+ children: (e) => /* @__PURE__ */ F("div", {
747
+ className: "flex items-center justify-between gap-4 rounded-lg bg-muted/50 px-3 py-2.5",
748
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P(j, {
749
+ htmlFor: r("rate-matrix"),
750
+ children: /* @__PURE__ */ P(o, { id: "Use matrix rates" })
751
+ }), /* @__PURE__ */ P("p", {
752
+ className: "text-xs text-muted-foreground",
753
+ children: /* @__PURE__ */ P(o, { id: "Price each value of one registered dimension separately." })
754
+ })] }), /* @__PURE__ */ P(ue, {
755
+ id: r("rate-matrix"),
756
+ checked: e.state.value,
757
+ onCheckedChange: e.handleChange,
758
+ disabled: Object.keys(n.group_by ?? {}).length === 0
759
+ })]
760
+ })
761
+ }),
762
+ /* @__PURE__ */ P(t.Subscribe, {
763
+ selector: (e) => e.values.matrixEnabled,
764
+ children: (e) => e ? /* @__PURE__ */ P(He, {
765
+ form: t,
766
+ meter: n
767
+ }) : /* @__PURE__ */ P(t.Field, {
768
+ name: "unitAmount",
769
+ children: (e) => /* @__PURE__ */ P(q, {
770
+ id: "rate-unit-amount",
771
+ label: i("Price per divisor"),
772
+ value: e.state.value,
773
+ onChange: e.handleChange,
774
+ placeholder: "0.0025"
775
+ })
776
+ })
777
+ }),
778
+ /* @__PURE__ */ F("div", {
779
+ className: "grid gap-4 sm:grid-cols-3",
780
+ children: [
781
+ /* @__PURE__ */ P(t.Field, {
782
+ name: "divideBy",
783
+ children: (e) => /* @__PURE__ */ P(K, {
784
+ id: "rate-divide-by",
785
+ label: i("Divisor"),
786
+ value: e.state.value,
787
+ onChange: e.handleChange,
788
+ inputMode: "numeric",
789
+ placeholder: "1"
790
+ })
791
+ }),
792
+ /* @__PURE__ */ P(t.Field, {
793
+ name: "round",
794
+ children: (e) => /* @__PURE__ */ F("div", {
795
+ className: "grid gap-1.5",
796
+ children: [/* @__PURE__ */ P(j, {
797
+ htmlFor: r("rate-round"),
798
+ children: /* @__PURE__ */ P(o, { id: "Rounding" })
799
+ }), /* @__PURE__ */ F(C, {
800
+ value: e.state.value,
801
+ onValueChange: (t) => e.handleChange(t),
802
+ children: [/* @__PURE__ */ P(b, {
803
+ id: r("rate-round"),
804
+ className: "w-full",
805
+ children: /* @__PURE__ */ P(y, {})
806
+ }), /* @__PURE__ */ F(x, { children: [
807
+ /* @__PURE__ */ P(S, {
808
+ value: "half_up",
809
+ children: /* @__PURE__ */ P(o, { id: "Nearest" })
810
+ }),
811
+ /* @__PURE__ */ P(S, {
812
+ value: "up",
813
+ children: /* @__PURE__ */ P(o, { id: "Up" })
814
+ }),
815
+ /* @__PURE__ */ P(S, {
816
+ value: "down",
817
+ children: /* @__PURE__ */ P(o, { id: "Down" })
818
+ })
819
+ ] })]
820
+ })]
821
+ })
822
+ }),
823
+ /* @__PURE__ */ P(t.Field, {
824
+ name: "maximumAmount",
825
+ children: (e) => /* @__PURE__ */ P(q, {
826
+ id: "rate-maximum",
827
+ label: i("Period maximum"),
828
+ value: e.state.value,
829
+ onChange: e.handleChange,
830
+ placeholder: i("No maximum")
831
+ })
832
+ })
833
+ ]
834
+ })
835
+ ] });
836
+ }
837
+ function He({ form: t, meter: n }) {
838
+ let { id: r, text: i } = e(), a = M.useContext(G);
839
+ return /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ P(t.Field, {
840
+ name: "matrixDimension",
841
+ children: (e) => /* @__PURE__ */ F("div", {
842
+ className: "grid gap-1.5",
843
+ children: [
844
+ /* @__PURE__ */ P(j, {
845
+ htmlFor: r("matrix-dimension"),
846
+ children: /* @__PURE__ */ P(o, { id: "Dimension" })
847
+ }),
848
+ /* @__PURE__ */ F(C, {
849
+ value: e.state.value || null,
850
+ onValueChange: (t) => e.handleChange(t ?? ""),
851
+ children: [/* @__PURE__ */ P(b, {
852
+ id: r("matrix-dimension"),
853
+ className: "w-full",
854
+ ...Y("matrix-dimension", a),
855
+ children: /* @__PURE__ */ P(y, { placeholder: i("Select dimension") })
856
+ }), /* @__PURE__ */ P(x, { children: Object.keys(n.group_by ?? {}).map((e) => /* @__PURE__ */ P(S, {
857
+ value: e,
858
+ children: e
859
+ }, e)) })]
860
+ }),
861
+ /* @__PURE__ */ P(X, { fieldId: "matrix-dimension" })
862
+ ]
863
+ })
864
+ }), /* @__PURE__ */ P(t.Field, {
865
+ name: "matrixCells",
866
+ mode: "array",
867
+ children: (e) => /* @__PURE__ */ F("div", {
868
+ className: "grid gap-2",
869
+ children: [
870
+ /* @__PURE__ */ F("div", {
871
+ className: "flex items-center justify-between gap-3",
872
+ children: [/* @__PURE__ */ P(j, { children: /* @__PURE__ */ P(o, { id: "Matrix cells" }) }), /* @__PURE__ */ F(s, {
873
+ id: r("matrix-add-cell"),
874
+ type: "button",
875
+ variant: "outline",
876
+ size: "sm",
877
+ onClick: () => e.pushValue({
878
+ key: "",
879
+ unitAmount: "",
880
+ maximumAmount: ""
881
+ }),
882
+ children: [/* @__PURE__ */ P(I, {
883
+ icon: L,
884
+ className: "size-4"
885
+ }), /* @__PURE__ */ P(o, { id: "Add cell" })]
886
+ })]
887
+ }),
888
+ /* @__PURE__ */ P(X, { fieldId: "matrix-add-cell" }),
889
+ e.state.value.length > 0 && /* @__PURE__ */ F("div", {
890
+ className: "hidden gap-2 px-0.5 text-xs text-muted-foreground sm:grid sm:grid-cols-[1fr_1fr_1fr_auto]",
891
+ children: [
892
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Value" }) }),
893
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Unit price" }) }),
894
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Maximum" }) }),
895
+ /* @__PURE__ */ P("span", {
896
+ className: "size-8",
897
+ "aria-hidden": "true"
898
+ })
899
+ ]
900
+ }),
901
+ e.state.value.map((n, r) => /* @__PURE__ */ F("div", {
902
+ className: "grid gap-2 sm:grid-cols-[1fr_1fr_1fr_auto]",
903
+ children: [
904
+ /* @__PURE__ */ P(J, {
905
+ id: `matrix-cell-${r}-value`,
906
+ label: i("Value"),
907
+ value: n.key,
908
+ onChange: (e) => t.setFieldValue(`matrixCells[${r}].key`, e),
909
+ placeholder: i("gpt-5")
910
+ }),
911
+ /* @__PURE__ */ P(J, {
912
+ id: `matrix-cell-${r}-unit-price`,
913
+ label: i("Unit price"),
914
+ value: n.unitAmount,
915
+ onChange: (e) => t.setFieldValue(`matrixCells[${r}].unitAmount`, e),
916
+ inputMode: "decimal",
917
+ placeholder: i("Price")
918
+ }),
919
+ /* @__PURE__ */ P(J, {
920
+ id: `matrix-cell-${r}-maximum`,
921
+ label: i("Maximum"),
922
+ value: n.maximumAmount,
923
+ onChange: (e) => t.setFieldValue(`matrixCells[${r}].maximumAmount`, e),
924
+ inputMode: "decimal",
925
+ placeholder: i("Maximum")
926
+ }),
927
+ /* @__PURE__ */ P(Ye, {
928
+ label: `Remove matrix cell ${r + 1}`,
929
+ onClick: () => e.removeValue(r)
930
+ })
931
+ ]
932
+ }, r))
933
+ ]
934
+ })
935
+ })] });
936
+ }
937
+ function Ue({ form: t }) {
938
+ let { id: n, text: r } = e();
939
+ return /* @__PURE__ */ P(N, { children: /* @__PURE__ */ P(t.Field, {
940
+ name: "tiers",
941
+ mode: "array",
942
+ children: (e) => /* @__PURE__ */ F("div", {
943
+ className: "grid gap-2",
944
+ children: [
945
+ /* @__PURE__ */ F("div", {
946
+ className: "flex items-center justify-between gap-3",
947
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P(j, { children: /* @__PURE__ */ P(o, { id: "Tiers" }) }), /* @__PURE__ */ P("p", {
948
+ className: "text-xs text-muted-foreground",
949
+ children: /* @__PURE__ */ P(o, { id: "Leave the final limit blank for the unbounded tier." })
950
+ })] }), /* @__PURE__ */ F(s, {
951
+ id: n("tier-add"),
952
+ type: "button",
953
+ variant: "outline",
954
+ size: "sm",
955
+ onClick: () => e.pushValue({
956
+ upTo: "",
957
+ unitAmount: "",
958
+ flatAmount: ""
959
+ }),
960
+ children: [/* @__PURE__ */ P(I, {
961
+ icon: L,
962
+ className: "size-4"
963
+ }), /* @__PURE__ */ P(o, { id: "Add tier" })]
964
+ })]
965
+ }),
966
+ /* @__PURE__ */ P(X, { fieldId: "tier-add" }),
967
+ e.state.value.length > 0 && /* @__PURE__ */ F("div", {
968
+ className: "hidden gap-2 px-0.5 text-xs text-muted-foreground sm:grid sm:grid-cols-[1fr_1fr_1fr_auto]",
969
+ children: [
970
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Upper limit" }) }),
971
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Unit price" }) }),
972
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Flat amount" }) }),
973
+ /* @__PURE__ */ P("span", {
974
+ className: "size-8",
975
+ "aria-hidden": "true"
976
+ })
977
+ ]
978
+ }),
979
+ e.state.value.map((n, i) => /* @__PURE__ */ F("div", {
980
+ className: "grid gap-2 sm:grid-cols-[1fr_1fr_1fr_auto]",
981
+ children: [
982
+ /* @__PURE__ */ P(J, {
983
+ id: `tier-${i}-limit`,
984
+ label: r("Upper limit"),
985
+ value: n.upTo,
986
+ onChange: (e) => t.setFieldValue(`tiers[${i}].upTo`, e),
987
+ inputMode: "numeric",
988
+ placeholder: i === e.state.value.length - 1 ? "No limit" : "Up to"
989
+ }),
990
+ /* @__PURE__ */ P(J, {
991
+ id: `tier-${i}-unit-price`,
992
+ label: r("Unit price"),
993
+ value: n.unitAmount,
994
+ onChange: (e) => t.setFieldValue(`tiers[${i}].unitAmount`, e),
995
+ inputMode: "decimal",
996
+ placeholder: r("Unit price")
997
+ }),
998
+ /* @__PURE__ */ P(J, {
999
+ id: `tier-${i}-flat-amount`,
1000
+ label: r("Flat amount"),
1001
+ value: n.flatAmount,
1002
+ onChange: (e) => t.setFieldValue(`tiers[${i}].flatAmount`, e),
1003
+ inputMode: "decimal",
1004
+ placeholder: r("Flat amount")
1005
+ }),
1006
+ /* @__PURE__ */ P(Ye, {
1007
+ label: `Remove tier ${i + 1}`,
1008
+ onClick: () => e.removeValue(i),
1009
+ disabled: e.state.value.length === 1
1010
+ })
1011
+ ]
1012
+ }, i))
1013
+ ]
1014
+ })
1015
+ }) });
1016
+ }
1017
+ function We({ form: t }) {
1018
+ let { text: n } = e();
1019
+ return /* @__PURE__ */ F("div", {
1020
+ className: "grid gap-4 sm:grid-cols-3",
1021
+ children: [
1022
+ /* @__PURE__ */ P(t.Field, {
1023
+ name: "packageAmount",
1024
+ children: (e) => /* @__PURE__ */ P(q, {
1025
+ id: "package-amount",
1026
+ label: n("Package price"),
1027
+ value: e.state.value,
1028
+ onChange: e.handleChange,
1029
+ placeholder: "10.00"
1030
+ })
1031
+ }),
1032
+ /* @__PURE__ */ P(t.Field, {
1033
+ name: "packageSize",
1034
+ children: (e) => /* @__PURE__ */ P(K, {
1035
+ id: "package-size",
1036
+ label: n("Units per package"),
1037
+ value: e.state.value,
1038
+ onChange: e.handleChange,
1039
+ inputMode: "numeric",
1040
+ placeholder: "1000"
1041
+ })
1042
+ }),
1043
+ /* @__PURE__ */ P(t.Field, {
1044
+ name: "freeUnits",
1045
+ children: (e) => /* @__PURE__ */ P(K, {
1046
+ id: "package-free",
1047
+ label: n("Free units"),
1048
+ value: e.state.value,
1049
+ onChange: e.handleChange,
1050
+ inputMode: "numeric",
1051
+ placeholder: "0"
1052
+ })
1053
+ })
1054
+ ]
1055
+ });
1056
+ }
1057
+ function Ge({ form: t, meter: n }) {
1058
+ let { id: r, text: i } = e(), a = M.useContext(G);
1059
+ return /* @__PURE__ */ F("section", {
1060
+ className: "grid gap-3 border-t pt-5",
1061
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h3", {
1062
+ className: "text-sm font-medium",
1063
+ children: /* @__PURE__ */ P(o, { id: "Event filters" })
1064
+ }), /* @__PURE__ */ P("p", {
1065
+ className: "text-xs text-muted-foreground",
1066
+ children: /* @__PURE__ */ P(o, { id: "Optional. Only events with one of the listed dimension values are rated." })
1067
+ })] }), /* @__PURE__ */ P(t.Field, {
1068
+ name: "filters",
1069
+ mode: "array",
1070
+ children: (e) => /* @__PURE__ */ F("div", {
1071
+ className: "grid gap-2",
1072
+ children: [
1073
+ e.state.value.length > 0 && /* @__PURE__ */ F("div", {
1074
+ className: "hidden gap-2 px-0.5 text-xs text-muted-foreground sm:grid sm:grid-cols-[1fr_2fr_auto]",
1075
+ children: [
1076
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Dimension" }) }),
1077
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Values" }) }),
1078
+ /* @__PURE__ */ P("span", {
1079
+ className: "size-8",
1080
+ "aria-hidden": "true"
1081
+ })
1082
+ ]
1083
+ }),
1084
+ e.state.value.map((s, c) => /* @__PURE__ */ F("div", {
1085
+ className: "grid gap-2 sm:grid-cols-[1fr_2fr_auto]",
1086
+ children: [
1087
+ /* @__PURE__ */ F("div", {
1088
+ className: "grid gap-1.5",
1089
+ children: [
1090
+ /* @__PURE__ */ P(j, {
1091
+ htmlFor: r(`filter-${c}-dimension`),
1092
+ className: "text-xs text-muted-foreground sm:sr-only",
1093
+ children: /* @__PURE__ */ P(o, { id: "Dimension" })
1094
+ }),
1095
+ /* @__PURE__ */ F(C, {
1096
+ value: s.key || null,
1097
+ onValueChange: (e) => t.setFieldValue(`filters[${c}].key`, e ?? ""),
1098
+ children: [/* @__PURE__ */ P(b, {
1099
+ id: r(`filter-${c}-dimension`),
1100
+ className: "w-full",
1101
+ ...Y(`filter-${c}-dimension`, a),
1102
+ children: /* @__PURE__ */ P(y, { placeholder: i("Dimension") })
1103
+ }), /* @__PURE__ */ P(x, { children: Object.keys(n.group_by ?? {}).map((e) => /* @__PURE__ */ P(S, {
1104
+ value: e,
1105
+ children: e
1106
+ }, e)) })]
1107
+ }),
1108
+ /* @__PURE__ */ P(X, { fieldId: `filter-${c}-dimension` })
1109
+ ]
1110
+ }),
1111
+ /* @__PURE__ */ P(J, {
1112
+ id: `filter-${c}-values`,
1113
+ label: i("Values"),
1114
+ value: s.value,
1115
+ onChange: (e) => t.setFieldValue(`filters[${c}].value`, e),
1116
+ placeholder: i("eu, us")
1117
+ }),
1118
+ /* @__PURE__ */ P(Ye, {
1119
+ label: `Remove filter ${c + 1}`,
1120
+ onClick: () => e.removeValue(c)
1121
+ })
1122
+ ]
1123
+ }, c)),
1124
+ /* @__PURE__ */ F(s, {
1125
+ type: "button",
1126
+ variant: "outline",
1127
+ size: "sm",
1128
+ className: "w-fit",
1129
+ disabled: Object.keys(n.group_by ?? {}).length === 0,
1130
+ onClick: () => e.pushValue({
1131
+ key: "",
1132
+ value: ""
1133
+ }),
1134
+ children: [/* @__PURE__ */ P(I, {
1135
+ icon: L,
1136
+ className: "size-4"
1137
+ }), /* @__PURE__ */ P(o, { id: "Add filter" })]
1138
+ })
1139
+ ]
1140
+ })
1141
+ })]
1142
+ });
1143
+ }
1144
+ function Ke({ form: t }) {
1145
+ let { id: n, text: r } = e();
1146
+ return /* @__PURE__ */ F("section", {
1147
+ className: "grid gap-4 border-t pt-5",
1148
+ children: [
1149
+ /* @__PURE__ */ P("h3", {
1150
+ className: "text-sm font-medium",
1151
+ children: /* @__PURE__ */ P(o, { id: "Allowance" })
1152
+ }),
1153
+ /* @__PURE__ */ P(t.Field, {
1154
+ name: "allowanceMode",
1155
+ children: (e) => /* @__PURE__ */ F("div", {
1156
+ className: "grid gap-1.5",
1157
+ children: [/* @__PURE__ */ P(j, {
1158
+ htmlFor: n("allowance-mode"),
1159
+ children: /* @__PURE__ */ P(o, { id: "Included usage" })
1160
+ }), /* @__PURE__ */ F(C, {
1161
+ value: e.state.value,
1162
+ onValueChange: (t) => e.handleChange(t),
1163
+ children: [/* @__PURE__ */ P(b, {
1164
+ id: n("allowance-mode"),
1165
+ className: "w-full",
1166
+ children: /* @__PURE__ */ P(y, {})
1167
+ }), /* @__PURE__ */ F(x, { children: [/* @__PURE__ */ P(S, {
1168
+ value: "none",
1169
+ children: /* @__PURE__ */ P(o, { id: "No allowance" })
1170
+ }), /* @__PURE__ */ P(S, {
1171
+ value: "included",
1172
+ children: /* @__PURE__ */ P(o, { id: "Fixed included units" })
1173
+ })] })]
1174
+ })]
1175
+ })
1176
+ }),
1177
+ /* @__PURE__ */ P(t.Subscribe, {
1178
+ selector: (e) => e.values.allowanceMode,
1179
+ children: (e) => e === "included" ? /* @__PURE__ */ P(t.Field, {
1180
+ name: "allowanceIncluded",
1181
+ children: (e) => /* @__PURE__ */ P(K, {
1182
+ id: "allowance-included",
1183
+ label: r("Included units per period"),
1184
+ value: e.state.value,
1185
+ onChange: e.handleChange,
1186
+ inputMode: "numeric",
1187
+ placeholder: "1000"
1188
+ })
1189
+ }) : null
1190
+ })
1191
+ ]
1192
+ });
1193
+ }
1194
+ function qe({ values: e }) {
1195
+ let t = "Complete the required fields to preview this rate.";
1196
+ try {
1197
+ let n = ke(e);
1198
+ t = Ie({ price: n.price }), n.allowance?.included !== void 0 && (t += ` · ${n.allowance.included.toLocaleString()} included`);
1199
+ } catch {}
1200
+ return /* @__PURE__ */ F("section", {
1201
+ className: "rounded-lg bg-muted/50 px-3 py-2.5",
1202
+ "aria-live": "polite",
1203
+ children: [/* @__PURE__ */ P("p", {
1204
+ className: "text-xs font-medium text-muted-foreground",
1205
+ children: /* @__PURE__ */ P(o, { id: "Rate preview" })
1206
+ }), /* @__PURE__ */ P("p", {
1207
+ className: "mt-1 text-sm font-medium tabular-nums",
1208
+ children: t
1209
+ })]
1210
+ });
1211
+ }
1212
+ function K({ id: t, label: n, value: r, onChange: i, placeholder: a, inputMode: o }) {
1213
+ let { id: s } = e(), l = Je(t);
1214
+ return /* @__PURE__ */ F("div", {
1215
+ className: "grid gap-1.5",
1216
+ children: [
1217
+ /* @__PURE__ */ P(j, {
1218
+ htmlFor: s(t),
1219
+ children: n
1220
+ }),
1221
+ /* @__PURE__ */ P(c, {
1222
+ id: s(t),
1223
+ value: r,
1224
+ onChange: (e) => i(e.target.value),
1225
+ placeholder: a,
1226
+ inputMode: o,
1227
+ autoComplete: "off",
1228
+ ...Y(t, l ? {
1229
+ fieldId: t,
1230
+ message: l
1231
+ } : null)
1232
+ }),
1233
+ /* @__PURE__ */ P(X, { fieldId: t })
1234
+ ]
1235
+ });
1236
+ }
1237
+ function q(e) {
1238
+ return /* @__PURE__ */ P(K, {
1239
+ ...e,
1240
+ inputMode: "decimal"
1241
+ });
1242
+ }
1243
+ function J({ id: t, label: n, value: r, onChange: i, placeholder: a, inputMode: o }) {
1244
+ let { id: s } = e(), l = Je(t);
1245
+ return /* @__PURE__ */ F("div", {
1246
+ className: "grid gap-1.5",
1247
+ children: [
1248
+ /* @__PURE__ */ P(j, {
1249
+ htmlFor: s(t),
1250
+ className: "text-xs text-muted-foreground sm:sr-only",
1251
+ children: n
1252
+ }),
1253
+ /* @__PURE__ */ P(c, {
1254
+ id: s(t),
1255
+ value: r,
1256
+ onChange: (e) => i(e.target.value),
1257
+ placeholder: a,
1258
+ inputMode: o,
1259
+ autoComplete: "off",
1260
+ ...Y(t, l ? {
1261
+ fieldId: t,
1262
+ message: l
1263
+ } : null)
1264
+ }),
1265
+ /* @__PURE__ */ P(X, { fieldId: t })
1266
+ ]
1267
+ });
1268
+ }
1269
+ function Je(e) {
1270
+ let t = M.useContext(G);
1271
+ return t?.fieldId === e ? t.message : void 0;
1272
+ }
1273
+ function Y(e, t) {
1274
+ let n = t?.fieldId === e;
1275
+ return {
1276
+ "aria-invalid": n || void 0,
1277
+ "aria-describedby": n ? `${e}-error` : void 0
1278
+ };
1279
+ }
1280
+ function X({ fieldId: t }) {
1281
+ let { id: n } = e(), r = Je(t);
1282
+ return r ? /* @__PURE__ */ P("p", {
1283
+ id: n(`${t}-error`),
1284
+ className: "text-xs text-destructive",
1285
+ children: r
1286
+ }) : null;
1287
+ }
1288
+ function Ye({ label: e, onClick: t, disabled: n }) {
1289
+ return /* @__PURE__ */ P(s, {
1290
+ type: "button",
1291
+ variant: "ghost",
1292
+ size: "icon",
1293
+ "aria-label": e,
1294
+ onClick: t,
1295
+ disabled: n,
1296
+ className: "self-end",
1297
+ children: /* @__PURE__ */ P(I, {
1298
+ icon: R,
1299
+ className: "size-4"
1300
+ })
1301
+ });
1302
+ }
1303
+ //#endregion
1304
+ //#region src/admin/pages/catalog/metering.tsx
1305
+ var Xe = 200;
1306
+ function Ze() {
1307
+ let { text: n } = e(), { adminQueries: i } = r(), [a, l] = M.useState(""), d = T("", Xe), { data: f, isPending: p, error: m, refetch: h } = me(i.usageMeters(d.size, d.cursor)), g = u(), _ = f?.data ?? [], v = a.trim().toLowerCase(), y = v ? _.filter((e) => [
1308
+ e.key,
1309
+ e.event_type,
1310
+ e.aggregation,
1311
+ e.unit,
1312
+ e.rate_card?.product_key
1313
+ ].some((e) => e?.toLowerCase().includes(v))) : _, b = we({
1314
+ pending: p,
1315
+ error: m instanceof t ? m : m ? { status: 500 } : null,
1316
+ count: _.length
1317
+ });
1318
+ return /* @__PURE__ */ F("div", {
1319
+ className: "flex min-w-0 flex-col gap-5",
1320
+ children: [
1321
+ /* @__PURE__ */ F("div", {
1322
+ className: "flex flex-wrap items-start justify-between gap-4",
1323
+ children: [/* @__PURE__ */ F("div", {
1324
+ className: "max-w-2xl",
1325
+ children: [/* @__PURE__ */ P("h1", {
1326
+ className: "text-2xl font-semibold tracking-tight text-balance",
1327
+ children: /* @__PURE__ */ P(o, { id: "Metering" })
1328
+ }), /* @__PURE__ */ P("p", {
1329
+ className: "mt-1 text-sm text-pretty text-muted-foreground",
1330
+ children: /* @__PURE__ */ P(o, { id: "Define usage streams and the default rates charged when usage is recorded. Applications report the events separately." })
1331
+ })]
1332
+ }), g && b !== "permission" && /* @__PURE__ */ P(Re, { writesAllowed: !0 })]
1333
+ }),
1334
+ f && !g && /* @__PURE__ */ P(Q, { children: /* @__PURE__ */ P(o, { id: "Catalog updates are disabled. Meter definitions and rates are visible here; changes require the host operator." }) }),
1335
+ b === "loading" ? /* @__PURE__ */ P(tt, {}) : b === "permission" ? /* @__PURE__ */ P($, {
1336
+ title: n("Metering access is restricted"),
1337
+ description: n("Your role does not have permission to read the merchant catalog.")
1338
+ }) : b === "error" ? /* @__PURE__ */ P($, {
1339
+ title: n("Metering could not be loaded"),
1340
+ description: n("Try again. If the problem continues, check the OpenRails API logs."),
1341
+ action: /* @__PURE__ */ P(s, {
1342
+ variant: "outline",
1343
+ size: "sm",
1344
+ onClick: () => void h(),
1345
+ children: /* @__PURE__ */ P(o, { id: "Try again" })
1346
+ })
1347
+ }) : b === "empty" ? /* @__PURE__ */ P($, {
1348
+ title: n("No usage meters yet"),
1349
+ description: n("Create a meter to describe the events your application will report and bill."),
1350
+ action: g ? /* @__PURE__ */ P(Re, { writesAllowed: !0 }) : void 0
1351
+ }) : /* @__PURE__ */ F(N, { children: [
1352
+ /* @__PURE__ */ F("div", {
1353
+ className: "relative w-full sm:max-w-xs",
1354
+ children: [/* @__PURE__ */ P(I, {
1355
+ icon: xe,
1356
+ className: "absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
1357
+ }), /* @__PURE__ */ P(c, {
1358
+ value: a,
1359
+ onChange: (e) => l(e.target.value),
1360
+ className: "pl-8",
1361
+ placeholder: n("Filter this page…"),
1362
+ "aria-label": n("Filter meters on this page")
1363
+ })]
1364
+ }),
1365
+ /* @__PURE__ */ P("div", {
1366
+ className: "max-w-full overflow-x-auto",
1367
+ children: /* @__PURE__ */ F(k, { children: [/* @__PURE__ */ P(te, { children: /* @__PURE__ */ F(O, {
1368
+ className: "hover:bg-transparent",
1369
+ children: [
1370
+ /* @__PURE__ */ P(E, {
1371
+ className: "text-muted-foreground",
1372
+ children: /* @__PURE__ */ P(o, { id: "Meter" })
1373
+ }),
1374
+ /* @__PURE__ */ P(E, {
1375
+ className: "text-muted-foreground",
1376
+ children: /* @__PURE__ */ P(o, { id: "Event" })
1377
+ }),
1378
+ /* @__PURE__ */ P(E, {
1379
+ className: "text-muted-foreground",
1380
+ children: /* @__PURE__ */ P(o, { id: "Aggregation" })
1381
+ }),
1382
+ /* @__PURE__ */ P(E, {
1383
+ className: "text-muted-foreground",
1384
+ children: /* @__PURE__ */ P(o, { id: "Default price" })
1385
+ }),
1386
+ /* @__PURE__ */ P(E, {
1387
+ className: "text-muted-foreground",
1388
+ children: /* @__PURE__ */ P(o, { id: "Product" })
1389
+ }),
1390
+ /* @__PURE__ */ P(E, {
1391
+ className: "text-muted-foreground",
1392
+ children: /* @__PURE__ */ P(o, { id: "Activity" })
1393
+ }),
1394
+ /* @__PURE__ */ P(E, {
1395
+ className: "text-muted-foreground",
1396
+ children: /* @__PURE__ */ P(o, { id: "Last event" })
1397
+ }),
1398
+ /* @__PURE__ */ P(E, { children: /* @__PURE__ */ P("span", {
1399
+ className: "sr-only",
1400
+ children: /* @__PURE__ */ P(o, { id: "Open" })
1401
+ }) })
1402
+ ]
1403
+ }) }), /* @__PURE__ */ F(ee, { children: [y.map((e) => /* @__PURE__ */ P(Qe, { meter: e }, e.key)), y.length === 0 && /* @__PURE__ */ P(O, { children: /* @__PURE__ */ F(D, {
1404
+ colSpan: 9,
1405
+ className: "h-24 text-center text-muted-foreground",
1406
+ children: [
1407
+ /* @__PURE__ */ P(o, { id: "No meters on this page match “" }),
1408
+ a,
1409
+ "”."
1410
+ ]
1411
+ }) })] })] })
1412
+ }),
1413
+ /* @__PURE__ */ P(w, {
1414
+ pages: d,
1415
+ rows: f?.data?.length ?? 0,
1416
+ nextCursor: f?.next_cursor,
1417
+ busy: p,
1418
+ sizes: [
1419
+ 100,
1420
+ 200,
1421
+ 500
1422
+ ]
1423
+ })
1424
+ ] })
1425
+ ]
1426
+ });
1427
+ }
1428
+ function Qe({ meter: e }) {
1429
+ return /* @__PURE__ */ F(ne, {
1430
+ to: `/catalog/metering/${encodeURIComponent(e.key)}`,
1431
+ children: [
1432
+ /* @__PURE__ */ F(D, { children: [/* @__PURE__ */ P(i, {
1433
+ className: "font-medium underline-offset-3 hover:underline",
1434
+ to: `/catalog/metering/${encodeURIComponent(e.key)}`,
1435
+ children: e.key
1436
+ }), e.unit && /* @__PURE__ */ P("p", {
1437
+ className: "text-xs text-muted-foreground",
1438
+ children: e.unit
1439
+ })] }),
1440
+ /* @__PURE__ */ P(D, { children: e.event_type }),
1441
+ /* @__PURE__ */ P(D, { children: /* @__PURE__ */ P(A, {
1442
+ variant: "secondary",
1443
+ children: e.aggregation
1444
+ }) }),
1445
+ /* @__PURE__ */ P(D, {
1446
+ className: "font-medium tabular-nums",
1447
+ children: Ie(e.rate_card)
1448
+ }),
1449
+ /* @__PURE__ */ P(D, { children: e.rate_card?.product_key ?? "—" }),
1450
+ /* @__PURE__ */ P(D, { children: /* @__PURE__ */ F("span", {
1451
+ className: "inline-flex items-center gap-1.5 text-sm",
1452
+ children: [/* @__PURE__ */ P("span", { className: `size-1.5 rounded-full ${e.has_activity ? "bg-settled" : "bg-muted-foreground/50"}` }), e.has_activity ? "Active" : "No events"]
1453
+ }) }),
1454
+ /* @__PURE__ */ P(D, {
1455
+ className: "text-muted-foreground tabular-nums",
1456
+ children: h(e.last_event_at)
1457
+ }),
1458
+ /* @__PURE__ */ P(D, {
1459
+ className: "text-right",
1460
+ children: /* @__PURE__ */ P(I, {
1461
+ icon: ve,
1462
+ className: "ml-auto size-4 text-muted-foreground"
1463
+ })
1464
+ })
1465
+ ]
1466
+ });
1467
+ }
1468
+ function $e() {
1469
+ let { text: i } = e(), { adminQueries: c } = r(), { key: l = "" } = n(), d = l, f = a(), p = me(c.usageMeter(d)), m = u(), h = me(c.allProducts({ errorAction: "Load products for metering" }));
1470
+ if (p.isPending) return /* @__PURE__ */ P(nt, {});
1471
+ if (p.error) {
1472
+ let e = p.error instanceof t && p.error.status === 404, n = p.error instanceof t && p.error.status === 403;
1473
+ return /* @__PURE__ */ P($, {
1474
+ title: n ? "Metering access is restricted" : e ? "Meter not found" : "Meter could not be loaded",
1475
+ description: n ? "Your role does not have permission to read this meter." : e ? "This meter does not exist in the active merchant catalog." : "Try loading the meter again.",
1476
+ action: n ? void 0 : /* @__PURE__ */ P(s, {
1477
+ variant: "outline",
1478
+ size: "sm",
1479
+ onClick: () => e ? f("/catalog/metering") : void p.refetch(),
1480
+ children: e ? "Back to metering" : "Try again"
1481
+ })
1482
+ });
1483
+ }
1484
+ let g = p.data;
1485
+ if (!g) return null;
1486
+ let _ = Le(g, m);
1487
+ return /* @__PURE__ */ F("div", {
1488
+ className: "flex min-w-0 flex-col gap-8",
1489
+ children: [
1490
+ /* @__PURE__ */ F("header", {
1491
+ className: "flex flex-wrap items-start gap-3",
1492
+ children: [
1493
+ /* @__PURE__ */ P(s, {
1494
+ variant: "ghost",
1495
+ size: "icon",
1496
+ onClick: () => f("/catalog/metering"),
1497
+ "aria-label": i("Back to metering"),
1498
+ children: /* @__PURE__ */ P(I, {
1499
+ icon: _e,
1500
+ className: "size-4"
1501
+ })
1502
+ }),
1503
+ /* @__PURE__ */ F("div", {
1504
+ className: "min-w-0 flex-1",
1505
+ children: [/* @__PURE__ */ F("div", {
1506
+ className: "flex flex-wrap items-center gap-2",
1507
+ children: [/* @__PURE__ */ P("h1", {
1508
+ className: "truncate text-xl font-semibold tracking-tight",
1509
+ children: g.key
1510
+ }), !m && /* @__PURE__ */ P(A, {
1511
+ variant: "secondary",
1512
+ children: /* @__PURE__ */ P(o, { id: "read-only" })
1513
+ })]
1514
+ }), /* @__PURE__ */ F("p", {
1515
+ className: "mt-1 text-sm text-muted-foreground",
1516
+ children: [
1517
+ g.event_type,
1518
+ " · ",
1519
+ g.aggregation,
1520
+ g.unit ? ` · ${g.unit}` : ""
1521
+ ]
1522
+ })]
1523
+ }),
1524
+ /* @__PURE__ */ F("div", {
1525
+ className: "flex flex-wrap gap-2",
1526
+ children: [/* @__PURE__ */ P(Re, {
1527
+ meter: g,
1528
+ writesAllowed: m
1529
+ }), /* @__PURE__ */ P(ze, {
1530
+ meter: g,
1531
+ writesAllowed: m,
1532
+ products: h.data?.data ?? [],
1533
+ productsPending: h.isPending,
1534
+ productsError: !!h.error,
1535
+ productsForbidden: h.error instanceof t && h.error.status === 403
1536
+ })]
1537
+ })
1538
+ ]
1539
+ }),
1540
+ !m && /* @__PURE__ */ P(Q, { children: /* @__PURE__ */ P(o, { id: "Catalog updates are disabled. The console is read-only." }) }),
1541
+ /* @__PURE__ */ F("section", {
1542
+ className: "grid gap-4",
1543
+ children: [
1544
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h2", {
1545
+ className: "text-base font-semibold",
1546
+ children: /* @__PURE__ */ P(o, { id: "Event contract" })
1547
+ }), /* @__PURE__ */ F("p", {
1548
+ className: "mt-1 max-w-3xl text-sm text-pretty text-muted-foreground",
1549
+ children: [
1550
+ /* @__PURE__ */ P(o, { id: "Creating this meter does not send events. The host application must report idempotent usage to" }),
1551
+ " ",
1552
+ /* @__PURE__ */ P("code", {
1553
+ className: "text-foreground",
1554
+ children: /* @__PURE__ */ P(o, { id: "/app/usage-events" })
1555
+ }),
1556
+ /* @__PURE__ */ P(o, { id: " with this shape." })
1557
+ ]
1558
+ })] }),
1559
+ /* @__PURE__ */ F("dl", {
1560
+ className: "grid gap-x-8 gap-y-4 border-y py-4 sm:grid-cols-2 lg:grid-cols-4",
1561
+ children: [
1562
+ /* @__PURE__ */ P(Z, {
1563
+ label: i("Event type"),
1564
+ value: g.event_type
1565
+ }),
1566
+ /* @__PURE__ */ P(Z, {
1567
+ label: i("Aggregation"),
1568
+ value: g.aggregation === "sum" ? `Sum ${g.value_property}` : "Count each event"
1569
+ }),
1570
+ /* @__PURE__ */ P(Z, {
1571
+ label: i("Meter key"),
1572
+ value: g.key
1573
+ }),
1574
+ /* @__PURE__ */ P(Z, {
1575
+ label: i("Billing support"),
1576
+ value: g.billing_supported ? "Supported" : "Read only"
1577
+ }),
1578
+ Object.entries(g.group_by ?? {}).map(([e, t]) => /* @__PURE__ */ P(Z, {
1579
+ label: `Dimension: ${e}`,
1580
+ value: t
1581
+ }, e))
1582
+ ]
1583
+ }),
1584
+ _ && m && /* @__PURE__ */ F("p", {
1585
+ className: "flex items-center gap-2 text-xs text-muted-foreground",
1586
+ children: [/* @__PURE__ */ P(I, {
1587
+ icon: ge,
1588
+ className: "size-4"
1589
+ }), _]
1590
+ })
1591
+ ]
1592
+ }),
1593
+ /* @__PURE__ */ P(et, {
1594
+ meter: g,
1595
+ writesAllowed: m
1596
+ })
1597
+ ]
1598
+ });
1599
+ }
1600
+ function et({ meter: t, writesAllowed: n }) {
1601
+ let { toast: i, toastApiError: a, adminMutations: c } = r(), { text: l } = e(), u = _(), d = he(), f = pe(c.deleteDefaultUsageRateCard(d)), p = t.rate_card, m = async () => {
1602
+ if (await u({
1603
+ title: "Remove the default rate?",
1604
+ description: "New usage for this meter will stop being rated after removal. Billed usage orders and accrued amounts remain unchanged.",
1605
+ confirmLabel: "Remove default",
1606
+ cancelLabel: "Keep rate",
1607
+ tone: "destructive"
1608
+ })) try {
1609
+ await f.mutateAsync(t), i.success("Default rate removed");
1610
+ } catch (e) {
1611
+ a(e, "Remove default rate");
1612
+ }
1613
+ };
1614
+ return /* @__PURE__ */ F("section", {
1615
+ className: "grid gap-4 border-t pt-7",
1616
+ children: [/* @__PURE__ */ F("div", {
1617
+ className: "flex flex-wrap items-start justify-between gap-4",
1618
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h2", {
1619
+ className: "text-base font-semibold",
1620
+ children: /* @__PURE__ */ P(o, { id: "Default rate" })
1621
+ }), /* @__PURE__ */ P("p", {
1622
+ className: "mt-1 text-sm text-muted-foreground",
1623
+ children: /* @__PURE__ */ P(o, { id: "Used for every customer." })
1624
+ })] }), p && n && /* @__PURE__ */ F(s, {
1625
+ variant: "outline",
1626
+ size: "sm",
1627
+ disabled: f.isPending,
1628
+ onClick: () => void m(),
1629
+ children: [/* @__PURE__ */ P(I, {
1630
+ icon: R,
1631
+ className: "size-4"
1632
+ }), f.isPending ? "Removing…" : "Remove default"]
1633
+ })]
1634
+ }), t.billing_supported ? p ? /* @__PURE__ */ F("dl", {
1635
+ className: "grid gap-x-8 gap-y-4 border-y py-4 sm:grid-cols-2 lg:grid-cols-4",
1636
+ children: [
1637
+ /* @__PURE__ */ P(Z, {
1638
+ label: l("Price"),
1639
+ value: Ie(p)
1640
+ }),
1641
+ /* @__PURE__ */ P(Z, {
1642
+ label: l("Product"),
1643
+ value: p.product_key
1644
+ }),
1645
+ /* @__PURE__ */ P(Z, {
1646
+ label: l("Model"),
1647
+ value: p.price.model.replace("_", " ")
1648
+ }),
1649
+ /* @__PURE__ */ P(Z, {
1650
+ label: l("Filter"),
1651
+ value: Object.keys(p.filter ?? {}).length ? Object.entries(p.filter ?? {}).map(([e, t]) => `${e}: ${t.join(", ")}`).join(" · ") : "All matching events"
1652
+ }),
1653
+ /* @__PURE__ */ P(Z, {
1654
+ label: l("Allowance"),
1655
+ value: p.allowance?.included === void 0 ? "None" : `${p.allowance.included.toLocaleString()} included`
1656
+ }),
1657
+ /* @__PURE__ */ P(Z, {
1658
+ label: l("Updated"),
1659
+ value: h(p.updated_at)
1660
+ })
1661
+ ]
1662
+ }) : /* @__PURE__ */ P("p", {
1663
+ className: "border-y py-6 text-sm text-muted-foreground",
1664
+ children: /* @__PURE__ */ P(o, { id: "No default rate. Usage is recorded but is not billed by this meter." })
1665
+ }) : /* @__PURE__ */ P(Q, { children: /* @__PURE__ */ P(o, { id: "This meter uses an aggregation that the billing engine cannot rate." }) })]
1666
+ });
1667
+ }
1668
+ function Z({ label: e, value: t }) {
1669
+ return /* @__PURE__ */ F("div", {
1670
+ className: "min-w-0",
1671
+ children: [/* @__PURE__ */ P("dt", {
1672
+ className: "text-xs text-muted-foreground",
1673
+ children: e
1674
+ }), /* @__PURE__ */ P("dd", {
1675
+ className: "mt-1 text-sm font-medium break-words tabular-nums",
1676
+ children: t || "—"
1677
+ })]
1678
+ });
1679
+ }
1680
+ function Q({ children: e }) {
1681
+ return /* @__PURE__ */ F("div", {
1682
+ className: "flex items-start gap-2 rounded-lg bg-muted/50 px-3 py-2.5 text-sm text-muted-foreground",
1683
+ children: [/* @__PURE__ */ P(I, {
1684
+ icon: ye,
1685
+ className: "mt-0.5 size-4 shrink-0"
1686
+ }), /* @__PURE__ */ P("p", { children: e })]
1687
+ });
1688
+ }
1689
+ function $({ title: e, description: t, action: n }) {
1690
+ return /* @__PURE__ */ F("div", {
1691
+ className: "flex flex-col items-start gap-3 border-y py-10",
1692
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h2", {
1693
+ className: "text-sm font-medium",
1694
+ children: e
1695
+ }), /* @__PURE__ */ P("p", {
1696
+ className: "mt-1 text-sm text-muted-foreground",
1697
+ children: t
1698
+ })] }), n]
1699
+ });
1700
+ }
1701
+ function tt() {
1702
+ return /* @__PURE__ */ F("div", {
1703
+ className: "grid gap-3",
1704
+ children: [/* @__PURE__ */ P(l, { className: "h-8 w-64" }), Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ P(l, { className: "h-11 w-full" }, t))]
1705
+ });
1706
+ }
1707
+ function nt() {
1708
+ return /* @__PURE__ */ F("div", {
1709
+ className: "grid gap-6",
1710
+ children: [
1711
+ /* @__PURE__ */ P(l, { className: "h-10 w-72" }),
1712
+ /* @__PURE__ */ P(l, { className: "h-28 w-full" }),
1713
+ /* @__PURE__ */ P(l, { className: "h-36 w-full" }),
1714
+ /* @__PURE__ */ P(l, { className: "h-40 w-full" })
1715
+ ]
1716
+ });
1717
+ }
1718
+ //#endregion
1719
+ export { Ze as CatalogMeteringPage, $e as MeterDetailPage };
1720
+
1721
+ //# sourceMappingURL=admin-metering-COFcSPQy.js.map