@omnikit-js/ui 0.9.7 → 0.9.9
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/dist/chunk-2SK6OTCD.js +1049 -0
- package/dist/chunk-2SK6OTCD.js.map +1 -0
- package/dist/{chunk-O6555PUL.js → chunk-JFXMNYII.js} +3 -3
- package/dist/{chunk-O6555PUL.js.map → chunk-JFXMNYII.js.map} +1 -1
- package/dist/components/client/index.d.ts +14 -2
- package/dist/components/client/index.js +5 -49
- package/dist/components/client/index.js.map +1 -1
- package/dist/components/server/index.js +2 -2
- package/dist/index.js +2 -2
- package/package.json +18 -1
- package/dist/chunk-IKBW2JFX.js +0 -471
- package/dist/chunk-IKBW2JFX.js.map +0 -1
|
@@ -0,0 +1,1049 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useState, useMemo } from 'react';
|
|
3
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { loadStripe } from '@stripe/stripe-js';
|
|
5
|
+
import { Elements, useStripe, useElements, PaymentElement } from '@stripe/react-stripe-js';
|
|
6
|
+
import { Card, Button, Tabs } from '@marcoschwartz/lite-ui';
|
|
7
|
+
import { useRouter } from 'next/navigation';
|
|
8
|
+
|
|
9
|
+
// src/components/client/Modal/index.tsx
|
|
10
|
+
function Modal({ isOpen, onClose, title, children, className = "" }) {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const handleEscape = (e) => {
|
|
13
|
+
if (e.key === "Escape") onClose();
|
|
14
|
+
};
|
|
15
|
+
if (isOpen) {
|
|
16
|
+
document.addEventListener("keydown", handleEscape);
|
|
17
|
+
document.body.style.overflow = "hidden";
|
|
18
|
+
}
|
|
19
|
+
return () => {
|
|
20
|
+
document.removeEventListener("keydown", handleEscape);
|
|
21
|
+
document.body.style.overflow = "unset";
|
|
22
|
+
};
|
|
23
|
+
}, [isOpen, onClose]);
|
|
24
|
+
if (!isOpen) return null;
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
26
|
+
/* @__PURE__ */ jsx(
|
|
27
|
+
"div",
|
|
28
|
+
{
|
|
29
|
+
className: "absolute inset-0 bg-black/50 backdrop-blur-sm",
|
|
30
|
+
onClick: onClose
|
|
31
|
+
}
|
|
32
|
+
),
|
|
33
|
+
/* @__PURE__ */ jsxs(
|
|
34
|
+
"div",
|
|
35
|
+
{
|
|
36
|
+
className: `relative bg-white dark:bg-gray-900 rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto ${className}`,
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700", children: [
|
|
39
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold", children: title }),
|
|
40
|
+
/* @__PURE__ */ jsx(
|
|
41
|
+
"button",
|
|
42
|
+
{
|
|
43
|
+
onClick: onClose,
|
|
44
|
+
className: "text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors",
|
|
45
|
+
children: /* @__PURE__ */ jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
] }),
|
|
49
|
+
/* @__PURE__ */ jsx("div", { className: "p-6", children })
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
] });
|
|
54
|
+
}
|
|
55
|
+
function PaymentForm({ customerId, onSuccess, onCancel, onSubmit }) {
|
|
56
|
+
const stripe = useStripe();
|
|
57
|
+
const elements = useElements();
|
|
58
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
59
|
+
const [errorMessage, setErrorMessage] = useState(null);
|
|
60
|
+
const [setAsDefault, setSetAsDefault] = useState(false);
|
|
61
|
+
const handleSubmit = async (e) => {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
if (!stripe || !elements) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
setIsProcessing(true);
|
|
67
|
+
setErrorMessage(null);
|
|
68
|
+
try {
|
|
69
|
+
const { error: submitError } = await elements.submit();
|
|
70
|
+
if (submitError) {
|
|
71
|
+
setErrorMessage(submitError.message || "Failed to validate payment details");
|
|
72
|
+
setIsProcessing(false);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const { error, paymentMethod } = await stripe.createPaymentMethod({
|
|
76
|
+
elements
|
|
77
|
+
});
|
|
78
|
+
if (error) {
|
|
79
|
+
setErrorMessage(error.message || "Failed to create payment method");
|
|
80
|
+
setIsProcessing(false);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const result = await onSubmit(paymentMethod.id, setAsDefault);
|
|
84
|
+
if (!result.success) {
|
|
85
|
+
throw new Error(result.error || "Failed to add payment method");
|
|
86
|
+
}
|
|
87
|
+
onSuccess();
|
|
88
|
+
} catch (error) {
|
|
89
|
+
setErrorMessage(error instanceof Error ? error.message : String(error) || "An error occurred");
|
|
90
|
+
setIsProcessing(false);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
94
|
+
/* @__PURE__ */ jsx(PaymentElement, {}),
|
|
95
|
+
errorMessage && /* @__PURE__ */ jsx("div", { className: "text-red-600 dark:text-red-400 text-sm", children: errorMessage }),
|
|
96
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-2", children: [
|
|
97
|
+
/* @__PURE__ */ jsx(
|
|
98
|
+
"input",
|
|
99
|
+
{
|
|
100
|
+
type: "checkbox",
|
|
101
|
+
id: "setDefault",
|
|
102
|
+
checked: setAsDefault,
|
|
103
|
+
onChange: (e) => setSetAsDefault(e.target.checked),
|
|
104
|
+
className: "w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
/* @__PURE__ */ jsx(
|
|
108
|
+
"label",
|
|
109
|
+
{
|
|
110
|
+
htmlFor: "setDefault",
|
|
111
|
+
className: "text-sm text-gray-600 dark:text-gray-400",
|
|
112
|
+
children: "Set as default payment method"
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
] }),
|
|
116
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
|
|
117
|
+
/* @__PURE__ */ jsx(
|
|
118
|
+
Button,
|
|
119
|
+
{
|
|
120
|
+
type: "button",
|
|
121
|
+
variant: "secondary",
|
|
122
|
+
onClick: onCancel,
|
|
123
|
+
disabled: isProcessing,
|
|
124
|
+
children: "Cancel"
|
|
125
|
+
}
|
|
126
|
+
),
|
|
127
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", variant: "primary", disabled: !stripe || isProcessing, children: isProcessing ? "Processing..." : "Add Payment Method" })
|
|
128
|
+
] })
|
|
129
|
+
] });
|
|
130
|
+
}
|
|
131
|
+
function AddPaymentMethodForm({
|
|
132
|
+
customerId,
|
|
133
|
+
stripePublishableKey,
|
|
134
|
+
onSuccess,
|
|
135
|
+
onCancel,
|
|
136
|
+
onSubmit
|
|
137
|
+
}) {
|
|
138
|
+
const [stripePromise, setStripePromise] = useState(null);
|
|
139
|
+
const [theme, setTheme] = useState("light");
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
if (stripePublishableKey) {
|
|
142
|
+
setStripePromise(loadStripe(stripePublishableKey));
|
|
143
|
+
}
|
|
144
|
+
}, [stripePublishableKey]);
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
const isDark = document.documentElement.classList.contains("dark") || window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
147
|
+
setTheme(isDark ? "dark" : "light");
|
|
148
|
+
const observer = new MutationObserver(() => {
|
|
149
|
+
const isDark2 = document.documentElement.classList.contains("dark");
|
|
150
|
+
setTheme(isDark2 ? "dark" : "light");
|
|
151
|
+
});
|
|
152
|
+
observer.observe(document.documentElement, {
|
|
153
|
+
attributes: true,
|
|
154
|
+
attributeFilter: ["class"]
|
|
155
|
+
});
|
|
156
|
+
return () => observer.disconnect();
|
|
157
|
+
}, []);
|
|
158
|
+
const stripeOptions = useMemo(() => ({
|
|
159
|
+
mode: "setup",
|
|
160
|
+
currency: "usd",
|
|
161
|
+
paymentMethodCreation: "manual",
|
|
162
|
+
appearance: {
|
|
163
|
+
theme: theme === "dark" ? "night" : "stripe",
|
|
164
|
+
variables: {
|
|
165
|
+
colorPrimary: "#3b82f6",
|
|
166
|
+
colorBackground: theme === "dark" ? "#1f2937" : "#ffffff",
|
|
167
|
+
colorText: theme === "dark" ? "#f9fafb" : "#1f2937",
|
|
168
|
+
colorDanger: "#ef4444",
|
|
169
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
170
|
+
spacingUnit: "4px",
|
|
171
|
+
borderRadius: "6px"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}), [theme]);
|
|
175
|
+
if (!stripePromise) {
|
|
176
|
+
return /* @__PURE__ */ jsx("div", { className: "text-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: "Loading..." }) });
|
|
177
|
+
}
|
|
178
|
+
return /* @__PURE__ */ jsx(Elements, { stripe: stripePromise, options: stripeOptions, children: /* @__PURE__ */ jsx(
|
|
179
|
+
PaymentForm,
|
|
180
|
+
{
|
|
181
|
+
customerId,
|
|
182
|
+
onSuccess,
|
|
183
|
+
onCancel,
|
|
184
|
+
onSubmit
|
|
185
|
+
}
|
|
186
|
+
) });
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/components/server/Billing/actions.ts
|
|
190
|
+
function createHeaders(config) {
|
|
191
|
+
const headers = {
|
|
192
|
+
"Content-Type": "application/json"
|
|
193
|
+
};
|
|
194
|
+
if (config.accessToken) {
|
|
195
|
+
headers["Authorization"] = `Bearer ${config.accessToken}`;
|
|
196
|
+
}
|
|
197
|
+
if (config.apiKey) {
|
|
198
|
+
headers["X-API-Key"] = config.apiKey;
|
|
199
|
+
}
|
|
200
|
+
return headers;
|
|
201
|
+
}
|
|
202
|
+
async function fetchAPI(config, url, options = {}) {
|
|
203
|
+
try {
|
|
204
|
+
const response = await fetch(url, {
|
|
205
|
+
...options,
|
|
206
|
+
headers: {
|
|
207
|
+
...createHeaders(config),
|
|
208
|
+
...options.headers
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
return await response.json();
|
|
212
|
+
} catch (error) {
|
|
213
|
+
return {
|
|
214
|
+
success: false,
|
|
215
|
+
error: error instanceof Error ? error.message : "API request failed"
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
async function addPaymentMethod(config, customerId, stripePaymentMethodId, setAsDefault = false) {
|
|
220
|
+
const { baseUrl, projectId } = config;
|
|
221
|
+
const result = await fetchAPI(
|
|
222
|
+
config,
|
|
223
|
+
`${baseUrl}/billing/customers/${customerId}/payment-methods`,
|
|
224
|
+
{
|
|
225
|
+
method: "POST",
|
|
226
|
+
body: JSON.stringify({
|
|
227
|
+
project_id: projectId,
|
|
228
|
+
type: "card",
|
|
229
|
+
stripe_payment_method_id: stripePaymentMethodId,
|
|
230
|
+
set_as_default: setAsDefault
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
if (!result.success) {
|
|
235
|
+
return { success: false, error: result.error || "Failed to add payment method" };
|
|
236
|
+
}
|
|
237
|
+
return { success: true, data: result.data };
|
|
238
|
+
}
|
|
239
|
+
async function removePaymentMethod(config, customerId, paymentMethodId) {
|
|
240
|
+
const { baseUrl, projectId } = config;
|
|
241
|
+
const isStripeId = paymentMethodId.startsWith("pm_");
|
|
242
|
+
const idType = isStripeId ? "stripe" : "database";
|
|
243
|
+
const result = await fetchAPI(
|
|
244
|
+
config,
|
|
245
|
+
`${baseUrl}/billing/payment-methods/${paymentMethodId}`,
|
|
246
|
+
{
|
|
247
|
+
method: "DELETE",
|
|
248
|
+
body: JSON.stringify({
|
|
249
|
+
customer_id: customerId,
|
|
250
|
+
project_id: projectId,
|
|
251
|
+
id_type: idType,
|
|
252
|
+
test_mode: true
|
|
253
|
+
})
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
if (!result.success) {
|
|
257
|
+
return { success: false, error: result.error || "Failed to remove payment method" };
|
|
258
|
+
}
|
|
259
|
+
return { success: true };
|
|
260
|
+
}
|
|
261
|
+
async function setDefaultPaymentMethod(config, customerId, paymentMethodId) {
|
|
262
|
+
const { baseUrl, projectId } = config;
|
|
263
|
+
const isStripeId = paymentMethodId.startsWith("pm_");
|
|
264
|
+
const idType = isStripeId ? "stripe" : "database";
|
|
265
|
+
const result = await fetchAPI(
|
|
266
|
+
config,
|
|
267
|
+
`${baseUrl}/billing/payment-methods/${paymentMethodId}`,
|
|
268
|
+
{
|
|
269
|
+
method: "PUT",
|
|
270
|
+
body: JSON.stringify({
|
|
271
|
+
customer_id: customerId,
|
|
272
|
+
project_id: projectId,
|
|
273
|
+
id_type: idType,
|
|
274
|
+
is_default: true,
|
|
275
|
+
test_mode: true
|
|
276
|
+
})
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
if (!result.success) {
|
|
280
|
+
return { success: false, error: result.error || "Failed to set default payment method" };
|
|
281
|
+
}
|
|
282
|
+
return { success: true };
|
|
283
|
+
}
|
|
284
|
+
async function createSubscription(config, customerId, priceId, paymentMethodId) {
|
|
285
|
+
const { baseUrl, projectId } = config;
|
|
286
|
+
const result = await fetchAPI(
|
|
287
|
+
config,
|
|
288
|
+
`${baseUrl}/billing/subscriptions`,
|
|
289
|
+
{
|
|
290
|
+
method: "POST",
|
|
291
|
+
body: JSON.stringify({
|
|
292
|
+
customer_id: customerId,
|
|
293
|
+
price_id: priceId,
|
|
294
|
+
payment_method_id: paymentMethodId || void 0,
|
|
295
|
+
project_id: projectId,
|
|
296
|
+
sync_to_stripe: true,
|
|
297
|
+
test_mode: true
|
|
298
|
+
})
|
|
299
|
+
}
|
|
300
|
+
);
|
|
301
|
+
if (!result.success) {
|
|
302
|
+
return { success: false, error: result.error || "Failed to create subscription" };
|
|
303
|
+
}
|
|
304
|
+
return { success: true, data: result.data };
|
|
305
|
+
}
|
|
306
|
+
async function cancelSubscription(config, subscriptionId, cancelAtPeriodEnd = true) {
|
|
307
|
+
const { baseUrl, projectId } = config;
|
|
308
|
+
const result = await fetchAPI(
|
|
309
|
+
config,
|
|
310
|
+
`${baseUrl}/billing/subscriptions/${subscriptionId}/cancel`,
|
|
311
|
+
{
|
|
312
|
+
method: "POST",
|
|
313
|
+
body: JSON.stringify({
|
|
314
|
+
project_id: projectId,
|
|
315
|
+
cancel_at_period_end: cancelAtPeriodEnd,
|
|
316
|
+
cancellation_reason: "requested"
|
|
317
|
+
})
|
|
318
|
+
}
|
|
319
|
+
);
|
|
320
|
+
if (!result.success) {
|
|
321
|
+
return { success: false, error: result.error || "Failed to cancel subscription" };
|
|
322
|
+
}
|
|
323
|
+
return { success: true };
|
|
324
|
+
}
|
|
325
|
+
async function updateSubscription(config, subscriptionId, newPriceId) {
|
|
326
|
+
const { baseUrl, projectId } = config;
|
|
327
|
+
const result = await fetchAPI(
|
|
328
|
+
config,
|
|
329
|
+
`${baseUrl}/billing/subscriptions/${subscriptionId}`,
|
|
330
|
+
{
|
|
331
|
+
method: "PUT",
|
|
332
|
+
body: JSON.stringify({
|
|
333
|
+
project_id: projectId,
|
|
334
|
+
price_id: newPriceId,
|
|
335
|
+
sync_to_stripe: true
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
if (!result.success) {
|
|
340
|
+
return { success: false, error: result.error || "Failed to update subscription" };
|
|
341
|
+
}
|
|
342
|
+
return { success: true, data: result.data };
|
|
343
|
+
}
|
|
344
|
+
async function fetchPaymentConfig(config) {
|
|
345
|
+
const { baseUrl, projectId } = config;
|
|
346
|
+
const result = await fetchAPI(
|
|
347
|
+
config,
|
|
348
|
+
`${baseUrl}/billing/payment-config?project_id=${projectId}&test_mode=true`
|
|
349
|
+
);
|
|
350
|
+
if (!result.success) {
|
|
351
|
+
return { success: false, error: result.error || "Failed to fetch payment configuration" };
|
|
352
|
+
}
|
|
353
|
+
return { success: true, data: result.data };
|
|
354
|
+
}
|
|
355
|
+
function UsageBar({ label, used, limit, unit = "" }) {
|
|
356
|
+
const percentage = limit > 0 ? used / limit * 100 : 0;
|
|
357
|
+
const isWarning = percentage > 80;
|
|
358
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
359
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
360
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-700 dark:text-gray-300", children: label }),
|
|
361
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-600 dark:text-gray-400", children: [
|
|
362
|
+
used.toLocaleString(),
|
|
363
|
+
unit,
|
|
364
|
+
" / ",
|
|
365
|
+
limit.toLocaleString(),
|
|
366
|
+
unit
|
|
367
|
+
] })
|
|
368
|
+
] }),
|
|
369
|
+
/* @__PURE__ */ jsx("div", { className: "w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2", children: /* @__PURE__ */ jsx(
|
|
370
|
+
"div",
|
|
371
|
+
{
|
|
372
|
+
className: `h-2 rounded-full transition-all ${isWarning ? "bg-yellow-500" : "bg-blue-600"}`,
|
|
373
|
+
style: { width: `${Math.min(percentage, 100)}%` }
|
|
374
|
+
}
|
|
375
|
+
) }),
|
|
376
|
+
/* @__PURE__ */ jsxs("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
|
|
377
|
+
percentage.toFixed(1),
|
|
378
|
+
"% used"
|
|
379
|
+
] })
|
|
380
|
+
] });
|
|
381
|
+
}
|
|
382
|
+
function BillingContent({
|
|
383
|
+
subscription,
|
|
384
|
+
invoices,
|
|
385
|
+
paymentMethods,
|
|
386
|
+
plans,
|
|
387
|
+
customer,
|
|
388
|
+
entitlements,
|
|
389
|
+
actionConfig,
|
|
390
|
+
className = ""
|
|
391
|
+
}) {
|
|
392
|
+
const router = useRouter();
|
|
393
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
394
|
+
const [error, setError] = useState(null);
|
|
395
|
+
const [success, setSuccess] = useState(null);
|
|
396
|
+
const [activeTabIndex, setActiveTabIndex] = useState(0);
|
|
397
|
+
const [isAddPaymentModalOpen, setIsAddPaymentModalOpen] = useState(false);
|
|
398
|
+
const [isRemovePaymentModalOpen, setIsRemovePaymentModalOpen] = useState(false);
|
|
399
|
+
const [isCancelModalOpen, setIsCancelModalOpen] = useState(false);
|
|
400
|
+
const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false);
|
|
401
|
+
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(null);
|
|
402
|
+
const [selectedPlan, setSelectedPlan] = useState(null);
|
|
403
|
+
const [selectedUpgradePaymentMethod, setSelectedUpgradePaymentMethod] = useState(null);
|
|
404
|
+
const [stripePublishableKey, setStripePublishableKey] = useState(null);
|
|
405
|
+
const [stripeLoading, setStripeLoading] = useState(false);
|
|
406
|
+
const [isUpgrading, setIsUpgrading] = useState(false);
|
|
407
|
+
const [upgradeSuccess, setUpgradeSuccess] = useState(false);
|
|
408
|
+
useEffect(() => {
|
|
409
|
+
async function loadStripeConfig() {
|
|
410
|
+
setStripeLoading(true);
|
|
411
|
+
try {
|
|
412
|
+
const result = await fetchPaymentConfig(actionConfig);
|
|
413
|
+
if (result.success && result.data?.public_key) {
|
|
414
|
+
setStripePublishableKey(result.data.public_key);
|
|
415
|
+
}
|
|
416
|
+
} catch (err) {
|
|
417
|
+
console.error("Failed to load Stripe config:", err);
|
|
418
|
+
} finally {
|
|
419
|
+
setStripeLoading(false);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
loadStripeConfig();
|
|
423
|
+
}, [actionConfig]);
|
|
424
|
+
const handleCancelSubscription = async () => {
|
|
425
|
+
if (!subscription) return;
|
|
426
|
+
setIsLoading(true);
|
|
427
|
+
setError(null);
|
|
428
|
+
const result = await cancelSubscription(actionConfig, subscription.id);
|
|
429
|
+
if (!result.success) {
|
|
430
|
+
setError(result.error || "Failed to cancel subscription");
|
|
431
|
+
} else {
|
|
432
|
+
setSuccess("Subscription will be canceled at the end of the billing period");
|
|
433
|
+
setIsCancelModalOpen(false);
|
|
434
|
+
}
|
|
435
|
+
setIsLoading(false);
|
|
436
|
+
};
|
|
437
|
+
const handleAddPaymentMethod = async (stripePaymentMethodId, setAsDefault) => {
|
|
438
|
+
const result = await addPaymentMethod(actionConfig, customer.id, stripePaymentMethodId, setAsDefault);
|
|
439
|
+
return result;
|
|
440
|
+
};
|
|
441
|
+
const handleAddPaymentSuccess = () => {
|
|
442
|
+
setIsAddPaymentModalOpen(false);
|
|
443
|
+
setSuccess("Payment method added successfully");
|
|
444
|
+
router.refresh();
|
|
445
|
+
};
|
|
446
|
+
const handleRemovePaymentClick = (pm) => {
|
|
447
|
+
setSelectedPaymentMethod(pm);
|
|
448
|
+
setIsRemovePaymentModalOpen(true);
|
|
449
|
+
};
|
|
450
|
+
const handleConfirmRemovePayment = async () => {
|
|
451
|
+
if (!selectedPaymentMethod) return;
|
|
452
|
+
setIsLoading(true);
|
|
453
|
+
setError(null);
|
|
454
|
+
const paymentMethodId = selectedPaymentMethod.provider_payment_method_id || String(selectedPaymentMethod.id);
|
|
455
|
+
const result = await removePaymentMethod(actionConfig, customer.id, paymentMethodId);
|
|
456
|
+
if (!result.success) {
|
|
457
|
+
setError(result.error || "Failed to remove payment method");
|
|
458
|
+
} else {
|
|
459
|
+
setSuccess("Payment method removed");
|
|
460
|
+
setIsRemovePaymentModalOpen(false);
|
|
461
|
+
setSelectedPaymentMethod(null);
|
|
462
|
+
router.refresh();
|
|
463
|
+
}
|
|
464
|
+
setIsLoading(false);
|
|
465
|
+
};
|
|
466
|
+
const handleSelectPlan = (plan) => {
|
|
467
|
+
if (plan.current || !plan.priceId) return;
|
|
468
|
+
setSelectedPlan(plan);
|
|
469
|
+
setIsUpgradeModalOpen(true);
|
|
470
|
+
setError(null);
|
|
471
|
+
const priceNum = parseFloat(plan.price.replace(/[^0-9.]/g, "")) || 0;
|
|
472
|
+
if (priceNum > 0) {
|
|
473
|
+
const defaultPaymentMethod = paymentMethods.find((pm) => pm.is_default);
|
|
474
|
+
setSelectedUpgradePaymentMethod(defaultPaymentMethod?.id || null);
|
|
475
|
+
} else {
|
|
476
|
+
setSelectedUpgradePaymentMethod(null);
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
const handleConfirmUpgrade = async () => {
|
|
480
|
+
if (!selectedPlan) return;
|
|
481
|
+
const priceNum = parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) || 0;
|
|
482
|
+
if (priceNum > 0 && !selectedUpgradePaymentMethod && paymentMethods.length > 0) {
|
|
483
|
+
setError("Please select a payment method");
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
setIsUpgrading(true);
|
|
487
|
+
setError(null);
|
|
488
|
+
try {
|
|
489
|
+
if (subscription) {
|
|
490
|
+
const result = await updateSubscription(actionConfig, subscription.id, selectedPlan.priceId);
|
|
491
|
+
if (!result.success) {
|
|
492
|
+
setError(result.error || "Failed to update subscription");
|
|
493
|
+
setIsUpgrading(false);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
} else {
|
|
497
|
+
const paymentMethodId = selectedUpgradePaymentMethod ? paymentMethods.find((pm) => pm.id === selectedUpgradePaymentMethod)?.provider_payment_method_id || String(selectedUpgradePaymentMethod) : void 0;
|
|
498
|
+
const result = await createSubscription(actionConfig, customer.id, selectedPlan.priceId, paymentMethodId);
|
|
499
|
+
if (!result.success) {
|
|
500
|
+
setError(result.error || "Failed to create subscription");
|
|
501
|
+
setIsUpgrading(false);
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
setIsUpgradeModalOpen(false);
|
|
506
|
+
setUpgradeSuccess(true);
|
|
507
|
+
router.refresh();
|
|
508
|
+
} catch (err) {
|
|
509
|
+
setError(err instanceof Error ? err.message : "An error occurred");
|
|
510
|
+
} finally {
|
|
511
|
+
setIsUpgrading(false);
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
const handleCloseSuccessModal = () => {
|
|
515
|
+
setUpgradeSuccess(false);
|
|
516
|
+
setSelectedPlan(null);
|
|
517
|
+
setSelectedUpgradePaymentMethod(null);
|
|
518
|
+
};
|
|
519
|
+
const handleSetDefaultPaymentMethod = async (pm) => {
|
|
520
|
+
setIsLoading(true);
|
|
521
|
+
setError(null);
|
|
522
|
+
const paymentMethodId = pm.provider_payment_method_id || String(pm.id);
|
|
523
|
+
const result = await setDefaultPaymentMethod(actionConfig, customer.id, paymentMethodId);
|
|
524
|
+
if (!result.success) {
|
|
525
|
+
setError(result.error || "Failed to set default payment method");
|
|
526
|
+
} else {
|
|
527
|
+
setSuccess("Default payment method updated");
|
|
528
|
+
router.refresh();
|
|
529
|
+
}
|
|
530
|
+
setIsLoading(false);
|
|
531
|
+
};
|
|
532
|
+
const handleChangePlanClick = () => {
|
|
533
|
+
setActiveTabIndex(1);
|
|
534
|
+
};
|
|
535
|
+
const tabs = [
|
|
536
|
+
{
|
|
537
|
+
id: "subscription",
|
|
538
|
+
label: "Subscription",
|
|
539
|
+
content: /* @__PURE__ */ jsxs("div", { className: "space-y-6 mt-6", children: [
|
|
540
|
+
error && /* @__PURE__ */ jsx("div", { className: "p-4 bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200 rounded-lg", children: error }),
|
|
541
|
+
success && /* @__PURE__ */ jsx("div", { className: "p-4 bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200 rounded-lg", children: success }),
|
|
542
|
+
/* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs("div", { children: [
|
|
543
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-4", children: [
|
|
544
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
545
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "Current Plan" }),
|
|
546
|
+
subscription ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
547
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2", children: [
|
|
548
|
+
/* @__PURE__ */ jsx("span", { className: "text-3xl font-bold", children: subscription.price }),
|
|
549
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-600 dark:text-gray-400", children: [
|
|
550
|
+
"/ ",
|
|
551
|
+
subscription.period
|
|
552
|
+
] })
|
|
553
|
+
] }),
|
|
554
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-gray-600 dark:text-gray-400", children: subscription.plan })
|
|
555
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: "No active subscription" })
|
|
556
|
+
] }),
|
|
557
|
+
subscription && /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-3 py-1 text-sm font-medium ${subscription.status === "active" ? "bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300" : subscription.status === "canceled" ? "bg-red-100 dark:bg-red-900/30 text-red-800 dark:text-red-300" : "bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-300"}`, children: subscription.cancelAtPeriodEnd ? "Canceling" : subscription.status })
|
|
558
|
+
] }),
|
|
559
|
+
subscription && /* @__PURE__ */ jsx("div", { className: "space-y-3 mb-4", children: /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
560
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Next billing date" }),
|
|
561
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: subscription.nextBilling })
|
|
562
|
+
] }) }),
|
|
563
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
564
|
+
/* @__PURE__ */ jsx(Button, { className: "flex-1", disabled: isLoading, onClick: handleChangePlanClick, children: subscription ? "Change Plan" : "Choose a Plan" }),
|
|
565
|
+
subscription && !subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsx(
|
|
566
|
+
Button,
|
|
567
|
+
{
|
|
568
|
+
variant: "secondary",
|
|
569
|
+
onClick: () => setIsCancelModalOpen(true),
|
|
570
|
+
disabled: isLoading,
|
|
571
|
+
children: "Cancel"
|
|
572
|
+
}
|
|
573
|
+
)
|
|
574
|
+
] })
|
|
575
|
+
] }) }),
|
|
576
|
+
entitlements.length > 0 && /* @__PURE__ */ jsxs(Card, { children: [
|
|
577
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-4", children: "Current Usage" }),
|
|
578
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-4", children: entitlements.map((ent) => {
|
|
579
|
+
const featureName = ent.feature_key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
580
|
+
const entValue = typeof ent.value === "object" && ent.value?.value !== void 0 ? ent.value.value : ent.value;
|
|
581
|
+
const limit = typeof entValue === "number" ? entValue : 0;
|
|
582
|
+
const used = ent.usage_count || 0;
|
|
583
|
+
if (typeof entValue === "number" && entValue > 0) {
|
|
584
|
+
return /* @__PURE__ */ jsx(
|
|
585
|
+
UsageBar,
|
|
586
|
+
{
|
|
587
|
+
label: featureName,
|
|
588
|
+
used,
|
|
589
|
+
limit
|
|
590
|
+
},
|
|
591
|
+
ent.id
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
const isEnabled = entValue === true || entValue === "true" || entValue === "Enabled";
|
|
595
|
+
const isDisabled = entValue === false || entValue === "false";
|
|
596
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center text-sm", children: [
|
|
597
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-700 dark:text-gray-300", children: featureName }),
|
|
598
|
+
isEnabled || !isDisabled && entValue === void 0 ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-green-600 dark:text-green-400", children: [
|
|
599
|
+
/* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
|
|
600
|
+
"Included"
|
|
601
|
+
] }) : isDisabled ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-gray-400 dark:text-gray-500", children: [
|
|
602
|
+
/* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }),
|
|
603
|
+
"Not included"
|
|
604
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: String(entValue) })
|
|
605
|
+
] }, ent.id);
|
|
606
|
+
}) })
|
|
607
|
+
] })
|
|
608
|
+
] })
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
id: "plans",
|
|
612
|
+
label: "Plans",
|
|
613
|
+
content: /* @__PURE__ */ jsxs("div", { className: "space-y-6 mt-6", children: [
|
|
614
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
615
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "Choose Your Plan" }),
|
|
616
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400 mb-6", children: "Select the plan that best fits your needs. You can upgrade or downgrade at any time." })
|
|
617
|
+
] }),
|
|
618
|
+
plans.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-gray-500 dark:text-gray-400", children: "No plans available." }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-6", children: plans.map((plan) => /* @__PURE__ */ jsxs(
|
|
619
|
+
"div",
|
|
620
|
+
{
|
|
621
|
+
className: `relative rounded-lg border-2 p-6 flex flex-col ${plan.current ? "border-blue-600 dark:border-blue-500" : "border-gray-200 dark:border-neutral-700"} ${plan.popular ? "shadow-lg" : ""}`,
|
|
622
|
+
children: [
|
|
623
|
+
plan.popular && !plan.current && /* @__PURE__ */ jsx("div", { className: "absolute -top-3 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx("span", { className: "bg-blue-600 text-white text-xs font-semibold px-3 py-1 rounded-full", children: "Most Popular" }) }),
|
|
624
|
+
plan.current && /* @__PURE__ */ jsx("div", { className: "absolute -top-3 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx("span", { className: "bg-green-600 text-white text-xs font-semibold px-3 py-1 rounded-full", children: "Current Plan" }) }),
|
|
625
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
|
|
626
|
+
/* @__PURE__ */ jsx("h4", { className: "text-xl font-bold mb-2", children: plan.name }),
|
|
627
|
+
plan.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400 mb-2", children: plan.description }),
|
|
628
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2", children: [
|
|
629
|
+
/* @__PURE__ */ jsx("span", { className: "text-3xl font-bold", children: plan.price }),
|
|
630
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-600 dark:text-gray-400", children: [
|
|
631
|
+
"/ ",
|
|
632
|
+
plan.period
|
|
633
|
+
] })
|
|
634
|
+
] })
|
|
635
|
+
] }),
|
|
636
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-3 mb-6 flex-1", children: plan.features.map((feature, idx) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2 text-sm", children: [
|
|
637
|
+
/* @__PURE__ */ jsx(
|
|
638
|
+
"svg",
|
|
639
|
+
{
|
|
640
|
+
className: "w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0 mt-0.5",
|
|
641
|
+
fill: "none",
|
|
642
|
+
stroke: "currentColor",
|
|
643
|
+
viewBox: "0 0 24 24",
|
|
644
|
+
children: /* @__PURE__ */ jsx(
|
|
645
|
+
"path",
|
|
646
|
+
{
|
|
647
|
+
strokeLinecap: "round",
|
|
648
|
+
strokeLinejoin: "round",
|
|
649
|
+
strokeWidth: 2,
|
|
650
|
+
d: "M5 13l4 4L19 7"
|
|
651
|
+
}
|
|
652
|
+
)
|
|
653
|
+
}
|
|
654
|
+
),
|
|
655
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-700 dark:text-gray-300", children: feature })
|
|
656
|
+
] }, idx)) }),
|
|
657
|
+
/* @__PURE__ */ jsx(
|
|
658
|
+
Button,
|
|
659
|
+
{
|
|
660
|
+
className: "w-full",
|
|
661
|
+
disabled: plan.current || isLoading,
|
|
662
|
+
variant: plan.current ? "secondary" : "primary",
|
|
663
|
+
onClick: () => handleSelectPlan(plan),
|
|
664
|
+
children: plan.current ? "Current Plan" : subscription ? "Switch Plan" : "Select Plan"
|
|
665
|
+
}
|
|
666
|
+
)
|
|
667
|
+
]
|
|
668
|
+
},
|
|
669
|
+
plan.id
|
|
670
|
+
)) })
|
|
671
|
+
] })
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
id: "invoices",
|
|
675
|
+
label: "Invoices",
|
|
676
|
+
content: /* @__PURE__ */ jsx("div", { className: "mt-6", children: /* @__PURE__ */ jsxs(Card, { children: [
|
|
677
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "Invoice History" }),
|
|
678
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400 mb-6", children: "View and download your past invoices" }),
|
|
679
|
+
invoices.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-gray-500 dark:text-gray-400", children: "No invoices yet." }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: invoices.map((invoice) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border border-gray-200 dark:border-neutral-700 rounded-lg hover:bg-gray-50 dark:hover:bg-neutral-800 transition-colors", children: [
|
|
680
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
681
|
+
/* @__PURE__ */ jsx("div", { className: "h-10 w-10 rounded-full bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center", children: /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-blue-600 dark:text-blue-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) }) }),
|
|
682
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
683
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
684
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-sm", children: invoice.id }),
|
|
685
|
+
/* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${invoice.status === "paid" ? "bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300" : invoice.status === "open" ? "bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-300" : "bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-300"}`, children: invoice.status })
|
|
686
|
+
] }),
|
|
687
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400", children: invoice.date })
|
|
688
|
+
] })
|
|
689
|
+
] }),
|
|
690
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
691
|
+
/* @__PURE__ */ jsx("p", { className: "font-semibold", children: invoice.amount }),
|
|
692
|
+
invoice.url && invoice.url !== "#" && /* @__PURE__ */ jsx(
|
|
693
|
+
Button,
|
|
694
|
+
{
|
|
695
|
+
variant: "secondary",
|
|
696
|
+
size: "sm",
|
|
697
|
+
onClick: () => window.open(invoice.url, "_blank"),
|
|
698
|
+
children: "Download"
|
|
699
|
+
}
|
|
700
|
+
)
|
|
701
|
+
] })
|
|
702
|
+
] }, invoice.id)) })
|
|
703
|
+
] }) })
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
id: "payment",
|
|
707
|
+
label: "Payment Method",
|
|
708
|
+
content: /* @__PURE__ */ jsx("div", { className: "mt-6", children: /* @__PURE__ */ jsxs(Card, { children: [
|
|
709
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "Payment Methods" }),
|
|
710
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400 mb-6", children: "Manage your payment methods" }),
|
|
711
|
+
paymentMethods.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8 border border-dashed border-gray-300 dark:border-neutral-700 rounded-lg", children: [
|
|
712
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500 dark:text-gray-400 mb-4", children: "No payment methods on file" }),
|
|
713
|
+
/* @__PURE__ */ jsx(Button, { onClick: () => setIsAddPaymentModalOpen(true), disabled: stripeLoading, children: stripeLoading ? "Loading..." : "Add Payment Method" })
|
|
714
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
715
|
+
paymentMethods.map((pm) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border border-gray-200 dark:border-neutral-700 rounded-lg", children: [
|
|
716
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
717
|
+
/* @__PURE__ */ jsx("div", { className: "h-10 w-10 rounded-full bg-gray-100 dark:bg-neutral-800 flex items-center justify-center", children: /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" }) }) }),
|
|
718
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
719
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
720
|
+
/* @__PURE__ */ jsxs("p", { className: "font-medium text-sm", children: [
|
|
721
|
+
pm.card_brand || pm.type,
|
|
722
|
+
" \u2022\u2022\u2022\u2022 ",
|
|
723
|
+
pm.card_last4 || pm.bank_last4 || "****"
|
|
724
|
+
] }),
|
|
725
|
+
pm.is_default && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-blue-100 dark:bg-blue-900/30 px-2 py-0.5 text-xs font-medium text-blue-800 dark:text-blue-300", children: "Default" })
|
|
726
|
+
] }),
|
|
727
|
+
pm.card_exp_month && pm.card_exp_year && /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-600 dark:text-gray-400", children: [
|
|
728
|
+
"Expires ",
|
|
729
|
+
pm.card_exp_month,
|
|
730
|
+
"/",
|
|
731
|
+
pm.card_exp_year
|
|
732
|
+
] })
|
|
733
|
+
] })
|
|
734
|
+
] }),
|
|
735
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
736
|
+
!pm.is_default && /* @__PURE__ */ jsx(
|
|
737
|
+
Button,
|
|
738
|
+
{
|
|
739
|
+
variant: "secondary",
|
|
740
|
+
size: "sm",
|
|
741
|
+
onClick: () => handleSetDefaultPaymentMethod(pm),
|
|
742
|
+
disabled: isLoading,
|
|
743
|
+
children: "Set Default"
|
|
744
|
+
}
|
|
745
|
+
),
|
|
746
|
+
/* @__PURE__ */ jsx(
|
|
747
|
+
Button,
|
|
748
|
+
{
|
|
749
|
+
variant: "secondary",
|
|
750
|
+
size: "sm",
|
|
751
|
+
onClick: () => handleRemovePaymentClick(pm),
|
|
752
|
+
disabled: isLoading,
|
|
753
|
+
children: "Remove"
|
|
754
|
+
}
|
|
755
|
+
)
|
|
756
|
+
] })
|
|
757
|
+
] }, pm.id)),
|
|
758
|
+
/* @__PURE__ */ jsx(
|
|
759
|
+
Button,
|
|
760
|
+
{
|
|
761
|
+
variant: "secondary",
|
|
762
|
+
className: "w-full mt-4",
|
|
763
|
+
onClick: () => setIsAddPaymentModalOpen(true),
|
|
764
|
+
disabled: stripeLoading,
|
|
765
|
+
children: stripeLoading ? "Loading..." : "Add Payment Method"
|
|
766
|
+
}
|
|
767
|
+
)
|
|
768
|
+
] })
|
|
769
|
+
] }) })
|
|
770
|
+
}
|
|
771
|
+
];
|
|
772
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
773
|
+
/* @__PURE__ */ jsx(Tabs, { tabs, defaultIndex: activeTabIndex, onChange: setActiveTabIndex }, activeTabIndex),
|
|
774
|
+
/* @__PURE__ */ jsx(
|
|
775
|
+
Modal,
|
|
776
|
+
{
|
|
777
|
+
isOpen: isAddPaymentModalOpen,
|
|
778
|
+
onClose: () => setIsAddPaymentModalOpen(false),
|
|
779
|
+
title: "Add Payment Method",
|
|
780
|
+
children: stripePublishableKey ? /* @__PURE__ */ jsx(
|
|
781
|
+
AddPaymentMethodForm,
|
|
782
|
+
{
|
|
783
|
+
customerId: customer.id,
|
|
784
|
+
stripePublishableKey,
|
|
785
|
+
onSuccess: handleAddPaymentSuccess,
|
|
786
|
+
onCancel: () => setIsAddPaymentModalOpen(false),
|
|
787
|
+
onSubmit: handleAddPaymentMethod
|
|
788
|
+
}
|
|
789
|
+
) : /* @__PURE__ */ jsx("div", { className: "text-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: stripeLoading ? "Loading payment form..." : "Payment configuration not available" }) })
|
|
790
|
+
}
|
|
791
|
+
),
|
|
792
|
+
/* @__PURE__ */ jsx(
|
|
793
|
+
Modal,
|
|
794
|
+
{
|
|
795
|
+
isOpen: isRemovePaymentModalOpen,
|
|
796
|
+
onClose: () => {
|
|
797
|
+
setIsRemovePaymentModalOpen(false);
|
|
798
|
+
setSelectedPaymentMethod(null);
|
|
799
|
+
},
|
|
800
|
+
title: "Remove Payment Method",
|
|
801
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
802
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: "Are you sure you want to remove this payment method?" }),
|
|
803
|
+
selectedPaymentMethod && /* @__PURE__ */ jsx("div", { className: "bg-gray-50 dark:bg-gray-800 rounded-lg p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
804
|
+
/* @__PURE__ */ jsx("div", { className: "w-12 h-8 bg-gradient-to-br from-indigo-500 to-purple-600 rounded-lg flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx("svg", { className: "w-6 h-6 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" }) }) }),
|
|
805
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
806
|
+
/* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-900 dark:text-white", children: selectedPaymentMethod.card_brand || "Card" }),
|
|
807
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: [
|
|
808
|
+
"\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 ",
|
|
809
|
+
selectedPaymentMethod.card_last4 || "****"
|
|
810
|
+
] })
|
|
811
|
+
] })
|
|
812
|
+
] }) }),
|
|
813
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "This action cannot be undone." }),
|
|
814
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
|
|
815
|
+
/* @__PURE__ */ jsx(
|
|
816
|
+
Button,
|
|
817
|
+
{
|
|
818
|
+
variant: "secondary",
|
|
819
|
+
onClick: () => {
|
|
820
|
+
setIsRemovePaymentModalOpen(false);
|
|
821
|
+
setSelectedPaymentMethod(null);
|
|
822
|
+
},
|
|
823
|
+
disabled: isLoading,
|
|
824
|
+
children: "Cancel"
|
|
825
|
+
}
|
|
826
|
+
),
|
|
827
|
+
/* @__PURE__ */ jsx(
|
|
828
|
+
Button,
|
|
829
|
+
{
|
|
830
|
+
variant: "primary",
|
|
831
|
+
onClick: handleConfirmRemovePayment,
|
|
832
|
+
disabled: isLoading,
|
|
833
|
+
children: isLoading ? "Removing..." : "Remove Payment Method"
|
|
834
|
+
}
|
|
835
|
+
)
|
|
836
|
+
] })
|
|
837
|
+
] })
|
|
838
|
+
}
|
|
839
|
+
),
|
|
840
|
+
/* @__PURE__ */ jsx(
|
|
841
|
+
Modal,
|
|
842
|
+
{
|
|
843
|
+
isOpen: isCancelModalOpen,
|
|
844
|
+
onClose: () => setIsCancelModalOpen(false),
|
|
845
|
+
title: "Cancel Subscription",
|
|
846
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
847
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4", children: [
|
|
848
|
+
/* @__PURE__ */ jsx("svg", { className: "w-6 h-6 text-yellow-600 dark:text-yellow-400 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }),
|
|
849
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
850
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-yellow-900 dark:text-yellow-100 mb-1", children: "Are you sure you want to cancel?" }),
|
|
851
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-yellow-800 dark:text-yellow-200", children: "You'll lose access to premium features when your current billing period ends." })
|
|
852
|
+
] })
|
|
853
|
+
] }),
|
|
854
|
+
subscription && /* @__PURE__ */ jsxs("div", { className: "bg-gray-50 dark:bg-gray-800 rounded-lg p-4", children: [
|
|
855
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
856
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Current Plan:" }),
|
|
857
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: subscription.plan })
|
|
858
|
+
] }),
|
|
859
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm mt-2", children: [
|
|
860
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Access Until:" }),
|
|
861
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: subscription.nextBilling })
|
|
862
|
+
] })
|
|
863
|
+
] }),
|
|
864
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
|
|
865
|
+
/* @__PURE__ */ jsx(
|
|
866
|
+
Button,
|
|
867
|
+
{
|
|
868
|
+
variant: "secondary",
|
|
869
|
+
onClick: () => setIsCancelModalOpen(false),
|
|
870
|
+
disabled: isLoading,
|
|
871
|
+
children: "Keep Subscription"
|
|
872
|
+
}
|
|
873
|
+
),
|
|
874
|
+
/* @__PURE__ */ jsx(
|
|
875
|
+
Button,
|
|
876
|
+
{
|
|
877
|
+
variant: "primary",
|
|
878
|
+
onClick: handleCancelSubscription,
|
|
879
|
+
disabled: isLoading,
|
|
880
|
+
children: isLoading ? "Canceling..." : "Yes, Cancel Subscription"
|
|
881
|
+
}
|
|
882
|
+
)
|
|
883
|
+
] })
|
|
884
|
+
] })
|
|
885
|
+
}
|
|
886
|
+
),
|
|
887
|
+
/* @__PURE__ */ jsx(
|
|
888
|
+
Modal,
|
|
889
|
+
{
|
|
890
|
+
isOpen: isUpgradeModalOpen,
|
|
891
|
+
onClose: () => {
|
|
892
|
+
setIsUpgradeModalOpen(false);
|
|
893
|
+
setError(null);
|
|
894
|
+
},
|
|
895
|
+
title: selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) === 0 ? "Start Free Plan" : subscription ? "Confirm Plan Change" : "Confirm Subscription",
|
|
896
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
897
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
898
|
+
"Start your free ",
|
|
899
|
+
/* @__PURE__ */ jsx("strong", { children: selectedPlan?.name }),
|
|
900
|
+
" plan"
|
|
901
|
+
] }) : subscription ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
902
|
+
"Switch to the ",
|
|
903
|
+
/* @__PURE__ */ jsx("strong", { children: selectedPlan?.name }),
|
|
904
|
+
" plan"
|
|
905
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
906
|
+
"Subscribe to the ",
|
|
907
|
+
/* @__PURE__ */ jsx("strong", { children: selectedPlan?.name }),
|
|
908
|
+
" plan"
|
|
909
|
+
] }) }),
|
|
910
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-gray-50 dark:bg-gray-800 rounded-lg p-4", children: [
|
|
911
|
+
/* @__PURE__ */ jsx("h4", { className: "font-semibold text-gray-900 dark:text-white mb-2", children: "Billing Summary" }),
|
|
912
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm mb-1", children: [
|
|
913
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Plan:" }),
|
|
914
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900 dark:text-white", children: selectedPlan?.name })
|
|
915
|
+
] }),
|
|
916
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm mb-1", children: [
|
|
917
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Billing Cycle:" }),
|
|
918
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium text-gray-900 dark:text-white", children: [
|
|
919
|
+
selectedPlan?.period || "month",
|
|
920
|
+
"ly"
|
|
921
|
+
] })
|
|
922
|
+
] }),
|
|
923
|
+
selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) > 0 && /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm mb-1", children: [
|
|
924
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Price:" }),
|
|
925
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium text-gray-900 dark:text-white", children: [
|
|
926
|
+
selectedPlan.price,
|
|
927
|
+
"/",
|
|
928
|
+
selectedPlan.period || "month"
|
|
929
|
+
] })
|
|
930
|
+
] }),
|
|
931
|
+
/* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 mt-3 pt-3", children: /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
932
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-900 dark:text-white", children: selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) === 0 ? "Total:" : "Charged Today:" }),
|
|
933
|
+
/* @__PURE__ */ jsx("span", { className: "font-bold text-lg text-gray-900 dark:text-white", children: selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) === 0 ? /* @__PURE__ */ jsx("span", { className: "text-green-600 dark:text-green-400", children: "FREE" }) : selectedPlan?.price || "$0" })
|
|
934
|
+
] }) })
|
|
935
|
+
] }),
|
|
936
|
+
selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) > 0 && paymentMethods.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
937
|
+
/* @__PURE__ */ jsx("h4", { className: "font-semibold text-gray-900 dark:text-white text-sm", children: "Select Payment Method" }),
|
|
938
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: paymentMethods.map((method) => /* @__PURE__ */ jsxs(
|
|
939
|
+
"label",
|
|
940
|
+
{
|
|
941
|
+
className: `flex items-center gap-3 p-3 rounded-lg border-2 cursor-pointer transition-all ${selectedUpgradePaymentMethod === method.id ? "border-blue-500 bg-blue-50 dark:bg-blue-900/20" : "border-gray-200 dark:border-neutral-700 hover:border-gray-300 dark:hover:border-neutral-600"}`,
|
|
942
|
+
children: [
|
|
943
|
+
/* @__PURE__ */ jsx(
|
|
944
|
+
"input",
|
|
945
|
+
{
|
|
946
|
+
type: "radio",
|
|
947
|
+
name: "paymentMethod",
|
|
948
|
+
value: method.id,
|
|
949
|
+
checked: selectedUpgradePaymentMethod === method.id,
|
|
950
|
+
onChange: () => setSelectedUpgradePaymentMethod(method.id),
|
|
951
|
+
className: "w-4 h-4 text-blue-600"
|
|
952
|
+
}
|
|
953
|
+
),
|
|
954
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
955
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
956
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900 dark:text-white text-sm", children: method.card_brand ? method.card_brand.charAt(0).toUpperCase() + method.card_brand.slice(1) : "Card" }),
|
|
957
|
+
method.is_default && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-blue-100 dark:bg-blue-900/30 px-2 py-0.5 text-xs font-medium text-blue-800 dark:text-blue-300", children: "Default" })
|
|
958
|
+
] }),
|
|
959
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-600 dark:text-gray-400", children: [
|
|
960
|
+
"\u2022\u2022\u2022\u2022 ",
|
|
961
|
+
method.card_last4 || "XXXX"
|
|
962
|
+
] })
|
|
963
|
+
] })
|
|
964
|
+
]
|
|
965
|
+
},
|
|
966
|
+
method.id
|
|
967
|
+
)) })
|
|
968
|
+
] }),
|
|
969
|
+
selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) > 0 && paymentMethods.length === 0 && /* @__PURE__ */ jsx("div", { className: "bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-3", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-yellow-800 dark:text-yellow-200", children: "Please add a payment method before subscribing to a paid plan." }) }),
|
|
970
|
+
selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) === 0 && /* @__PURE__ */ jsx("div", { className: "bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-3", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-green-800 dark:text-green-200", children: "This is a free plan. No payment method required!" }) }),
|
|
971
|
+
selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) > 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Your payment method will be charged immediately. You can cancel anytime." }),
|
|
972
|
+
error && /* @__PURE__ */ jsx("div", { className: "bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
973
|
+
/* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0 mt-0.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
974
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-red-800 dark:text-red-200", children: error })
|
|
975
|
+
] }) }),
|
|
976
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6", children: [
|
|
977
|
+
/* @__PURE__ */ jsx(
|
|
978
|
+
Button,
|
|
979
|
+
{
|
|
980
|
+
variant: "secondary",
|
|
981
|
+
onClick: () => {
|
|
982
|
+
setIsUpgradeModalOpen(false);
|
|
983
|
+
setError(null);
|
|
984
|
+
},
|
|
985
|
+
disabled: isUpgrading,
|
|
986
|
+
children: "Cancel"
|
|
987
|
+
}
|
|
988
|
+
),
|
|
989
|
+
/* @__PURE__ */ jsx(
|
|
990
|
+
Button,
|
|
991
|
+
{
|
|
992
|
+
variant: "primary",
|
|
993
|
+
onClick: handleConfirmUpgrade,
|
|
994
|
+
disabled: isUpgrading || !!(selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) > 0 && paymentMethods.length === 0),
|
|
995
|
+
children: isUpgrading ? "Processing..." : selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) === 0 ? "Start Free Plan" : subscription ? "Confirm Change" : "Confirm Subscription"
|
|
996
|
+
}
|
|
997
|
+
)
|
|
998
|
+
] })
|
|
999
|
+
] })
|
|
1000
|
+
}
|
|
1001
|
+
),
|
|
1002
|
+
/* @__PURE__ */ jsx(
|
|
1003
|
+
Modal,
|
|
1004
|
+
{
|
|
1005
|
+
isOpen: upgradeSuccess,
|
|
1006
|
+
onClose: handleCloseSuccessModal,
|
|
1007
|
+
title: "Subscription Successful!",
|
|
1008
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
1009
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-16 h-16 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx("svg", { className: "w-8 h-8 text-green-600 dark:text-green-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) }) }),
|
|
1010
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
1011
|
+
/* @__PURE__ */ jsxs("h3", { className: "text-xl font-bold text-gray-900 dark:text-white mb-2", children: [
|
|
1012
|
+
"Welcome to ",
|
|
1013
|
+
selectedPlan?.name,
|
|
1014
|
+
"!"
|
|
1015
|
+
] }),
|
|
1016
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) === 0 ? "Your free plan is now active. Start exploring all the features!" : "Your subscription has been activated and your payment method has been charged." })
|
|
1017
|
+
] }),
|
|
1018
|
+
/* @__PURE__ */ jsx("div", { className: "bg-gray-50 dark:bg-gray-800 rounded-lg p-4", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1019
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
1020
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Plan:" }),
|
|
1021
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900 dark:text-white", children: selectedPlan?.name })
|
|
1022
|
+
] }),
|
|
1023
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
1024
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Billing:" }),
|
|
1025
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900 dark:text-white", children: selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) === 0 ? "Free" : `${selectedPlan?.price}/${selectedPlan?.period}` })
|
|
1026
|
+
] }),
|
|
1027
|
+
selectedPlan && parseFloat(selectedPlan.price.replace(/[^0-9.]/g, "")) > 0 && /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm pt-2 border-t border-gray-200 dark:border-gray-700", children: [
|
|
1028
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Status:" }),
|
|
1029
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-green-600 dark:text-green-400", children: "Active" })
|
|
1030
|
+
] })
|
|
1031
|
+
] }) }),
|
|
1032
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center pt-2", children: /* @__PURE__ */ jsx(
|
|
1033
|
+
Button,
|
|
1034
|
+
{
|
|
1035
|
+
variant: "primary",
|
|
1036
|
+
onClick: handleCloseSuccessModal,
|
|
1037
|
+
className: "px-8",
|
|
1038
|
+
children: "Get Started"
|
|
1039
|
+
}
|
|
1040
|
+
) })
|
|
1041
|
+
] })
|
|
1042
|
+
}
|
|
1043
|
+
)
|
|
1044
|
+
] });
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
export { AddPaymentMethodForm, BillingContent, Modal };
|
|
1048
|
+
//# sourceMappingURL=chunk-2SK6OTCD.js.map
|
|
1049
|
+
//# sourceMappingURL=chunk-2SK6OTCD.js.map
|