@lukoweb/apitogo-plugin-dev-portal-billing 0.2.53 → 0.2.56

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 (26) hide show
  1. package/dist/{AccountPlansPage-DvRFe3di.mjs → AccountPlansPage-BuM7fe82.mjs} +14 -10
  2. package/dist/{CheckoutPage-CwSElFUk.mjs → CheckoutPage-BSiADcI6.mjs} +32 -15
  3. package/dist/{ContactSalesPage-q7Dxxtx6.mjs → ContactSalesPage-BqqDmorF.mjs} +4 -11
  4. package/dist/{CredentialsPage-B2jPo6Go.mjs → CredentialsPage-DjNvBBLb.mjs} +28 -19
  5. package/dist/{PricingCard-CKdq1oWn.mjs → PricingCard-DFuQEw7Y.mjs} +10 -4
  6. package/dist/{PricingPage-DnQQfy9L.mjs → PricingPage-SpL81vpd.mjs} +14 -13
  7. package/dist/SubscriptionsPage-CwsBtNld.mjs +274 -0
  8. package/dist/{UsagePage-BF4QgrTc.mjs → UsagePage-Dw5Uepg3.mjs} +61 -19
  9. package/dist/{account-links-D_vS0GJn.mjs → account-links-Drofs-f-.mjs} +1 -1
  10. package/dist/{billing-state-DbU5Lpoz.mjs → billing-state-DBQR2tad.mjs} +1 -1
  11. package/dist/index.d.mts +3 -2
  12. package/dist/index.mjs +25 -23
  13. package/dist/{key-plan-note-DTWeFhn2.mjs → page-state-BLL2JJBc.mjs} +22 -2
  14. package/dist/paths-DaVyTIDJ.mjs +14 -0
  15. package/dist/pending-checkout-DpVaNnTu.mjs +45 -0
  16. package/dist/problem-details-n20-dy3w.mjs +18 -0
  17. package/dist/{useApiKeys-CVgXfUop.mjs → useApiKeys-BOY3vIOr.mjs} +3 -9
  18. package/dist/{useDevPortalApiBaseUrl-BstWzITX.mjs → useDevPortalApiBaseUrl-BiI2jFjU.mjs} +14 -14
  19. package/dist/{useMySubscriptions-BtxAXA1m.mjs → useMySubscriptions-BYVIIWbe.mjs} +2 -2
  20. package/dist/{usePlans-DPGFWcVo.mjs → usePlans-HyhIIuJZ.mjs} +1 -1
  21. package/dist/{useUsage--5sZub3M.mjs → useUsage-B5x9YuKa.mjs} +1 -1
  22. package/package.json +3 -3
  23. package/dist/SubscriptionsPage-msO31jv-.mjs +0 -223
  24. package/dist/paths-ujy9wjVK.mjs +0 -12
  25. /package/dist/{demo-session-rN2Gj4lM.mjs → demo-session-yK9qEqV-.mjs} +0 -0
  26. /package/dist/{pricing-config-02m4dyFf.mjs → pricing-config-Bc6eWFUO.mjs} +0 -0
@@ -1,223 +0,0 @@
1
- import { i as CREDENTIALS_PATH, t as ACCOUNT_PLANS_PATH } from "./paths-ujy9wjVK.mjs";
2
- import { a as formatPlanPrice, p as parseMonthlyQuotaCalls, s as isActiveSubscription, t as useDevPortalApiBaseUrl } from "./useDevPortalApiBaseUrl-BstWzITX.mjs";
3
- import { n as useDevPortalBillingConfig } from "./DevPortalBillingContext-CR83s4LO.mjs";
4
- import { t as useMySubscriptions } from "./useMySubscriptions-BtxAXA1m.mjs";
5
- import { t as usePlans } from "./usePlans-DPGFWcVo.mjs";
6
- import { n as useApiKeys } from "./useApiKeys-CVgXfUop.mjs";
7
- import { t as useUsage } from "./useUsage--5sZub3M.mjs";
8
- import { i as hasPaymentProvider, r as checkoutConfirmingText } from "./billing-state-DbU5Lpoz.mjs";
9
- import { n as ChoosePlanNotice, t as keyPlanNote } from "./key-plan-note-DTWeFhn2.mjs";
10
- import { Head, Spinner } from "@lukoweb/apitogo/components";
11
- import { Link as Link$1, useSearchParams } from "@lukoweb/apitogo/router";
12
- import { useEffect } from "react";
13
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
- import { useMutation } from "@lukoweb/apitogo/react-query";
15
- import { useAuth } from "@lukoweb/apitogo/hooks";
16
- import { Button as Button$1 } from "@lukoweb/apitogo/ui/Button.js";
17
-
18
- //#region src/hooks/useBillingPortal.ts
19
- function useBillingPortal() {
20
- const apiBaseUrl = useDevPortalApiBaseUrl();
21
- return useMutation({ mutationFn: async (returnUrl) => {
22
- if (!apiBaseUrl) throw new Error("Dev portal API is not configured.");
23
- const response = await fetch(`${apiBaseUrl}/api/v1/subscriptions/billing-portal`, {
24
- method: "POST",
25
- headers: {
26
- Accept: "application/json",
27
- "Content-Type": "application/json"
28
- },
29
- credentials: "include",
30
- body: JSON.stringify({ returnUrl: returnUrl ?? `${window.location.origin}/account/subscriptions` })
31
- });
32
- if (!response.ok) throw new Error("Unable to open billing portal.");
33
- const body = await response.json();
34
- if (!body.url) throw new Error("Billing portal URL was not returned.");
35
- window.location.assign(body.url);
36
- } });
37
- }
38
-
39
- //#endregion
40
- //#region src/pages/SubscriptionsPage.tsx
41
- const SubscriptionsPage = () => {
42
- const { billing } = useDevPortalBillingConfig();
43
- const auth = useAuth();
44
- const [searchParams] = useSearchParams();
45
- const checkoutSuccess = searchParams.get("checkout") === "success";
46
- const checkoutPaid = searchParams.get("paid") !== "0";
47
- const { data: me, isLoading, refetch } = useMySubscriptions();
48
- const { data: catalog } = usePlans();
49
- const billingPortal = useBillingPortal();
50
- const { data: usage } = useUsage("30d");
51
- const { data: apiKeys } = useApiKeys();
52
- const planNote = keyPlanNote(apiKeys?.plans ?? []);
53
- const planBySku = new Map((catalog?.plans ?? []).map((plan) => [plan.sku, plan]));
54
- const subscriptions = me?.subscriptions ?? [];
55
- const activeSubscription = subscriptions.find((sub) => isActiveSubscription(sub.status));
56
- const activePlan = activeSubscription ? planBySku.get(activeSubscription.planSku) : void 0;
57
- const confirmingPayment = checkoutSuccess && !isLoading && !activeSubscription;
58
- useEffect(() => {
59
- if (!confirmingPayment) return;
60
- let attempts = 0;
61
- const timer = setInterval(() => {
62
- attempts += 1;
63
- refetch();
64
- if (attempts >= 30) clearInterval(timer);
65
- }, 2e3);
66
- return () => clearInterval(timer);
67
- }, [confirmingPayment, refetch]);
68
- const monthlyQuota = activePlan ? parseMonthlyQuotaCalls(activePlan.limitsJson) : null;
69
- const usedRequests = usage?.requestCount ?? 0;
70
- const quotaPct = monthlyQuota && monthlyQuota > 0 ? Math.min(100, Math.round(usedRequests / monthlyQuota * 100)) : null;
71
- return /* @__PURE__ */ jsxs("div", {
72
- className: "px-8 py-7",
73
- children: [
74
- /* @__PURE__ */ jsx(Head, { children: /* @__PURE__ */ jsx("title", { children: "Billing" }) }),
75
- /* @__PURE__ */ jsx("h1", {
76
- className: "mb-2 text-[1.6rem] font-bold tracking-[-0.01em]",
77
- children: "Billing"
78
- }),
79
- /* @__PURE__ */ jsx("p", {
80
- className: "mb-8 text-muted-foreground",
81
- children: "Manage your plan, payment method, and invoices."
82
- }),
83
- confirmingPayment ? /* @__PURE__ */ jsx("div", {
84
- className: "mb-6 rounded-xl border border-border bg-card p-4 text-sm",
85
- children: checkoutConfirmingText(checkoutPaid)
86
- }) : null,
87
- checkoutSuccess && activeSubscription ? /* @__PURE__ */ jsx("div", {
88
- className: "mb-6 rounded-xl border border-green-500/30 bg-green-500/10 p-4 text-sm",
89
- children: planNote ? /* @__PURE__ */ jsxs(Fragment, { children: [
90
- planNote.text,
91
- " ",
92
- /* @__PURE__ */ jsx(Link$1, {
93
- to: CREDENTIALS_PATH,
94
- className: "font-medium underline",
95
- children: "Create the key"
96
- }),
97
- "."
98
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
99
- "Your subscription is active.",
100
- " ",
101
- /* @__PURE__ */ jsx(Link$1, {
102
- to: CREDENTIALS_PATH,
103
- className: "font-medium underline",
104
- children: "View your API credentials"
105
- }),
106
- "."
107
- ] })
108
- }) : null,
109
- isLoading ? /* @__PURE__ */ jsx("p", {
110
- className: "text-muted-foreground",
111
- children: "Loading billing details…"
112
- }) : null,
113
- !isLoading && activeSubscription ? /* @__PURE__ */ jsxs("div", {
114
- className: "mb-8 rounded-xl border border-border bg-card p-6",
115
- children: [
116
- /* @__PURE__ */ jsx("p", {
117
- className: "text-xs font-medium uppercase tracking-[0.05em] text-muted-foreground",
118
- children: "Current plan"
119
- }),
120
- /* @__PURE__ */ jsx("h2", {
121
- className: "mt-2 text-2xl font-bold",
122
- children: activePlan?.displayName ?? activeSubscription.planSku
123
- }),
124
- activePlan ? /* @__PURE__ */ jsx("p", {
125
- className: "mt-1 text-sm text-muted-foreground",
126
- children: formatPlanPrice(activePlan)
127
- }) : /* @__PURE__ */ jsx("p", {
128
- className: "mt-1 text-sm text-muted-foreground",
129
- children: "This plan is no longer offered. Your access continues until you cancel or change plan."
130
- }),
131
- activeSubscription.currentPeriodEnd ? /* @__PURE__ */ jsxs("p", {
132
- className: "mt-3 text-sm text-muted-foreground",
133
- children: [
134
- "Renews",
135
- " ",
136
- new Date(activeSubscription.currentPeriodEnd).toLocaleDateString()
137
- ]
138
- }) : null,
139
- quotaPct != null && monthlyQuota != null ? /* @__PURE__ */ jsxs("div", {
140
- className: "mt-5",
141
- children: [/* @__PURE__ */ jsxs("div", {
142
- className: "mb-1.5 flex justify-between text-xs text-muted-foreground",
143
- children: [/* @__PURE__ */ jsx("span", { children: "Monthly requests" }), /* @__PURE__ */ jsxs("span", { children: [
144
- usedRequests.toLocaleString(),
145
- " /",
146
- " ",
147
- monthlyQuota.toLocaleString()
148
- ] })]
149
- }), /* @__PURE__ */ jsx("div", {
150
- className: "h-2 rounded-full bg-muted",
151
- children: /* @__PURE__ */ jsx("div", {
152
- className: "h-full rounded-full bg-primary transition-[width]",
153
- style: { width: `${quotaPct}%` }
154
- })
155
- })]
156
- }) : null
157
- ]
158
- }) : null,
159
- !isLoading && subscriptions.length === 0 ? /* @__PURE__ */ jsx(ChoosePlanNotice, {
160
- className: "mb-8 rounded-xl border border-dashed p-8 text-center",
161
- body: "You do not have a plan yet. Choose one to start using the API; your billing details appear here afterwards."
162
- }) : null,
163
- !isLoading && subscriptions.length > 1 ? /* @__PURE__ */ jsx("div", {
164
- className: "mb-8 space-y-4",
165
- children: subscriptions.map((subscription) => {
166
- const plan = planBySku.get(subscription.planSku);
167
- return /* @__PURE__ */ jsx("article", {
168
- className: "rounded-xl border bg-card p-5",
169
- children: /* @__PURE__ */ jsxs("div", {
170
- className: "flex flex-wrap items-start justify-between gap-4",
171
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
172
- className: "font-semibold",
173
- children: plan?.displayName ?? subscription.planSku
174
- }), plan ? /* @__PURE__ */ jsx("p", {
175
- className: "mt-1 text-sm text-muted-foreground",
176
- children: formatPlanPrice(plan)
177
- }) : null] }), /* @__PURE__ */ jsx("span", {
178
- className: "rounded-full bg-muted px-3 py-1 text-xs font-medium text-muted-foreground",
179
- children: subscription.status
180
- })]
181
- })
182
- }, `${subscription.planSku}-${subscription.status}`);
183
- })
184
- }) : null,
185
- /* @__PURE__ */ jsxs("div", {
186
- className: "flex flex-wrap gap-3",
187
- children: [
188
- /* @__PURE__ */ jsx(Button$1, {
189
- variant: "outline",
190
- asChild: true,
191
- children: /* @__PURE__ */ jsx(Link$1, {
192
- to: ACCOUNT_PLANS_PATH,
193
- children: "Change plan"
194
- })
195
- }),
196
- auth.isAuthenticated && hasPaymentProvider(billing) ? /* @__PURE__ */ jsx(Button$1, {
197
- variant: "default",
198
- disabled: billingPortal.isPending,
199
- onClick: () => {
200
- billingPortal.mutate();
201
- },
202
- children: billingPortal.isPending ? /* @__PURE__ */ jsx(Spinner, {}) : "Manage payment & invoices"
203
- }) : null,
204
- auth.isAuthenticated ? /* @__PURE__ */ jsx(Button$1, {
205
- variant: "secondary",
206
- asChild: true,
207
- children: /* @__PURE__ */ jsx(Link$1, {
208
- to: CREDENTIALS_PATH,
209
- children: "API credentials"
210
- })
211
- }) : null
212
- ]
213
- }),
214
- billingPortal.isError ? /* @__PURE__ */ jsx("p", {
215
- className: "mt-4 text-sm text-destructive",
216
- children: billingPortal.error instanceof Error ? billingPortal.error.message : "Unable to open billing portal."
217
- }) : null
218
- ]
219
- });
220
- };
221
-
222
- //#endregion
223
- export { SubscriptionsPage as default };
@@ -1,12 +0,0 @@
1
- //#region src/paths.ts
2
- const PRICING_PATH = "/pricing";
3
- const ACCOUNT_PLANS_PATH = "/account/plans";
4
- const CHECKOUT_PATH = "/checkout";
5
- const CONTACT_SALES_PATH = "/contact-sales";
6
- const SUBSCRIPTIONS_PATH = "/account/subscriptions";
7
- const CREDENTIALS_PATH = "/account/credentials";
8
- const USAGE_PATH = "/account/usage";
9
- const LOGIN_NAV_PATH = "/signin";
10
-
11
- //#endregion
12
- export { LOGIN_NAV_PATH as a, USAGE_PATH as c, CREDENTIALS_PATH as i, CHECKOUT_PATH as n, PRICING_PATH as o, CONTACT_SALES_PATH as r, SUBSCRIPTIONS_PATH as s, ACCOUNT_PLANS_PATH as t };