@openrails/billing-ui 0.242.0 → 0.243.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -11
- package/README.md +41 -8
- package/dist/admin/billing-admin.d.ts +3 -0
- package/dist/admin/components/app-sidebar.d.ts +1 -0
- package/dist/admin/components/confirm.d.ts +4 -0
- package/dist/admin/components/cursor-pager.d.ts +8 -0
- package/dist/admin/components/data-table.d.ts +14 -0
- package/dist/admin/components/fact-card.d.ts +5 -0
- package/dist/admin/components/form-field-errors.d.ts +3 -0
- package/dist/admin/components/linked-table-row.d.ts +5 -0
- package/dist/admin/components/logo.d.ts +3 -0
- package/dist/admin/components/no-access.d.ts +3 -0
- package/dist/admin/components/no-merchants.d.ts +1 -0
- package/dist/admin/components/notification-bell.d.ts +2 -0
- package/dist/admin/components/route-error.d.ts +3 -0
- package/dist/admin/components/site-header.d.ts +9 -0
- package/dist/admin/components/status-badge.d.ts +3 -0
- package/dist/admin/components/typed-confirm-dialog.d.ts +11 -0
- package/dist/admin/components/ui/alert-dialog.d.ts +18 -0
- package/dist/admin/components/ui/avatar.d.ts +11 -0
- package/dist/admin/components/ui/badge.d.ts +7 -0
- package/dist/admin/components/ui/breadcrumb.d.ts +10 -0
- package/dist/admin/components/ui/button.d.ts +8 -0
- package/dist/admin/components/ui/card.d.ts +11 -0
- package/dist/admin/components/ui/chart.d.ts +44 -0
- package/dist/admin/components/ui/dialog.d.ts +17 -0
- package/dist/admin/components/ui/dropdown-menu.d.ts +29 -0
- package/dist/admin/components/ui/input.d.ts +3 -0
- package/dist/admin/components/ui/label.d.ts +3 -0
- package/dist/admin/components/ui/select.d.ts +15 -0
- package/dist/admin/components/ui/separator.d.ts +3 -0
- package/dist/admin/components/ui/sheet.d.ts +14 -0
- package/dist/admin/components/ui/sidebar.d.ts +63 -0
- package/dist/admin/components/ui/skeleton.d.ts +2 -0
- package/dist/admin/components/ui/sonner.d.ts +3 -0
- package/dist/admin/components/ui/switch.d.ts +5 -0
- package/dist/admin/components/ui/table.d.ts +10 -0
- package/dist/admin/components/ui/tabs.d.ts +10 -0
- package/dist/admin/components/ui/textarea.d.ts +3 -0
- package/dist/admin/components/ui/tooltip.d.ts +6 -0
- package/dist/admin/context.d.ts +1193 -0
- package/dist/admin/hooks/use-mobile.d.ts +1 -0
- package/dist/admin/index.d.ts +5 -0
- package/dist/admin/layouts/app-layout.d.ts +4 -0
- package/dist/admin/lib/api/client.d.ts +64 -0
- package/dist/admin/lib/api/copilot.d.ts +6 -0
- package/dist/admin/lib/api/credit-endpoints.d.ts +8 -0
- package/dist/admin/lib/api/credit-types.d.ts +9 -0
- package/dist/admin/lib/api/endpoints.d.ts +133 -0
- package/dist/admin/lib/api/index.d.ts +89 -0
- package/dist/admin/lib/api/invoice-profile-endpoints.d.ts +6 -0
- package/dist/admin/lib/api/metrics.d.ts +68 -0
- package/dist/admin/lib/api/order-endpoints.d.ts +21 -0
- package/dist/admin/lib/api/types.d.ts +122 -0
- package/dist/admin/lib/auth.d.ts +6 -0
- package/dist/admin/lib/capabilities.d.ts +13 -0
- package/dist/admin/lib/chunk-error.d.ts +1 -0
- package/dist/admin/lib/confirm.d.ts +11 -0
- package/dist/admin/lib/credit-queries.d.ts +23 -0
- package/dist/admin/lib/csv.d.ts +3 -0
- package/dist/admin/lib/cursor-pages.d.ts +13 -0
- package/dist/admin/lib/dialog-width.d.ts +6 -0
- package/dist/admin/lib/dom.d.ts +1 -0
- package/dist/admin/lib/duration.d.ts +3 -0
- package/dist/admin/lib/format.d.ts +23 -0
- package/dist/admin/lib/mount.d.ts +6 -0
- package/dist/admin/lib/mutations.d.ts +125 -0
- package/dist/admin/lib/order-queries.d.ts +29 -0
- package/dist/admin/lib/queries.d.ts +369 -0
- package/dist/admin/lib/query-client.d.ts +3 -0
- package/dist/admin/lib/toast.d.ts +10 -0
- package/dist/admin/lib/utils.d.ts +2 -0
- package/dist/admin/messages.d.ts +670 -0
- package/dist/admin/navigation.d.ts +14 -0
- package/dist/admin/pages/catalog/application-dialog.d.ts +2 -0
- package/dist/admin/pages/catalog/copilot-panel.d.ts +4 -0
- package/dist/admin/pages/catalog/index.d.ts +4 -0
- package/dist/admin/pages/catalog/meter-form.d.ts +6 -0
- package/dist/admin/pages/catalog/metering-model.d.ts +67 -0
- package/dist/admin/pages/catalog/metering.d.ts +3 -0
- package/dist/admin/pages/catalog/price-detail.d.ts +2 -0
- package/dist/admin/pages/catalog/price-format.d.ts +3 -0
- package/dist/admin/pages/catalog/price-wizard-logic.d.ts +20 -0
- package/dist/admin/pages/catalog/price-wizard.d.ts +10 -0
- package/dist/admin/pages/catalog/psp-links.d.ts +10 -0
- package/dist/admin/pages/catalog/rate-card-editor.d.ts +10 -0
- package/dist/admin/pages/customers/credit-form.d.ts +14 -0
- package/dist/admin/pages/customers/credits.d.ts +5 -0
- package/dist/admin/pages/customers/default-card-badges.d.ts +3 -0
- package/dist/admin/pages/customers/detail.d.ts +5 -0
- package/dist/admin/pages/customers/grant-duration.d.ts +32 -0
- package/dist/admin/pages/customers/index.d.ts +2 -0
- package/dist/admin/pages/customers/invoice-profile-model.d.ts +18 -0
- package/dist/admin/pages/customers/invoice-profile.d.ts +9 -0
- package/dist/admin/pages/dashboard/index.d.ts +2 -0
- package/dist/admin/pages/dashboard/lib.d.ts +48 -0
- package/dist/admin/pages/dashboard/range-picker.d.ts +1 -0
- package/dist/admin/pages/dashboard/range.d.ts +34 -0
- package/dist/admin/pages/dashboard/reports-model.d.ts +29 -0
- package/dist/admin/pages/dashboard/reports.d.ts +2 -0
- package/dist/admin/pages/dashboard/use-range.d.ts +5 -0
- package/dist/admin/pages/dashboard/widget-editor.d.ts +8 -0
- package/dist/admin/pages/dashboard/widget-tile.d.ts +9 -0
- package/dist/admin/pages/dashboard/widget-viz.d.ts +12 -0
- package/dist/admin/pages/ops/index.d.ts +2 -0
- package/dist/admin/pages/orders/detail.d.ts +5 -0
- package/dist/admin/pages/orders/index.d.ts +1 -0
- package/dist/admin/pages/orders/model.d.ts +7 -0
- package/dist/admin/pages/payments/attempts.d.ts +7 -0
- package/dist/admin/pages/payments/detail.d.ts +2 -0
- package/dist/admin/pages/payments/health-model.d.ts +149 -0
- package/dist/admin/pages/payments/health.d.ts +2 -0
- package/dist/admin/pages/payments/index.d.ts +2 -0
- package/dist/admin/pages/settings/configuration-edit.d.ts +9 -0
- package/dist/admin/pages/settings/index.d.ts +9 -0
- package/dist/admin/pages/settings/notifications.d.ts +2 -0
- package/dist/admin/pages/settings/setting-fields.d.ts +20 -0
- package/dist/admin/pages/subscriptions/change-subscription-dialog.d.ts +16 -0
- package/dist/admin/pages/subscriptions/detail.d.ts +2 -0
- package/dist/admin/pages/subscriptions/dunning.d.ts +2 -0
- package/dist/admin/pages/subscriptions/index.d.ts +2 -0
- package/dist/admin/pages/subscriptions/subscription-change-options.d.ts +23 -0
- package/dist/admin/pages/subscriptions/views.d.ts +15 -0
- package/dist/admin/router.d.ts +32 -0
- package/dist/admin/routes.d.ts +5 -0
- package/dist/admin/summary.d.ts +27 -0
- package/dist/admin/theme.d.ts +2 -0
- package/dist/admin/types.d.ts +56 -0
- package/dist/admin/ui-context.d.ts +14 -0
- package/dist/admin-attempts-lAoW-Urd.js +419 -0
- package/dist/admin-attempts-lAoW-Urd.js.map +1 -0
- package/dist/admin-auth-DQGHtt0j.js +14 -0
- package/dist/admin-auth-DQGHtt0j.js.map +1 -0
- package/dist/admin-badge-DR5-1qd8.js +31 -0
- package/dist/admin-badge-DR5-1qd8.js.map +1 -0
- package/dist/admin-button-CTL3DgOt.js +46 -0
- package/dist/admin-button-CTL3DgOt.js.map +1 -0
- package/dist/admin-capabilities-BuigAgtm.js +59 -0
- package/dist/admin-capabilities-BuigAgtm.js.map +1 -0
- package/dist/admin-card-bzAks3-3.js +51 -0
- package/dist/admin-card-bzAks3-3.js.map +1 -0
- package/dist/admin-catalog-CC7I4n0_.js +1189 -0
- package/dist/admin-catalog-CC7I4n0_.js.map +1 -0
- package/dist/admin-confirm-katGq0Qo.js +12 -0
- package/dist/admin-confirm-katGq0Qo.js.map +1 -0
- package/dist/admin-csv-CPoNZj2D.js +16 -0
- package/dist/admin-csv-CPoNZj2D.js.map +1 -0
- package/dist/admin-customers-D8u5gq3M.js +160 -0
- package/dist/admin-customers-D8u5gq3M.js.map +1 -0
- package/dist/admin-dashboard-DqqFjOzq.js +420 -0
- package/dist/admin-dashboard-DqqFjOzq.js.map +1 -0
- package/dist/admin-data-table-qfXLOFmN.js +96 -0
- package/dist/admin-data-table-qfXLOFmN.js.map +1 -0
- package/dist/admin-detail-5aNNvrc0.js +324 -0
- package/dist/admin-detail-5aNNvrc0.js.map +1 -0
- package/dist/admin-detail-7p684Uyc.js +342 -0
- package/dist/admin-detail-7p684Uyc.js.map +1 -0
- package/dist/admin-detail-CGOyqs7s.js +1312 -0
- package/dist/admin-detail-CGOyqs7s.js.map +1 -0
- package/dist/admin-detail-DUAJQg8G.js +710 -0
- package/dist/admin-detail-DUAJQg8G.js.map +1 -0
- package/dist/admin-dialog-BjuKI5Hp.js +88 -0
- package/dist/admin-dialog-BjuKI5Hp.js.map +1 -0
- package/dist/admin-dialog-width-BPrgdYlj.js +6 -0
- package/dist/admin-dialog-width-BPrgdYlj.js.map +1 -0
- package/dist/admin-dom-uMmZzRvU.js +149 -0
- package/dist/admin-dom-uMmZzRvU.js.map +1 -0
- package/dist/admin-dropdown-menu-BW1D_h6s.js +69 -0
- package/dist/admin-dropdown-menu-BW1D_h6s.js.map +1 -0
- package/dist/admin-dunning-B2zgtrOo.js +10 -0
- package/dist/admin-dunning-B2zgtrOo.js.map +1 -0
- package/dist/admin-fact-card-DO_fHosg.js +20 -0
- package/dist/admin-fact-card-DO_fHosg.js.map +1 -0
- package/dist/admin-form-field-errors-hbUMIriS.js +14 -0
- package/dist/admin-form-field-errors-hbUMIriS.js.map +1 -0
- package/dist/admin-format-DoohJ7Fg.js +136 -0
- package/dist/admin-format-DoohJ7Fg.js.map +1 -0
- package/dist/admin-health-B4jN2LwR.js +983 -0
- package/dist/admin-health-B4jN2LwR.js.map +1 -0
- package/dist/admin-input-CcfQfJFN.js +17 -0
- package/dist/admin-input-CcfQfJFN.js.map +1 -0
- package/dist/admin-invoice-profile-model-Cgjy3zV8.js +53 -0
- package/dist/admin-invoice-profile-model-Cgjy3zV8.js.map +1 -0
- package/dist/admin-label-BiEN5cjb.js +15 -0
- package/dist/admin-label-BiEN5cjb.js.map +1 -0
- package/dist/admin-linked-table-row-BsaUruCN.js +26 -0
- package/dist/admin-linked-table-row-BsaUruCN.js.map +1 -0
- package/dist/admin-metering-BGAXbT23.js +1702 -0
- package/dist/admin-metering-BGAXbT23.js.map +1 -0
- package/dist/admin-ops-B3mcr76u.js +217 -0
- package/dist/admin-ops-B3mcr76u.js.map +1 -0
- package/dist/admin-orders-dxC99Idl.js +192 -0
- package/dist/admin-orders-dxC99Idl.js.map +1 -0
- package/dist/admin-payments-Bs7HSfP0.js +246 -0
- package/dist/admin-payments-Bs7HSfP0.js.map +1 -0
- package/dist/admin-price-detail-DRquxpA9.js +482 -0
- package/dist/admin-price-detail-DRquxpA9.js.map +1 -0
- package/dist/admin-price-format-DM1qORWI.js +44 -0
- package/dist/admin-price-format-DM1qORWI.js.map +1 -0
- package/dist/admin-price-wizard-CI7K-2Nz.js +357 -0
- package/dist/admin-price-wizard-CI7K-2Nz.js.map +1 -0
- package/dist/admin-range-picker-Dr2M1EZr.js +192 -0
- package/dist/admin-range-picker-Dr2M1EZr.js.map +1 -0
- package/dist/admin-reports-CywKLiSA.js +320 -0
- package/dist/admin-reports-CywKLiSA.js.map +1 -0
- package/dist/admin-select-DBgprVW6.js +81 -0
- package/dist/admin-select-DBgprVW6.js.map +1 -0
- package/dist/admin-settings-Bmoy95uO.js +1434 -0
- package/dist/admin-settings-Bmoy95uO.js.map +1 -0
- package/dist/admin-skeleton-DsM7crYi.js +14 -0
- package/dist/admin-skeleton-DsM7crYi.js.map +1 -0
- package/dist/admin-status-badge-BFPgo71d.js +38 -0
- package/dist/admin-status-badge-BFPgo71d.js.map +1 -0
- package/dist/admin-subscriptions-CLYc_HEV.js +301 -0
- package/dist/admin-subscriptions-CLYc_HEV.js.map +1 -0
- package/dist/admin-switch-BJUxLCsa.js +20 -0
- package/dist/admin-switch-BJUxLCsa.js.map +1 -0
- package/dist/admin-table-CH9TrXJf.js +61 -0
- package/dist/admin-table-CH9TrXJf.js.map +1 -0
- package/dist/admin-tabs-528FJMjt.js +46 -0
- package/dist/admin-tabs-528FJMjt.js.map +1 -0
- package/dist/admin-textarea-DEz38RaI.js +15 -0
- package/dist/admin-textarea-DEz38RaI.js.map +1 -0
- package/dist/admin-typed-confirm-dialog-DU7m9-O7.js +66 -0
- package/dist/admin-typed-confirm-dialog-DU7m9-O7.js.map +1 -0
- package/dist/admin-utils-BK4Vh1o_.js +1809 -0
- package/dist/admin-utils-BK4Vh1o_.js.map +1 -0
- package/dist/admin-widget-viz-Da48c-Zf.js +581 -0
- package/dist/admin-widget-viz-Da48c-Zf.js.map +1 -0
- package/dist/admin.css +3 -0
- package/dist/admin.js +2164 -0
- package/dist/admin.js.map +1 -0
- package/dist/appearance.d.ts +1 -1
- package/dist/client/generated/error-codes.d.ts +1 -1
- package/dist/client/generated/routes.d.ts +2171 -176
- package/dist/client/generated/wire.d.ts +1273 -0
- package/dist/{hooks-Uiw-zW3H.js → hooks-Ckd8F2JF.js} +7 -7
- package/dist/hooks-Ckd8F2JF.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/lib/{offer-label.d.ts → price-label.d.ts} +1 -1
- package/dist/locales/de.js +1 -1
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/en.d.ts +1 -1
- package/dist/locales/en.js +1 -1
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +1 -1
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/ja.js +1 -1
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +1 -1
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +1 -1
- package/dist/locales/zh.js.map +1 -1
- package/dist/{offers.d.ts → product-list.d.ts} +5 -5
- package/dist/react.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +28 -6
- package/dist/hooks-Uiw-zW3H.js.map +0 -1
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import { E as e, o as t, p as n, r, s as i, w as a } from "./admin-utils-BK4Vh1o_.js";
|
|
2
|
+
import { t as o } from "./admin-button-CTL3DgOt.js";
|
|
3
|
+
import { s } from "./admin-capabilities-BuigAgtm.js";
|
|
4
|
+
import { o as c, u as l } from "./admin-format-DoohJ7Fg.js";
|
|
5
|
+
import { n as u } from "./admin-confirm-katGq0Qo.js";
|
|
6
|
+
import { a as d, n as f, o as p, r as m, s as h, t as g } from "./admin-table-CH9TrXJf.js";
|
|
7
|
+
import { t as _ } from "./admin-badge-DR5-1qd8.js";
|
|
8
|
+
import { n as v, t as y } from "./admin-price-format-DM1qORWI.js";
|
|
9
|
+
import { a as b, i as x, o as S, r as C, t as w } from "./admin-card-bzAks3-3.js";
|
|
10
|
+
import { t as T } from "./admin-price-wizard-CI7K-2Nz.js";
|
|
11
|
+
import { t as E } from "./admin-fact-card-DO_fHosg.js";
|
|
12
|
+
import * as D from "react";
|
|
13
|
+
import { useMutation as O, useQuery as k, useQueryClient as A } from "@tanstack/react-query";
|
|
14
|
+
import { Fragment as j, jsx as M, jsxs as N } from "react/jsx-runtime";
|
|
15
|
+
import { HugeiconsIcon as P } from "@hugeicons/react";
|
|
16
|
+
import { ArrowLeft01Icon as F } from "@hugeicons/core-free-icons";
|
|
17
|
+
//#region src/admin/pages/catalog/psp-links.tsx
|
|
18
|
+
var I = {
|
|
19
|
+
unknown_selector: "That name matches no provider you have set up.",
|
|
20
|
+
ambiguous_selector: "More than one provider on this rail is set up. Name the provider rather than the rail.",
|
|
21
|
+
not_armed: "This provider is not set up here, or it was archived.",
|
|
22
|
+
credentials_missing: "The provider is set up, but the credentials it needs are missing.",
|
|
23
|
+
link_missing: "This price has not been sent to the provider yet.",
|
|
24
|
+
mode_unsupported: "This provider cannot take this kind of payment (one-off or recurring).",
|
|
25
|
+
posture_disarmed: "The provider's credentials failed their test-mode check, so it is switched off.",
|
|
26
|
+
service_unavailable: "The connection to this provider is not running.",
|
|
27
|
+
resolve_failed: "The provider could not be worked out at the time of asking."
|
|
28
|
+
}, L = {
|
|
29
|
+
unknown_selector: "unknown provider",
|
|
30
|
+
ambiguous_selector: "more than one match",
|
|
31
|
+
not_armed: "not set up",
|
|
32
|
+
credentials_missing: "credentials missing",
|
|
33
|
+
link_missing: "not sent to provider",
|
|
34
|
+
mode_unsupported: "cannot take this payment",
|
|
35
|
+
posture_disarmed: "credentials failed check",
|
|
36
|
+
service_unavailable: "connection not running",
|
|
37
|
+
resolve_failed: "could not be worked out"
|
|
38
|
+
};
|
|
39
|
+
function R(e) {
|
|
40
|
+
return e ? L[e] ?? e : "ready";
|
|
41
|
+
}
|
|
42
|
+
function z(e) {
|
|
43
|
+
return e ? I[e] ?? e : "";
|
|
44
|
+
}
|
|
45
|
+
var B = "bg-settled-surface text-settled", V = "bg-held-surface text-held", H = "bg-failed-surface text-failed";
|
|
46
|
+
function U(e) {
|
|
47
|
+
return e === "linked" ? B : e === "error" ? H : V;
|
|
48
|
+
}
|
|
49
|
+
function W(e) {
|
|
50
|
+
switch (e) {
|
|
51
|
+
case "in_sync": return B;
|
|
52
|
+
case "drifted":
|
|
53
|
+
case "missing": return H;
|
|
54
|
+
case "never_synced":
|
|
55
|
+
case "sync_disabled": return V;
|
|
56
|
+
default: return "";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
var G = [
|
|
60
|
+
"price_id",
|
|
61
|
+
"product_id",
|
|
62
|
+
"plan_id",
|
|
63
|
+
"form_name",
|
|
64
|
+
"flex_id",
|
|
65
|
+
"recurring_billing_option_id",
|
|
66
|
+
"lookup_key",
|
|
67
|
+
"provider"
|
|
68
|
+
];
|
|
69
|
+
function K(e) {
|
|
70
|
+
let t = Object.entries(e ?? {}).filter(([e, t]) => e !== "rail" && t !== "");
|
|
71
|
+
return t.sort(([e], [t]) => {
|
|
72
|
+
let n = G.indexOf(e), r = G.indexOf(t);
|
|
73
|
+
return n === r ? e.localeCompare(t) : (n < 0 ? G.length : n) - (r < 0 ? G.length : r);
|
|
74
|
+
}), t;
|
|
75
|
+
}
|
|
76
|
+
function q({ price: e, verifying: t, verified: n, onVerify: r }) {
|
|
77
|
+
let i = Object.entries(e.psps ?? {}).sort(([e], [t]) => e.localeCompare(t));
|
|
78
|
+
return /* @__PURE__ */ N(w, { children: [/* @__PURE__ */ N(b, {
|
|
79
|
+
className: "flex flex-row items-start justify-between gap-2",
|
|
80
|
+
children: [/* @__PURE__ */ N("div", {
|
|
81
|
+
className: "grid gap-1",
|
|
82
|
+
children: [/* @__PURE__ */ M(S, {
|
|
83
|
+
className: "text-sm",
|
|
84
|
+
children: /* @__PURE__ */ M(a, { id: "Payment providers" })
|
|
85
|
+
}), /* @__PURE__ */ M(x, { children: /* @__PURE__ */ M(a, { id: "Which providers this price has been sent to, and whether their copy still matches yours. Publishing the catalog is what sends it; this page only reports. Verify asks each provider what it currently holds, and changes nothing." }) })]
|
|
86
|
+
}), /* @__PURE__ */ M(o, {
|
|
87
|
+
variant: "outline",
|
|
88
|
+
size: "sm",
|
|
89
|
+
disabled: t || !i.length,
|
|
90
|
+
onClick: r,
|
|
91
|
+
children: t ? "Verifying…" : "Verify"
|
|
92
|
+
})]
|
|
93
|
+
}), /* @__PURE__ */ N(C, {
|
|
94
|
+
className: "flex flex-col gap-3",
|
|
95
|
+
children: [
|
|
96
|
+
i.length ? /* @__PURE__ */ M("div", {
|
|
97
|
+
className: "overflow-x-auto",
|
|
98
|
+
children: /* @__PURE__ */ N(g, { children: [/* @__PURE__ */ M(p, { children: /* @__PURE__ */ N(h, {
|
|
99
|
+
className: "hover:bg-transparent",
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ M(d, {
|
|
102
|
+
className: "text-muted-foreground",
|
|
103
|
+
children: /* @__PURE__ */ M(a, { id: "Provider" })
|
|
104
|
+
}),
|
|
105
|
+
/* @__PURE__ */ M(d, {
|
|
106
|
+
className: "text-muted-foreground",
|
|
107
|
+
children: /* @__PURE__ */ M(a, { id: "Rail" })
|
|
108
|
+
}),
|
|
109
|
+
/* @__PURE__ */ M(d, {
|
|
110
|
+
className: "text-muted-foreground",
|
|
111
|
+
children: /* @__PURE__ */ M(a, { id: "Sent" })
|
|
112
|
+
}),
|
|
113
|
+
/* @__PURE__ */ M(d, {
|
|
114
|
+
className: "text-muted-foreground",
|
|
115
|
+
children: /* @__PURE__ */ M(a, { id: "Still matches" })
|
|
116
|
+
}),
|
|
117
|
+
/* @__PURE__ */ M(d, {
|
|
118
|
+
className: "text-muted-foreground",
|
|
119
|
+
children: /* @__PURE__ */ M(a, { id: "Their reference" })
|
|
120
|
+
})
|
|
121
|
+
]
|
|
122
|
+
}) }), /* @__PURE__ */ M(f, { children: i.map(([e, t]) => /* @__PURE__ */ N(h, { children: [
|
|
123
|
+
/* @__PURE__ */ M(m, {
|
|
124
|
+
className: "font-mono text-xs",
|
|
125
|
+
children: e
|
|
126
|
+
}),
|
|
127
|
+
/* @__PURE__ */ M(m, {
|
|
128
|
+
className: "text-xs",
|
|
129
|
+
children: t.ids?.rail ?? "—"
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ N(m, { children: [/* @__PURE__ */ M(_, {
|
|
132
|
+
variant: "secondary",
|
|
133
|
+
className: U(t.status),
|
|
134
|
+
children: t.status
|
|
135
|
+
}), t.message && /* @__PURE__ */ M("p", {
|
|
136
|
+
className: "mt-1 max-w-xs text-xs text-muted-foreground",
|
|
137
|
+
children: t.message
|
|
138
|
+
})] }),
|
|
139
|
+
/* @__PURE__ */ N(m, { children: [/* @__PURE__ */ M(_, {
|
|
140
|
+
variant: "secondary",
|
|
141
|
+
className: W(t.sync_status),
|
|
142
|
+
children: t.sync_status ?? "unknown"
|
|
143
|
+
}), t.drift?.map((e) => /* @__PURE__ */ N("p", {
|
|
144
|
+
className: "mt-1 text-xs text-muted-foreground",
|
|
145
|
+
children: [
|
|
146
|
+
e.field,
|
|
147
|
+
/* @__PURE__ */ M(a, { id: ": yours " }),
|
|
148
|
+
e.openrails_value,
|
|
149
|
+
/* @__PURE__ */ M(a, { id: " · theirs" }),
|
|
150
|
+
" ",
|
|
151
|
+
e.remote_value
|
|
152
|
+
]
|
|
153
|
+
}, e.field))] }),
|
|
154
|
+
/* @__PURE__ */ M(m, {
|
|
155
|
+
className: "font-mono text-xs",
|
|
156
|
+
children: K(t.ids).length ? /* @__PURE__ */ M("div", {
|
|
157
|
+
className: "grid gap-0.5",
|
|
158
|
+
children: K(t.ids).map(([e, t]) => /* @__PURE__ */ N("span", { children: [
|
|
159
|
+
e,
|
|
160
|
+
"=",
|
|
161
|
+
t
|
|
162
|
+
] }, e))
|
|
163
|
+
}) : "—"
|
|
164
|
+
})
|
|
165
|
+
] }, e)) })] })
|
|
166
|
+
}) : /* @__PURE__ */ M("p", {
|
|
167
|
+
className: "text-sm text-muted-foreground",
|
|
168
|
+
children: /* @__PURE__ */ M(a, { id: "This price has not been sent to any provider, so nobody can be charged for it yet." })
|
|
169
|
+
}),
|
|
170
|
+
!!e.pending_manual_actions?.length && /* @__PURE__ */ M("div", {
|
|
171
|
+
className: "border-held/40 rounded-md border p-3 text-xs",
|
|
172
|
+
children: e.pending_manual_actions.map((e) => /* @__PURE__ */ N("p", { children: [
|
|
173
|
+
/* @__PURE__ */ M("span", {
|
|
174
|
+
className: "font-mono",
|
|
175
|
+
children: e.psp
|
|
176
|
+
}),
|
|
177
|
+
": ",
|
|
178
|
+
e.hint || e.action
|
|
179
|
+
] }, `${e.psp}-${e.action}`))
|
|
180
|
+
}),
|
|
181
|
+
!n && !!i.length && /* @__PURE__ */ M("p", {
|
|
182
|
+
className: "text-xs text-muted-foreground",
|
|
183
|
+
children: /* @__PURE__ */ M(a, { id: "Nothing is claimed about the providers' copies until you press Verify." })
|
|
184
|
+
})
|
|
185
|
+
]
|
|
186
|
+
})] });
|
|
187
|
+
}
|
|
188
|
+
function J({ price: e }) {
|
|
189
|
+
let { adminQueries: t } = n(), { data: r, isFetching: i, refetch: s } = k(t.checkoutRouting(e.id)), c = r?.candidates.filter((e) => !e.skip) ?? [];
|
|
190
|
+
return /* @__PURE__ */ N(w, { children: [/* @__PURE__ */ N(b, {
|
|
191
|
+
className: "flex flex-row items-start justify-between gap-2",
|
|
192
|
+
children: [/* @__PURE__ */ N("div", {
|
|
193
|
+
className: "grid gap-1",
|
|
194
|
+
children: [/* @__PURE__ */ M(S, {
|
|
195
|
+
className: "text-sm",
|
|
196
|
+
children: /* @__PURE__ */ M(a, { id: "Can this be bought?" })
|
|
197
|
+
}), /* @__PURE__ */ M(x, { children: /* @__PURE__ */ M(a, { id: "Which provider would take the money if someone bought this right now, and why the others were passed over. This asks the same question a real checkout asks, without starting one." }) })]
|
|
198
|
+
}), /* @__PURE__ */ M(o, {
|
|
199
|
+
variant: "outline",
|
|
200
|
+
size: "sm",
|
|
201
|
+
disabled: i,
|
|
202
|
+
onClick: () => void s(),
|
|
203
|
+
children: i ? "Checking…" : "Re-check"
|
|
204
|
+
})]
|
|
205
|
+
}), /* @__PURE__ */ M(C, {
|
|
206
|
+
className: "flex flex-col gap-3",
|
|
207
|
+
children: r ? /* @__PURE__ */ N(j, { children: [
|
|
208
|
+
/* @__PURE__ */ M("p", {
|
|
209
|
+
className: "text-sm",
|
|
210
|
+
children: r.psp ? /* @__PURE__ */ N(j, { children: [
|
|
211
|
+
/* @__PURE__ */ M(a, { id: "Money for this price would go to" }),
|
|
212
|
+
" ",
|
|
213
|
+
/* @__PURE__ */ M("span", {
|
|
214
|
+
className: "font-medium",
|
|
215
|
+
children: r.psp
|
|
216
|
+
}),
|
|
217
|
+
r.rail && /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M(a, { id: " on " }), r.rail] }),
|
|
218
|
+
"."
|
|
219
|
+
] }) : /* @__PURE__ */ M("span", {
|
|
220
|
+
className: "text-held",
|
|
221
|
+
children: /* @__PURE__ */ M(a, { id: "No provider can take this payment, so nobody can buy this price yet." })
|
|
222
|
+
})
|
|
223
|
+
}),
|
|
224
|
+
r.candidates.length ? /* @__PURE__ */ M("div", {
|
|
225
|
+
className: "overflow-x-auto",
|
|
226
|
+
children: /* @__PURE__ */ N(g, { children: [/* @__PURE__ */ M(p, { children: /* @__PURE__ */ N(h, {
|
|
227
|
+
className: "hover:bg-transparent",
|
|
228
|
+
children: [
|
|
229
|
+
/* @__PURE__ */ M(d, {
|
|
230
|
+
className: "text-muted-foreground",
|
|
231
|
+
children: /* @__PURE__ */ M(a, { id: "Provider" })
|
|
232
|
+
}),
|
|
233
|
+
/* @__PURE__ */ M(d, {
|
|
234
|
+
className: "text-muted-foreground",
|
|
235
|
+
children: /* @__PURE__ */ M(a, { id: "Rail" })
|
|
236
|
+
}),
|
|
237
|
+
/* @__PURE__ */ M(d, {
|
|
238
|
+
className: "text-muted-foreground",
|
|
239
|
+
children: /* @__PURE__ */ M(a, { id: "Outcome" })
|
|
240
|
+
}),
|
|
241
|
+
/* @__PURE__ */ M(d, {
|
|
242
|
+
className: "text-muted-foreground",
|
|
243
|
+
children: /* @__PURE__ */ M(a, { id: "Why" })
|
|
244
|
+
})
|
|
245
|
+
]
|
|
246
|
+
}) }), /* @__PURE__ */ M(f, { children: r.candidates.map((e) => /* @__PURE__ */ N(h, { children: [
|
|
247
|
+
/* @__PURE__ */ N(m, {
|
|
248
|
+
className: "font-mono text-xs",
|
|
249
|
+
children: [e.psp, e.psp === r.psp && /* @__PURE__ */ M(_, {
|
|
250
|
+
variant: "secondary",
|
|
251
|
+
className: `ml-2 ${B}`,
|
|
252
|
+
children: /* @__PURE__ */ M(a, { id: "selected" })
|
|
253
|
+
})]
|
|
254
|
+
}),
|
|
255
|
+
/* @__PURE__ */ M(m, {
|
|
256
|
+
className: "text-xs",
|
|
257
|
+
children: e.rail || "—"
|
|
258
|
+
}),
|
|
259
|
+
/* @__PURE__ */ M(m, { children: /* @__PURE__ */ M(_, {
|
|
260
|
+
variant: "secondary",
|
|
261
|
+
className: e.skip ? V : B,
|
|
262
|
+
children: R(e.skip)
|
|
263
|
+
}) }),
|
|
264
|
+
/* @__PURE__ */ M(m, {
|
|
265
|
+
className: "text-xs text-muted-foreground",
|
|
266
|
+
children: z(e.skip)
|
|
267
|
+
})
|
|
268
|
+
] }, e.psp)) })] })
|
|
269
|
+
}) : /* @__PURE__ */ M("p", {
|
|
270
|
+
className: "text-sm text-muted-foreground",
|
|
271
|
+
children: /* @__PURE__ */ M(a, { id: "There were no providers to consider." })
|
|
272
|
+
}),
|
|
273
|
+
!!r.candidates.length && c.length === 0 && /* @__PURE__ */ M("p", {
|
|
274
|
+
className: "text-xs text-muted-foreground",
|
|
275
|
+
children: /* @__PURE__ */ M(a, { id: "\"Not sent to provider\" is fixed by publishing the catalog. Everything else is fixed under Settings, Payment providers." })
|
|
276
|
+
})
|
|
277
|
+
] }) : /* @__PURE__ */ M("p", {
|
|
278
|
+
className: "text-sm text-muted-foreground",
|
|
279
|
+
children: i ? "Checking…" : "This check could not be run."
|
|
280
|
+
})
|
|
281
|
+
})] });
|
|
282
|
+
}
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/admin/pages/catalog/price-detail.tsx
|
|
285
|
+
function Y(e) {
|
|
286
|
+
let t = e.replace(/\/+$/, "").split("/").at(-1) ?? "";
|
|
287
|
+
try {
|
|
288
|
+
return decodeURIComponent(t);
|
|
289
|
+
} catch {
|
|
290
|
+
return "";
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function X() {
|
|
294
|
+
let { text: u } = e(), { adminQueries: x } = n(), O = Y(t().pathname), A = s(), j = i(), [I, L] = D.useState(!1), { data: R, isPending: z, isFetching: B, refetch: V } = k(x.price(O, {
|
|
295
|
+
verify: I,
|
|
296
|
+
errorAction: "Load price"
|
|
297
|
+
})), { data: H } = k(x.product(R?.product_id)), { data: U } = k(x.priceHistory(R?.id)), { data: W } = k(x.priceMigrations(H?.key, R?.key)), G = W?.data?.[0];
|
|
298
|
+
if (!O) return /* @__PURE__ */ M("p", {
|
|
299
|
+
role: "alert",
|
|
300
|
+
className: "text-sm text-muted-foreground",
|
|
301
|
+
children: "Invalid price URL."
|
|
302
|
+
});
|
|
303
|
+
if (!R) return /* @__PURE__ */ M("p", {
|
|
304
|
+
className: "text-sm text-muted-foreground",
|
|
305
|
+
children: z ? "Loading…" : "Price not found."
|
|
306
|
+
});
|
|
307
|
+
let K = !!G && G.scheduled > 0;
|
|
308
|
+
return /* @__PURE__ */ N("div", {
|
|
309
|
+
className: "flex flex-col gap-4",
|
|
310
|
+
children: [
|
|
311
|
+
/* @__PURE__ */ N("div", {
|
|
312
|
+
className: "flex items-center gap-3",
|
|
313
|
+
children: [
|
|
314
|
+
/* @__PURE__ */ M(o, {
|
|
315
|
+
variant: "ghost",
|
|
316
|
+
size: "icon",
|
|
317
|
+
onClick: () => j(-1),
|
|
318
|
+
"aria-label": u("Back"),
|
|
319
|
+
children: /* @__PURE__ */ M(P, {
|
|
320
|
+
icon: F,
|
|
321
|
+
className: "size-4"
|
|
322
|
+
})
|
|
323
|
+
}),
|
|
324
|
+
/* @__PURE__ */ N("div", { children: [/* @__PURE__ */ N("h2", {
|
|
325
|
+
className: "flex items-center gap-2 text-sm",
|
|
326
|
+
children: [R.id, R.archived && /* @__PURE__ */ M(_, {
|
|
327
|
+
variant: "secondary",
|
|
328
|
+
children: /* @__PURE__ */ M(a, { id: "archived" })
|
|
329
|
+
})]
|
|
330
|
+
}), /* @__PURE__ */ M("p", {
|
|
331
|
+
className: "text-xs text-muted-foreground",
|
|
332
|
+
children: H?.display_name
|
|
333
|
+
})] }),
|
|
334
|
+
/* @__PURE__ */ M("div", {
|
|
335
|
+
className: "ml-auto",
|
|
336
|
+
children: A && /* @__PURE__ */ M(T, {
|
|
337
|
+
price: R,
|
|
338
|
+
productName: H?.display_name ?? "…",
|
|
339
|
+
productKey: H?.key
|
|
340
|
+
})
|
|
341
|
+
})
|
|
342
|
+
]
|
|
343
|
+
}),
|
|
344
|
+
/* @__PURE__ */ N("div", {
|
|
345
|
+
className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-4",
|
|
346
|
+
children: [
|
|
347
|
+
/* @__PURE__ */ M(E, {
|
|
348
|
+
label: u("Product"),
|
|
349
|
+
children: /* @__PURE__ */ M(r, {
|
|
350
|
+
className: "underline-offset-2 hover:underline",
|
|
351
|
+
to: "/catalog",
|
|
352
|
+
children: H?.display_name ?? l(R.product_id, 13)
|
|
353
|
+
})
|
|
354
|
+
}),
|
|
355
|
+
/* @__PURE__ */ M(E, {
|
|
356
|
+
label: u("Amount"),
|
|
357
|
+
children: y(R)
|
|
358
|
+
}),
|
|
359
|
+
/* @__PURE__ */ N(E, {
|
|
360
|
+
label: u("Renews"),
|
|
361
|
+
children: [
|
|
362
|
+
R.currency.toUpperCase(),
|
|
363
|
+
" · ",
|
|
364
|
+
v(R)
|
|
365
|
+
]
|
|
366
|
+
}),
|
|
367
|
+
/* @__PURE__ */ M(E, {
|
|
368
|
+
label: u("Created"),
|
|
369
|
+
children: c(R.created_at)
|
|
370
|
+
})
|
|
371
|
+
]
|
|
372
|
+
}),
|
|
373
|
+
/* @__PURE__ */ M(q, {
|
|
374
|
+
price: R,
|
|
375
|
+
verifying: I && B,
|
|
376
|
+
verified: I,
|
|
377
|
+
onVerify: () => I ? void V() : L(!0)
|
|
378
|
+
}),
|
|
379
|
+
/* @__PURE__ */ M(J, { price: R }),
|
|
380
|
+
/* @__PURE__ */ N(w, { children: [/* @__PURE__ */ M(b, { children: /* @__PURE__ */ M(S, {
|
|
381
|
+
className: "text-sm",
|
|
382
|
+
children: /* @__PURE__ */ M(a, { id: "Price history" })
|
|
383
|
+
}) }), /* @__PURE__ */ M(C, { children: U?.data?.length ? /* @__PURE__ */ N(g, { children: [/* @__PURE__ */ M(p, { children: /* @__PURE__ */ N(h, {
|
|
384
|
+
className: "hover:bg-transparent",
|
|
385
|
+
children: [
|
|
386
|
+
/* @__PURE__ */ M(d, {
|
|
387
|
+
className: "text-muted-foreground",
|
|
388
|
+
children: /* @__PURE__ */ M(a, { id: "Amount" })
|
|
389
|
+
}),
|
|
390
|
+
/* @__PURE__ */ M(d, {
|
|
391
|
+
className: "text-muted-foreground",
|
|
392
|
+
children: /* @__PURE__ */ M(a, { id: "Since" })
|
|
393
|
+
}),
|
|
394
|
+
/* @__PURE__ */ M(d, {
|
|
395
|
+
className: "text-muted-foreground",
|
|
396
|
+
children: /* @__PURE__ */ M(a, { id: "State" })
|
|
397
|
+
}),
|
|
398
|
+
/* @__PURE__ */ M(d, {
|
|
399
|
+
className: "text-muted-foreground",
|
|
400
|
+
children: /* @__PURE__ */ M(a, { id: "Price" })
|
|
401
|
+
})
|
|
402
|
+
]
|
|
403
|
+
}) }), /* @__PURE__ */ M(f, { children: U.data.map((e) => /* @__PURE__ */ N(h, { children: [
|
|
404
|
+
/* @__PURE__ */ M(m, { children: y(e.price) }),
|
|
405
|
+
/* @__PURE__ */ M(m, { children: c(e.effective_at) }),
|
|
406
|
+
/* @__PURE__ */ M(m, { children: e.archived ? /* @__PURE__ */ M(_, {
|
|
407
|
+
variant: "secondary",
|
|
408
|
+
children: /* @__PURE__ */ M(a, { id: "retired" })
|
|
409
|
+
}) : /* @__PURE__ */ M(_, {
|
|
410
|
+
className: "bg-settled-surface text-settled",
|
|
411
|
+
children: /* @__PURE__ */ M(a, { id: "offered" })
|
|
412
|
+
}) }),
|
|
413
|
+
/* @__PURE__ */ M(m, { children: /* @__PURE__ */ M(r, {
|
|
414
|
+
className: "text-xs underline-offset-2 hover:underline",
|
|
415
|
+
to: `/catalog/prices/${encodeURIComponent(e.price.id)}`,
|
|
416
|
+
title: e.price.id,
|
|
417
|
+
children: e.price.id
|
|
418
|
+
}) })
|
|
419
|
+
] }, `${e.price.id}-${e.effective_at}`)) })] }) : /* @__PURE__ */ M("p", {
|
|
420
|
+
className: "text-sm text-muted-foreground",
|
|
421
|
+
children: /* @__PURE__ */ M(a, { id: "No history yet." })
|
|
422
|
+
}) })] }),
|
|
423
|
+
G && /* @__PURE__ */ N(w, { children: [/* @__PURE__ */ N(b, {
|
|
424
|
+
className: "flex flex-row items-center justify-between gap-2",
|
|
425
|
+
children: [/* @__PURE__ */ M(S, {
|
|
426
|
+
className: "text-sm",
|
|
427
|
+
children: K ? "Moving customers to the new price" : "Last move to a new price"
|
|
428
|
+
}), K && /* @__PURE__ */ M(Z, { migrationId: G.id })]
|
|
429
|
+
}), /* @__PURE__ */ N(C, {
|
|
430
|
+
className: "flex flex-col gap-2 text-sm",
|
|
431
|
+
children: [/* @__PURE__ */ N("p", { children: [
|
|
432
|
+
G.applied,
|
|
433
|
+
/* @__PURE__ */ M(a, { id: " of" }),
|
|
434
|
+
" ",
|
|
435
|
+
G.applied + G.scheduled + G.canceled,
|
|
436
|
+
" ",
|
|
437
|
+
/* @__PURE__ */ M(a, { id: "moved" }),
|
|
438
|
+
G.scheduled > 0 && ` · ${G.scheduled} still scheduled`,
|
|
439
|
+
" · effective",
|
|
440
|
+
c(G.effective_at)
|
|
441
|
+
] }), G.skipped > 0 && /* @__PURE__ */ N("p", {
|
|
442
|
+
className: "text-xs text-muted-foreground",
|
|
443
|
+
children: [
|
|
444
|
+
G.skipped,
|
|
445
|
+
/* @__PURE__ */ M(a, { id: " subscription" }),
|
|
446
|
+
G.skipped === 1 ? " was" : "s were",
|
|
447
|
+
/* @__PURE__ */ M(a, { id: " left alone because another change was already scheduled for them." })
|
|
448
|
+
]
|
|
449
|
+
})]
|
|
450
|
+
})] })
|
|
451
|
+
]
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
function Z({ migrationId: e }) {
|
|
455
|
+
let { toast: t, toastApiError: r, adminMutations: i } = n(), a = A(), s = O(i.cancelPriceMigration(a)), c = u();
|
|
456
|
+
return /* @__PURE__ */ M(o, {
|
|
457
|
+
variant: "destructive",
|
|
458
|
+
size: "sm",
|
|
459
|
+
disabled: s.isPending,
|
|
460
|
+
onClick: async () => {
|
|
461
|
+
if (await c({
|
|
462
|
+
title: "Cancel this migration?",
|
|
463
|
+
description: "Subscribers not yet moved stay on their current price. Those already moved stay moved.",
|
|
464
|
+
confirmLabel: "Cancel migration",
|
|
465
|
+
cancelLabel: "Keep migrating",
|
|
466
|
+
tone: "destructive"
|
|
467
|
+
})) try {
|
|
468
|
+
let n = await s.mutateAsync(e);
|
|
469
|
+
t.success(`Canceled ${n.canceled} pending move${n.canceled === 1 ? "" : "s"}. Already-migrated subscribers stay migrated.`);
|
|
470
|
+
let r = n.rail_release_required.length;
|
|
471
|
+
r > 0 && t.warning(`${r} Stripe subscription${r === 1 ? " still carries" : "s still carry"} the move as a Stripe subscription schedule: release it in Stripe, or the price changes at period end.`);
|
|
472
|
+
} catch (e) {
|
|
473
|
+
r(e, "Cancel migration");
|
|
474
|
+
}
|
|
475
|
+
},
|
|
476
|
+
children: s.isPending ? "Canceling…" : "Cancel migration"
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
//#endregion
|
|
480
|
+
export { X as PriceDetailPage };
|
|
481
|
+
|
|
482
|
+
//# sourceMappingURL=admin-price-detail-DRquxpA9.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-price-detail-DRquxpA9.js","names":[],"sources":["../src/admin/pages/catalog/psp-links.tsx","../src/admin/pages/catalog/price-detail.tsx"],"sourcesContent":["import { AdminMessage } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { useQuery } from \"@tanstack/react-query\"\n\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport type { PSPRoutingSkip } from \"#orck/admin/lib/api/types\"\nimport type { PSPLinkState, Price } from \"#orck/client/generated/wire\"\n\n// The catalog is declarative: the provider adapter pushes prices and the\n// read-back reconciliation is alert-only, so this surface displays a price's\n// psp_links and never edits them. It answers two different questions:\n// - Link state (`price.providers`): does OpenRails hold a link for this PSP,\n// and does the remote object still match?\n// - Checkout readiness (the routing preview): would a real checkout land\n// here now? A linked price can still be unroutable (PSP unarmed,\n// credentials missing).\n\n// SKIP_LABELS renders the routing skip vocabulary for operators. Keep the keys\n// in lockstep with internal/db/models/checkout_attempt.go.\nconst SKIP_LABELS: Record<PSPRoutingSkip, string> = {\n unknown_selector: \"That name matches no provider you have set up.\",\n ambiguous_selector:\n \"More than one provider on this rail is set up. Name the provider rather than the rail.\",\n not_armed: \"This provider is not set up here, or it was archived.\",\n credentials_missing:\n \"The provider is set up, but the credentials it needs are missing.\",\n link_missing: \"This price has not been sent to the provider yet.\",\n mode_unsupported:\n \"This provider cannot take this kind of payment (one-off or recurring).\",\n posture_disarmed:\n \"The provider's credentials failed their test-mode check, so it is switched off.\",\n service_unavailable: \"The connection to this provider is not running.\",\n resolve_failed: \"The provider could not be worked out at the time of asking.\",\n}\n\n// The engine names each outcome for its own logs. These are the same outcomes\n// as a sentence you can act on.\nconst SKIP_HEADLINES: Record<PSPRoutingSkip, string> = {\n unknown_selector: \"unknown provider\",\n ambiguous_selector: \"more than one match\",\n not_armed: \"not set up\",\n credentials_missing: \"credentials missing\",\n link_missing: \"not sent to provider\",\n mode_unsupported: \"cannot take this payment\",\n posture_disarmed: \"credentials failed check\",\n service_unavailable: \"connection not running\",\n resolve_failed: \"could not be worked out\",\n}\n\nfunction skipHeadline(skip?: string | null): string {\n if (!skip) return \"ready\"\n return SKIP_HEADLINES[skip as PSPRoutingSkip] ?? skip\n}\n\nfunction skipLabel(skip?: string | null) {\n if (!skip) return \"\"\n return SKIP_LABELS[skip as PSPRoutingSkip] ?? skip\n}\n\nconst OK_BADGE = \"bg-settled-surface text-settled\"\nconst WARN_BADGE = \"bg-held-surface text-held\"\nconst BAD_BADGE = \"bg-failed-surface text-failed\"\n\nfunction linkStatusClass(status: PSPLinkState[\"status\"]) {\n if (status === \"linked\") return OK_BADGE\n if (status === \"error\") return BAD_BADGE\n return WARN_BADGE\n}\n\n// syncStatusClass leaves \"unknown\" neutral, not a warning: nobody has checked\n// yet.\nfunction syncStatusClass(sync?: string) {\n switch (sync) {\n case \"in_sync\":\n return OK_BADGE\n case \"drifted\":\n case \"missing\":\n return BAD_BADGE\n case \"never_synced\":\n case \"sync_disabled\":\n return WARN_BADGE\n default:\n return \"\"\n }\n}\n\n// LINK_ID_ORDER puts the identifying fields first; anything else the adapter\n// stored follows in sorted order. `rail` is pulled out into its own column.\nconst LINK_ID_ORDER = [\n \"price_id\",\n \"product_id\",\n \"plan_id\",\n \"form_name\",\n \"flex_id\",\n \"recurring_billing_option_id\",\n \"lookup_key\",\n \"provider\",\n]\n\nfunction linkEntries(ids?: Record<string, string> | null) {\n const rest = Object.entries(ids ?? {}).filter(\n ([k, v]) => k !== \"rail\" && v !== \"\"\n )\n rest.sort(([a], [b]) => {\n const ia = LINK_ID_ORDER.indexOf(a)\n const ib = LINK_ID_ORDER.indexOf(b)\n if (ia !== ib)\n return (\n (ia < 0 ? LINK_ID_ORDER.length : ia) -\n (ib < 0 ? LINK_ID_ORDER.length : ib)\n )\n return a.localeCompare(b)\n })\n return rest\n}\n\nexport function PSPLinksCard({\n price,\n verifying,\n verified,\n onVerify,\n}: {\n price: Price\n verifying: boolean\n verified: boolean\n onVerify: () => void\n}) {\n const links = Object.entries(price.psps ?? {}).sort(([a], [b]) =>\n a.localeCompare(b)\n )\n return (\n <Card>\n <CardHeader className=\"flex flex-row items-start justify-between gap-2\">\n <div className=\"grid gap-1\">\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Payment providers\"} />\n </CardTitle>\n <CardDescription>\n <AdminMessage\n id={\n \"Which providers this price has been sent to, and whether their copy still matches yours. Publishing the catalog is what sends it; this page only reports. Verify asks each provider what it currently holds, and changes nothing.\"\n }\n />\n </CardDescription>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={verifying || !links.length}\n onClick={onVerify}\n >\n {verifying ? \"Verifying…\" : \"Verify\"}\n </Button>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-3\">\n {!links.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage\n id={\n \"This price has not been sent to any provider, so nobody can be charged for it yet.\"\n }\n />\n </p>\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Provider\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Rail\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Sent\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Still matches\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Their reference\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {links.map(([psp, state]) => (\n <TableRow key={psp}>\n <TableCell className=\"font-mono text-xs\">{psp}</TableCell>\n <TableCell className=\"text-xs\">\n {state.ids?.rail ?? \"—\"}\n </TableCell>\n <TableCell>\n <Badge\n variant=\"secondary\"\n className={linkStatusClass(state.status)}\n >\n {state.status}\n </Badge>\n {state.message && (\n <p className=\"mt-1 max-w-xs text-xs text-muted-foreground\">\n {state.message}\n </p>\n )}\n </TableCell>\n <TableCell>\n <Badge\n variant=\"secondary\"\n className={syncStatusClass(state.sync_status)}\n >\n {state.sync_status ?? \"unknown\"}\n </Badge>\n {state.drift?.map((d) => (\n <p\n key={d.field}\n className=\"mt-1 text-xs text-muted-foreground\"\n >\n {d.field}\n <AdminMessage id={\": yours \"} />\n {d.openrails_value}\n <AdminMessage id={\" · theirs\"} /> {d.remote_value}\n </p>\n ))}\n </TableCell>\n <TableCell className=\"font-mono text-xs\">\n {linkEntries(state.ids).length ? (\n <div className=\"grid gap-0.5\">\n {linkEntries(state.ids).map(([k, v]) => (\n <span key={k}>\n {k}={v}\n </span>\n ))}\n </div>\n ) : (\n \"—\"\n )}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n {!!price.pending_manual_actions?.length && (\n <div className=\"border-held/40 rounded-md border p-3 text-xs\">\n {price.pending_manual_actions.map((a) => (\n <p key={`${a.psp}-${a.action}`}>\n <span className=\"font-mono\">{a.psp}</span>: {a.hint || a.action}\n </p>\n ))}\n </div>\n )}\n {!verified && !!links.length && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n \"Nothing is claimed about the providers' copies until you press Verify.\"\n }\n />\n </p>\n )}\n </CardContent>\n </Card>\n )\n}\n\n// CheckoutReadinessCard answers \"can someone buy this right now, and if not,\n// why?\" with the routing preview, so the console and checkout never disagree.\nexport function CheckoutReadinessCard({ price }: { price: Price }) {\n const { adminQueries } = useAdminServices()\n\n const {\n data: decision,\n isFetching: busy,\n refetch: reload,\n } = useQuery(adminQueries.checkoutRouting(price.id))\n\n const eligible = decision?.candidates.filter((c) => !c.skip) ?? []\n\n return (\n <Card>\n <CardHeader className=\"flex flex-row items-start justify-between gap-2\">\n <div className=\"grid gap-1\">\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Can this be bought?\"} />\n </CardTitle>\n <CardDescription>\n <AdminMessage\n id={\n \"Which provider would take the money if someone bought this right now, and why the others were passed over. This asks the same question a real checkout asks, without starting one.\"\n }\n />\n </CardDescription>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n onClick={() => void reload()}\n >\n {busy ? \"Checking…\" : \"Re-check\"}\n </Button>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-3\">\n {!decision ? (\n <p className=\"text-sm text-muted-foreground\">\n {busy ? \"Checking…\" : \"This check could not be run.\"}\n </p>\n ) : (\n <>\n <p className=\"text-sm\">\n {decision.psp ? (\n <>\n <AdminMessage id={\"Money for this price would go to\"} />{\" \"}\n <span className=\"font-medium\">{decision.psp}</span>\n {decision.rail && (\n <>\n <AdminMessage id={\" on \"} />\n {decision.rail}\n </>\n )}\n .\n </>\n ) : (\n <span className=\"text-held\">\n <AdminMessage\n id={\n \"No provider can take this payment, so nobody can buy this price yet.\"\n }\n />\n </span>\n )}\n </p>\n {!decision.candidates.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"There were no providers to consider.\"} />\n </p>\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Provider\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Rail\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Outcome\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Why\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {decision.candidates.map((c) => (\n <TableRow key={c.psp}>\n <TableCell className=\"font-mono text-xs\">\n {c.psp}\n {c.psp === decision.psp && (\n <Badge\n variant=\"secondary\"\n className={`ml-2 ${OK_BADGE}`}\n >\n <AdminMessage id={\"selected\"} />\n </Badge>\n )}\n </TableCell>\n <TableCell className=\"text-xs\">\n {c.rail || \"—\"}\n </TableCell>\n <TableCell>\n <Badge\n variant=\"secondary\"\n className={c.skip ? WARN_BADGE : OK_BADGE}\n >\n {skipHeadline(c.skip)}\n </Badge>\n </TableCell>\n <TableCell className=\"text-xs text-muted-foreground\">\n {skipLabel(c.skip)}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n {!!decision.candidates.length && eligible.length === 0 && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n '\"Not sent to provider\" is fixed by publishing the catalog. Everything else is fixed under Settings, Payment providers.'\n }\n />\n </p>\n )}\n </>\n )}\n </CardContent>\n </Card>\n )\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport { ArrowLeft01Icon } from \"@hugeicons/core-free-icons\"\nimport * as React from \"react\"\nimport { Link, useLocation, useNavigate } from \"#orck/admin/router\"\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Fact } from \"#orck/admin/components/fact-card\"\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { useConfirm } from \"#orck/admin/lib/confirm\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport { formatDate, shortId } from \"#orck/admin/lib/format\"\n\nimport {\n priceAmountLabel,\n priceIntervalLabel,\n} from \"#orck/admin/pages/catalog/price-format\"\nimport { PriceChangeWizard } from \"#orck/admin/pages/catalog/price-wizard\"\nimport {\n CheckoutReadinessCard,\n PSPLinksCard,\n} from \"#orck/admin/pages/catalog/psp-links\"\nimport { useCatalogWrites } from \"#orck/admin/lib/capabilities\"\n\n// A price ID can contain its own percent-encoded key bytes. Router params\n// decode an inner %2F again; decode the original URL segment exactly once.\nfunction priceIDFromPath(pathname: string): string {\n const segment = pathname.replace(/\\/+$/, \"\").split(\"/\").at(-1) ?? \"\"\n try {\n return decodeURIComponent(segment)\n } catch {\n return \"\"\n }\n}\n\n// PriceDetailPage (#777): the version chain (from the #774 pointer-movement\n// log, with dates) and any pending scheduled migration (progress + cancel)\n// for one price key — the wizard's Step 1 entry point (\"Change price\") also\n// lives here alongside the catalog list row.\nexport function PriceDetailPage() {\n const { text: adminText } = useAdminUI()\n\n const { adminQueries } = useAdminServices()\n\n const id = priceIDFromPath(useLocation().pathname)\n const writesAllowed = useCatalogWrites()\n const navigate = useNavigate()\n // verify (or#812) is opt-in: it makes GET price perform a live retrieve\n // against every attached provider, which is a network round trip per PSP.\n const [verify, setVerify] = React.useState(false)\n const {\n data: price,\n isPending: loading,\n isFetching,\n refetch: reload,\n } = useQuery(adminQueries.price(id, { verify, errorAction: \"Load price\" }))\n const { data: product } = useQuery(adminQueries.product(price?.product_id))\n const { data: history } = useQuery(adminQueries.priceHistory(price?.id))\n const { data: migrations } = useQuery(\n adminQueries.priceMigrations(product?.key, price?.key)\n )\n const latestBatch = migrations?.data?.[0]\n\n if (!id)\n return (\n <p role=\"alert\" className=\"text-sm text-muted-foreground\">\n Invalid price URL.\n </p>\n )\n\n // Only the FIRST load blanks the page; a verify refetch keeps the rendered\n // price in place so the button can show its own in-flight state.\n if (!price)\n return (\n <p className=\"text-sm text-muted-foreground\">\n {loading ? \"Loading…\" : \"Price not found.\"}\n </p>\n )\n\n const isPending = !!latestBatch && latestBatch.scheduled > 0\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => navigate(-1)}\n aria-label={adminText(\"Back\")}\n >\n <HugeiconsIcon icon={ArrowLeft01Icon} className=\"size-4\" />\n </Button>\n <div>\n <h2 className=\"flex items-center gap-2 text-sm\">\n {price.id}\n {price.archived && (\n <Badge variant=\"secondary\">\n <AdminMessage id={\"archived\"} />\n </Badge>\n )}\n </h2>\n <p className=\"text-xs text-muted-foreground\">\n {product?.display_name}\n </p>\n </div>\n <div className=\"ml-auto\">\n {writesAllowed && (\n <PriceChangeWizard\n price={price}\n productName={product?.display_name ?? \"…\"}\n productKey={product?.key}\n />\n )}\n </div>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <Fact label={adminText(\"Product\")}>\n <Link className=\"underline-offset-2 hover:underline\" to={`/catalog`}>\n {product?.display_name ?? shortId(price.product_id, 13)}\n </Link>\n </Fact>\n <Fact label={adminText(\"Amount\")}>{priceAmountLabel(price)}</Fact>\n <Fact label={adminText(\"Renews\")}>\n {price.currency.toUpperCase()} · {priceIntervalLabel(price)}\n </Fact>\n <Fact label={adminText(\"Created\")}>{formatDate(price.created_at)}</Fact>\n </div>\n\n <PSPLinksCard\n price={price}\n verifying={verify && isFetching}\n verified={verify}\n onVerify={() => (verify ? void reload() : setVerify(true))}\n />\n\n <CheckoutReadinessCard price={price} />\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Price history\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {!history?.data?.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"No history yet.\"} />\n </p>\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Amount\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Since\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"State\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Price\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {history.data.map((entry) => (\n <TableRow key={`${entry.price.id}-${entry.effective_at}`}>\n <TableCell>{priceAmountLabel(entry.price)}</TableCell>\n <TableCell>{formatDate(entry.effective_at)}</TableCell>\n <TableCell>\n {entry.archived ? (\n <Badge variant=\"secondary\">\n <AdminMessage id={\"retired\"} />\n </Badge>\n ) : (\n <Badge className=\"bg-settled-surface text-settled\">\n <AdminMessage id={\"offered\"} />\n </Badge>\n )}\n </TableCell>\n <TableCell>\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/catalog/prices/${encodeURIComponent(entry.price.id)}`}\n title={entry.price.id}\n >\n {entry.price.id}\n </Link>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </CardContent>\n </Card>\n\n {latestBatch && (\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between gap-2\">\n <CardTitle className=\"text-sm\">\n {isPending\n ? \"Moving customers to the new price\"\n : \"Last move to a new price\"}\n </CardTitle>\n {isPending && (\n <CancelMigrationButton migrationId={latestBatch.id} />\n )}\n </CardHeader>\n <CardContent className=\"flex flex-col gap-2 text-sm\">\n <p>\n {latestBatch.applied}\n <AdminMessage id={\" of\"} />{\" \"}\n {latestBatch.applied +\n latestBatch.scheduled +\n latestBatch.canceled}{\" \"}\n <AdminMessage id={\"moved\"} />\n {latestBatch.scheduled > 0 &&\n ` · ${latestBatch.scheduled} still scheduled`}\n {\" · effective\"}\n {formatDate(latestBatch.effective_at)}\n </p>\n {latestBatch.skipped > 0 && (\n <p className=\"text-xs text-muted-foreground\">\n {latestBatch.skipped}\n <AdminMessage id={\" subscription\"} />\n {latestBatch.skipped === 1 ? \" was\" : \"s were\"}\n <AdminMessage\n id={\n \" left alone because another change was already scheduled for them.\"\n }\n />\n </p>\n )}\n </CardContent>\n </Card>\n )}\n </div>\n )\n}\n\nfunction CancelMigrationButton({ migrationId }: { migrationId: string }) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const queryClient = useQueryClient()\n const cancelBatch = useMutation(\n adminMutations.cancelPriceMigration(queryClient)\n )\n const confirm = useConfirm()\n return (\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={cancelBatch.isPending}\n onClick={async () => {\n const canceling = await confirm({\n title: \"Cancel this migration?\",\n description:\n \"Subscribers not yet moved stay on their current price. Those already moved stay moved.\",\n confirmLabel: \"Cancel migration\",\n cancelLabel: \"Keep migrating\",\n tone: \"destructive\",\n })\n if (!canceling) return\n try {\n const result = await cancelBatch.mutateAsync(migrationId)\n toast.success(\n `Canceled ${result.canceled} pending move${result.canceled === 1 ? \"\" : \"s\"}. Already-migrated subscribers stay migrated.`\n )\n const release = result.rail_release_required.length\n if (release > 0)\n toast.warning(\n `${release} Stripe subscription${release === 1 ? \" still carries\" : \"s still carry\"} the move as a Stripe subscription schedule: release it in Stripe, or the price changes at period end.`\n )\n } catch (err) {\n toastApiError(err, \"Cancel migration\")\n }\n }}\n >\n {cancelBatch.isPending ? \"Canceling…\" : \"Cancel migration\"}\n </Button>\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { s as e } from "./admin-format-DoohJ7Fg.js";
|
|
2
|
+
//#region src/admin/lib/duration.ts
|
|
3
|
+
var t = [
|
|
4
|
+
[604800, "week"],
|
|
5
|
+
[86400, "day"],
|
|
6
|
+
[3600, "hour"],
|
|
7
|
+
[60, "minute"],
|
|
8
|
+
[1, "second"]
|
|
9
|
+
];
|
|
10
|
+
function n(e, t) {
|
|
11
|
+
return `${e} ${t}${e === 1 ? "" : "s"}`;
|
|
12
|
+
}
|
|
13
|
+
function r(e) {
|
|
14
|
+
if (!Number.isSafeInteger(e) || e <= 0) return n(e, "second");
|
|
15
|
+
let [r, i] = t.find(([t]) => e % t === 0) ?? t[4];
|
|
16
|
+
return n(e / r, i);
|
|
17
|
+
}
|
|
18
|
+
function i(e) {
|
|
19
|
+
return r(e * 3600);
|
|
20
|
+
}
|
|
21
|
+
var a = {
|
|
22
|
+
h: 1,
|
|
23
|
+
d: 24,
|
|
24
|
+
w: 168
|
|
25
|
+
};
|
|
26
|
+
function o(e) {
|
|
27
|
+
let t = /^\s*(\d+)\s*(h|hours?|d|days?|w|weeks?)\s*$/i.exec(e);
|
|
28
|
+
if (!t) return null;
|
|
29
|
+
let n = Number(t[1]) * a[t[2][0].toLowerCase()];
|
|
30
|
+
return Number.isSafeInteger(n) && n > 0 ? n : null;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/admin/pages/catalog/price-format.ts
|
|
34
|
+
function s(e) {
|
|
35
|
+
return e.billing_interval_hours ? `every ${i(e.billing_interval_hours)}` : e.access_duration_hours ? `${i(e.access_duration_hours)} once` : "one-time";
|
|
36
|
+
}
|
|
37
|
+
function c(t) {
|
|
38
|
+
let n = t.customer_amount;
|
|
39
|
+
return n ? `Customer chooses ${e(n.min_amount, t.currency)}–${e(n.max_amount, t.currency)}` : e(t.unit_amount, t.currency);
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { o as i, s as n, i as r, c as t };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=admin-price-format-DM1qORWI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-price-format-DM1qORWI.js","names":[],"sources":["../src/admin/lib/duration.ts","../src/admin/pages/catalog/price-format.ts"],"sourcesContent":["// Durations travel as exact hours or seconds; people read and type them in\n// words. A value is shown in the largest whole unit that divides it.\nconst UNITS: [seconds: number, name: string][] = [\n [604_800, \"week\"],\n [86_400, \"day\"],\n [3_600, \"hour\"],\n [60, \"minute\"],\n [1, \"second\"],\n]\n\nfunction counted(count: number, name: string): string {\n return `${count} ${name}${count === 1 ? \"\" : \"s\"}`\n}\n\n// formatSeconds renders \"1 week\", \"30 days\", \"36 hours\", \"90 minutes\".\nexport function formatSeconds(seconds: number): string {\n if (!Number.isSafeInteger(seconds) || seconds <= 0)\n return counted(seconds, \"second\")\n const [size, name] = UNITS.find(([size]) => seconds % size === 0) ?? UNITS[4]\n return counted(seconds / size, name)\n}\n\nexport function formatHours(hours: number): string {\n return formatSeconds(hours * 3_600)\n}\n\nconst HOURS_PER_UNIT: Record<string, number> = { h: 1, d: 24, w: 168 }\n\n// parseHours reads what the catalog YAML accepts — \"30 days\", \"1 week\",\n// \"12 hours\", or the short \"30d\" — as whole hours; anything else is null.\nexport function parseHours(text: string): number | null {\n const match = /^\\s*(\\d+)\\s*(h|hours?|d|days?|w|weeks?)\\s*$/i.exec(text)\n if (!match) return null\n const hours = Number(match[1]) * HOURS_PER_UNIT[match[2][0].toLowerCase()]\n return Number.isSafeInteger(hours) && hours > 0 ? hours : null\n}\n\n","import type { Price } from \"#orck/client/generated/wire\"\nimport { formatHours } from \"#orck/admin/lib/duration\"\nimport { formatNativeAmount } from \"#orck/admin/lib/format\"\n\n// priceIntervalLabel renders a price's renewal cadence, shared by the catalog\n// list and the price-change wizard.\nexport function priceIntervalLabel(\n price: Pick<Price, \"billing_interval_hours\" | \"access_duration_hours\">\n): string {\n if (price.billing_interval_hours) {\n return `every ${formatHours(price.billing_interval_hours)}`\n }\n if (price.access_duration_hours) {\n return `${formatHours(price.access_duration_hours)} once`\n }\n return \"one-time\"\n}\n\n// A deposit descriptor has no fixed amount: zero is not its purchase price.\nexport function priceAmountLabel(\n price: Pick<Price, \"unit_amount\" | \"currency\" | \"customer_amount\">\n): string {\n const range = price.customer_amount\n if (!range) return formatNativeAmount(price.unit_amount, price.currency)\n return `Customer chooses ${formatNativeAmount(range.min_amount, price.currency)}–${formatNativeAmount(range.max_amount, price.currency)}`\n}\n"],"mappings":";;AAEA,IAAM,IAA2C;CAC/C,CAAC,QAAS,MAAM;CAChB,CAAC,OAAQ,KAAK;CACd,CAAC,MAAO,MAAM;CACd,CAAC,IAAI,QAAQ;CACb,CAAC,GAAG,QAAQ;AACd;AAEA,SAAS,EAAQ,GAAe,GAAsB;CACpD,OAAO,GAAG,EAAM,GAAG,IAAO,MAAU,IAAI,KAAK;AAC/C;AAGA,SAAgB,EAAc,GAAyB;CACrD,IAAI,CAAC,OAAO,cAAc,CAAO,KAAK,KAAW,GAC/C,OAAO,EAAQ,GAAS,QAAQ;CAClC,IAAM,CAAC,GAAM,KAAQ,EAAM,MAAM,CAAC,OAAU,IAAU,MAAS,CAAC,KAAK,EAAM;CAC3E,OAAO,EAAQ,IAAU,GAAM,CAAI;AACrC;AAEA,SAAgB,EAAY,GAAuB;CACjD,OAAO,EAAc,IAAQ,IAAK;AACpC;AAEA,IAAM,IAAyC;CAAE,GAAG;CAAG,GAAG;CAAI,GAAG;AAAI;AAIrE,SAAgB,EAAW,GAA6B;CACtD,IAAM,IAAQ,+CAA+C,KAAK,CAAI;CACtE,IAAI,CAAC,GAAO,OAAO;CACnB,IAAM,IAAQ,OAAO,EAAM,EAAE,IAAI,EAAe,EAAM,EAAE,CAAC,EAAE,CAAC,YAAY;CACxE,OAAO,OAAO,cAAc,CAAK,KAAK,IAAQ,IAAI,IAAQ;AAC5D;;;AC7BA,SAAgB,EACd,GACQ;CAOR,OANI,EAAM,yBACD,SAAS,EAAY,EAAM,sBAAsB,MAEtD,EAAM,wBACD,GAAG,EAAY,EAAM,qBAAqB,EAAE,SAE9C;AACT;AAGA,SAAgB,EACd,GACQ;CACR,IAAM,IAAQ,EAAM;CAEpB,OADK,IACE,oBAAoB,EAAmB,EAAM,YAAY,EAAM,QAAQ,EAAE,GAAG,EAAmB,EAAM,YAAY,EAAM,QAAQ,MADnH,EAAmB,EAAM,aAAa,EAAM,QAAQ;AAEzE"}
|