@omnikit-js/ui 0.9.7 → 0.9.8
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-IKBW2JFX.js → chunk-2KDIPVL3.js} +395 -22
- package/dist/chunk-2KDIPVL3.js.map +1 -0
- package/dist/{chunk-O6555PUL.js → chunk-IZA33E5G.js} +3 -3
- package/dist/{chunk-O6555PUL.js.map → chunk-IZA33E5G.js.map} +1 -1
- package/dist/components/client/index.d.ts +13 -1
- package/dist/components/client/index.js +4 -48
- 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 +13 -1
- package/dist/chunk-IKBW2JFX.js.map +0 -1
|
@@ -1,9 +1,189 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { Card, Button, Tabs } from '@marcoschwartz/lite-ui';
|
|
2
|
+
import { useEffect, useState, useMemo } from 'react';
|
|
4
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';
|
|
5
7
|
|
|
6
|
-
// src/components/client/
|
|
8
|
+
// src/components/client/Modal/index.tsx
|
|
9
|
+
function Modal({ isOpen, onClose, title, children, className = "" }) {
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const handleEscape = (e) => {
|
|
12
|
+
if (e.key === "Escape") onClose();
|
|
13
|
+
};
|
|
14
|
+
if (isOpen) {
|
|
15
|
+
document.addEventListener("keydown", handleEscape);
|
|
16
|
+
document.body.style.overflow = "hidden";
|
|
17
|
+
}
|
|
18
|
+
return () => {
|
|
19
|
+
document.removeEventListener("keydown", handleEscape);
|
|
20
|
+
document.body.style.overflow = "unset";
|
|
21
|
+
};
|
|
22
|
+
}, [isOpen, onClose]);
|
|
23
|
+
if (!isOpen) return null;
|
|
24
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
25
|
+
/* @__PURE__ */ jsx(
|
|
26
|
+
"div",
|
|
27
|
+
{
|
|
28
|
+
className: "absolute inset-0 bg-black/50 backdrop-blur-sm",
|
|
29
|
+
onClick: onClose
|
|
30
|
+
}
|
|
31
|
+
),
|
|
32
|
+
/* @__PURE__ */ jsxs(
|
|
33
|
+
"div",
|
|
34
|
+
{
|
|
35
|
+
className: `relative bg-white dark:bg-gray-900 rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto ${className}`,
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700", children: [
|
|
38
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold", children: title }),
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
"button",
|
|
41
|
+
{
|
|
42
|
+
onClick: onClose,
|
|
43
|
+
className: "text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors",
|
|
44
|
+
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" }) })
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
] }),
|
|
48
|
+
/* @__PURE__ */ jsx("div", { className: "p-6", children })
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
] });
|
|
53
|
+
}
|
|
54
|
+
function PaymentForm({ customerId, onSuccess, onCancel, onSubmit }) {
|
|
55
|
+
const stripe = useStripe();
|
|
56
|
+
const elements = useElements();
|
|
57
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
58
|
+
const [errorMessage, setErrorMessage] = useState(null);
|
|
59
|
+
const [setAsDefault, setSetAsDefault] = useState(false);
|
|
60
|
+
const handleSubmit = async (e) => {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
if (!stripe || !elements) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
setIsProcessing(true);
|
|
66
|
+
setErrorMessage(null);
|
|
67
|
+
try {
|
|
68
|
+
const { error: submitError } = await elements.submit();
|
|
69
|
+
if (submitError) {
|
|
70
|
+
setErrorMessage(submitError.message || "Failed to validate payment details");
|
|
71
|
+
setIsProcessing(false);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const { error, paymentMethod } = await stripe.createPaymentMethod({
|
|
75
|
+
elements
|
|
76
|
+
});
|
|
77
|
+
if (error) {
|
|
78
|
+
setErrorMessage(error.message || "Failed to create payment method");
|
|
79
|
+
setIsProcessing(false);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const result = await onSubmit(paymentMethod.id, setAsDefault);
|
|
83
|
+
if (!result.success) {
|
|
84
|
+
throw new Error(result.error || "Failed to add payment method");
|
|
85
|
+
}
|
|
86
|
+
onSuccess();
|
|
87
|
+
} catch (error) {
|
|
88
|
+
setErrorMessage(error instanceof Error ? error.message : String(error) || "An error occurred");
|
|
89
|
+
setIsProcessing(false);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
93
|
+
/* @__PURE__ */ jsx(PaymentElement, {}),
|
|
94
|
+
errorMessage && /* @__PURE__ */ jsx("div", { className: "text-red-600 dark:text-red-400 text-sm", children: errorMessage }),
|
|
95
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-2", children: [
|
|
96
|
+
/* @__PURE__ */ jsx(
|
|
97
|
+
"input",
|
|
98
|
+
{
|
|
99
|
+
type: "checkbox",
|
|
100
|
+
id: "setDefault",
|
|
101
|
+
checked: setAsDefault,
|
|
102
|
+
onChange: (e) => setSetAsDefault(e.target.checked),
|
|
103
|
+
className: "w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
/* @__PURE__ */ jsx(
|
|
107
|
+
"label",
|
|
108
|
+
{
|
|
109
|
+
htmlFor: "setDefault",
|
|
110
|
+
className: "text-sm text-gray-600 dark:text-gray-400",
|
|
111
|
+
children: "Set as default payment method"
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
] }),
|
|
115
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
|
|
116
|
+
/* @__PURE__ */ jsx(
|
|
117
|
+
Button,
|
|
118
|
+
{
|
|
119
|
+
type: "button",
|
|
120
|
+
variant: "secondary",
|
|
121
|
+
onClick: onCancel,
|
|
122
|
+
disabled: isProcessing,
|
|
123
|
+
children: "Cancel"
|
|
124
|
+
}
|
|
125
|
+
),
|
|
126
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", variant: "primary", disabled: !stripe || isProcessing, children: isProcessing ? "Processing..." : "Add Payment Method" })
|
|
127
|
+
] })
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
function AddPaymentMethodForm({
|
|
131
|
+
customerId,
|
|
132
|
+
stripePublishableKey,
|
|
133
|
+
onSuccess,
|
|
134
|
+
onCancel,
|
|
135
|
+
onSubmit
|
|
136
|
+
}) {
|
|
137
|
+
const [stripePromise, setStripePromise] = useState(null);
|
|
138
|
+
const [theme, setTheme] = useState("light");
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
if (stripePublishableKey) {
|
|
141
|
+
setStripePromise(loadStripe(stripePublishableKey));
|
|
142
|
+
}
|
|
143
|
+
}, [stripePublishableKey]);
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
const isDark = document.documentElement.classList.contains("dark") || window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
146
|
+
setTheme(isDark ? "dark" : "light");
|
|
147
|
+
const observer = new MutationObserver(() => {
|
|
148
|
+
const isDark2 = document.documentElement.classList.contains("dark");
|
|
149
|
+
setTheme(isDark2 ? "dark" : "light");
|
|
150
|
+
});
|
|
151
|
+
observer.observe(document.documentElement, {
|
|
152
|
+
attributes: true,
|
|
153
|
+
attributeFilter: ["class"]
|
|
154
|
+
});
|
|
155
|
+
return () => observer.disconnect();
|
|
156
|
+
}, []);
|
|
157
|
+
const stripeOptions = useMemo(() => ({
|
|
158
|
+
mode: "setup",
|
|
159
|
+
currency: "usd",
|
|
160
|
+
paymentMethodCreation: "manual",
|
|
161
|
+
appearance: {
|
|
162
|
+
theme: theme === "dark" ? "night" : "stripe",
|
|
163
|
+
variables: {
|
|
164
|
+
colorPrimary: "#3b82f6",
|
|
165
|
+
colorBackground: theme === "dark" ? "#1f2937" : "#ffffff",
|
|
166
|
+
colorText: theme === "dark" ? "#f9fafb" : "#1f2937",
|
|
167
|
+
colorDanger: "#ef4444",
|
|
168
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
169
|
+
spacingUnit: "4px",
|
|
170
|
+
borderRadius: "6px"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}), [theme]);
|
|
174
|
+
if (!stripePromise) {
|
|
175
|
+
return /* @__PURE__ */ jsx("div", { className: "text-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: "Loading..." }) });
|
|
176
|
+
}
|
|
177
|
+
return /* @__PURE__ */ jsx(Elements, { stripe: stripePromise, options: stripeOptions, children: /* @__PURE__ */ jsx(
|
|
178
|
+
PaymentForm,
|
|
179
|
+
{
|
|
180
|
+
customerId,
|
|
181
|
+
onSuccess,
|
|
182
|
+
onCancel,
|
|
183
|
+
onSubmit
|
|
184
|
+
}
|
|
185
|
+
) });
|
|
186
|
+
}
|
|
7
187
|
|
|
8
188
|
// src/components/server/Billing/actions.ts
|
|
9
189
|
function createHeaders(config) {
|
|
@@ -35,6 +215,26 @@ async function fetchAPI(config, url, options = {}) {
|
|
|
35
215
|
};
|
|
36
216
|
}
|
|
37
217
|
}
|
|
218
|
+
async function addPaymentMethod(config, customerId, stripePaymentMethodId, setAsDefault = false) {
|
|
219
|
+
const { baseUrl, projectId } = config;
|
|
220
|
+
const result = await fetchAPI(
|
|
221
|
+
config,
|
|
222
|
+
`${baseUrl}/billing/customers/${customerId}/payment-methods`,
|
|
223
|
+
{
|
|
224
|
+
method: "POST",
|
|
225
|
+
body: JSON.stringify({
|
|
226
|
+
project_id: projectId,
|
|
227
|
+
type: "card",
|
|
228
|
+
stripe_payment_method_id: stripePaymentMethodId,
|
|
229
|
+
set_as_default: setAsDefault
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
if (!result.success) {
|
|
234
|
+
return { success: false, error: result.error || "Failed to add payment method" };
|
|
235
|
+
}
|
|
236
|
+
return { success: true, data: result.data };
|
|
237
|
+
}
|
|
38
238
|
async function removePaymentMethod(config, customerId, paymentMethodId) {
|
|
39
239
|
const { baseUrl, projectId } = config;
|
|
40
240
|
const isStripeId = paymentMethodId.startsWith("pm_");
|
|
@@ -140,6 +340,17 @@ async function updateSubscription(config, subscriptionId, newPriceId) {
|
|
|
140
340
|
}
|
|
141
341
|
return { success: true, data: result.data };
|
|
142
342
|
}
|
|
343
|
+
async function fetchPaymentConfig(config) {
|
|
344
|
+
const { baseUrl, projectId } = config;
|
|
345
|
+
const result = await fetchAPI(
|
|
346
|
+
config,
|
|
347
|
+
`${baseUrl}/billing/payment-config?project_id=${projectId}&test_mode=true`
|
|
348
|
+
);
|
|
349
|
+
if (!result.success) {
|
|
350
|
+
return { success: false, error: result.error || "Failed to fetch payment configuration" };
|
|
351
|
+
}
|
|
352
|
+
return { success: true, data: result.data };
|
|
353
|
+
}
|
|
143
354
|
function UsageBar({ label, used, limit, unit = "" }) {
|
|
144
355
|
const percentage = limit > 0 ? used / limit * 100 : 0;
|
|
145
356
|
const isWarning = percentage > 80;
|
|
@@ -180,6 +391,28 @@ function BillingContent({
|
|
|
180
391
|
const [isLoading, setIsLoading] = useState(false);
|
|
181
392
|
const [error, setError] = useState(null);
|
|
182
393
|
const [success, setSuccess] = useState(null);
|
|
394
|
+
const [isAddPaymentModalOpen, setIsAddPaymentModalOpen] = useState(false);
|
|
395
|
+
const [isRemovePaymentModalOpen, setIsRemovePaymentModalOpen] = useState(false);
|
|
396
|
+
const [isCancelModalOpen, setIsCancelModalOpen] = useState(false);
|
|
397
|
+
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(null);
|
|
398
|
+
const [stripePublishableKey, setStripePublishableKey] = useState(null);
|
|
399
|
+
const [stripeLoading, setStripeLoading] = useState(false);
|
|
400
|
+
useEffect(() => {
|
|
401
|
+
async function loadStripeConfig() {
|
|
402
|
+
setStripeLoading(true);
|
|
403
|
+
try {
|
|
404
|
+
const result = await fetchPaymentConfig(actionConfig);
|
|
405
|
+
if (result.success && result.data?.publishable_key) {
|
|
406
|
+
setStripePublishableKey(result.data.publishable_key);
|
|
407
|
+
}
|
|
408
|
+
} catch (err) {
|
|
409
|
+
console.error("Failed to load Stripe config:", err);
|
|
410
|
+
} finally {
|
|
411
|
+
setStripeLoading(false);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
loadStripeConfig();
|
|
415
|
+
}, [actionConfig]);
|
|
183
416
|
const handleCancelSubscription = async () => {
|
|
184
417
|
if (!subscription) return;
|
|
185
418
|
setIsLoading(true);
|
|
@@ -189,6 +422,33 @@ function BillingContent({
|
|
|
189
422
|
setError(result.error || "Failed to cancel subscription");
|
|
190
423
|
} else {
|
|
191
424
|
setSuccess("Subscription will be canceled at the end of the billing period");
|
|
425
|
+
setIsCancelModalOpen(false);
|
|
426
|
+
}
|
|
427
|
+
setIsLoading(false);
|
|
428
|
+
};
|
|
429
|
+
const handleAddPaymentMethod = async (stripePaymentMethodId, setAsDefault) => {
|
|
430
|
+
const result = await addPaymentMethod(actionConfig, customer.id, stripePaymentMethodId, setAsDefault);
|
|
431
|
+
return result;
|
|
432
|
+
};
|
|
433
|
+
const handleAddPaymentSuccess = () => {
|
|
434
|
+
setIsAddPaymentModalOpen(false);
|
|
435
|
+
setSuccess("Payment method added successfully");
|
|
436
|
+
};
|
|
437
|
+
const handleRemovePaymentClick = (pm) => {
|
|
438
|
+
setSelectedPaymentMethod(pm);
|
|
439
|
+
setIsRemovePaymentModalOpen(true);
|
|
440
|
+
};
|
|
441
|
+
const handleConfirmRemovePayment = async () => {
|
|
442
|
+
if (!selectedPaymentMethod) return;
|
|
443
|
+
setIsLoading(true);
|
|
444
|
+
setError(null);
|
|
445
|
+
const result = await removePaymentMethod(actionConfig, customer.id, String(selectedPaymentMethod.id));
|
|
446
|
+
if (!result.success) {
|
|
447
|
+
setError(result.error || "Failed to remove payment method");
|
|
448
|
+
} else {
|
|
449
|
+
setSuccess("Payment method removed");
|
|
450
|
+
setIsRemovePaymentModalOpen(false);
|
|
451
|
+
setSelectedPaymentMethod(null);
|
|
192
452
|
}
|
|
193
453
|
setIsLoading(false);
|
|
194
454
|
};
|
|
@@ -213,17 +473,6 @@ function BillingContent({
|
|
|
213
473
|
}
|
|
214
474
|
setIsLoading(false);
|
|
215
475
|
};
|
|
216
|
-
const handleRemovePaymentMethod = async (pmId) => {
|
|
217
|
-
setIsLoading(true);
|
|
218
|
-
setError(null);
|
|
219
|
-
const result = await removePaymentMethod(actionConfig, customer.id, String(pmId));
|
|
220
|
-
if (!result.success) {
|
|
221
|
-
setError(result.error || "Failed to remove payment method");
|
|
222
|
-
} else {
|
|
223
|
-
setSuccess("Payment method removed");
|
|
224
|
-
}
|
|
225
|
-
setIsLoading(false);
|
|
226
|
-
};
|
|
227
476
|
const handleSetDefaultPaymentMethod = async (pmId) => {
|
|
228
477
|
setIsLoading(true);
|
|
229
478
|
setError(null);
|
|
@@ -269,7 +518,7 @@ function BillingContent({
|
|
|
269
518
|
Button,
|
|
270
519
|
{
|
|
271
520
|
variant: "secondary",
|
|
272
|
-
onClick:
|
|
521
|
+
onClick: () => setIsCancelModalOpen(true),
|
|
273
522
|
disabled: isLoading,
|
|
274
523
|
children: "Cancel"
|
|
275
524
|
}
|
|
@@ -413,7 +662,7 @@ function BillingContent({
|
|
|
413
662
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400 mb-6", children: "Manage your payment methods" }),
|
|
414
663
|
paymentMethods.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8 border border-dashed border-gray-300 dark:border-neutral-700 rounded-lg", children: [
|
|
415
664
|
/* @__PURE__ */ jsx("p", { className: "text-gray-500 dark:text-gray-400 mb-4", children: "No payment methods on file" }),
|
|
416
|
-
/* @__PURE__ */ jsx(Button, { children: "Add Payment Method" })
|
|
665
|
+
/* @__PURE__ */ jsx(Button, { onClick: () => setIsAddPaymentModalOpen(true), disabled: stripeLoading, children: stripeLoading ? "Loading..." : "Add Payment Method" })
|
|
417
666
|
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
418
667
|
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: [
|
|
419
668
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
@@ -451,21 +700,145 @@ function BillingContent({
|
|
|
451
700
|
{
|
|
452
701
|
variant: "secondary",
|
|
453
702
|
size: "sm",
|
|
454
|
-
onClick: () =>
|
|
703
|
+
onClick: () => handleRemovePaymentClick(pm),
|
|
455
704
|
disabled: isLoading,
|
|
456
705
|
children: "Remove"
|
|
457
706
|
}
|
|
458
707
|
)
|
|
459
708
|
] })
|
|
460
709
|
] }, pm.id)),
|
|
461
|
-
/* @__PURE__ */ jsx(
|
|
710
|
+
/* @__PURE__ */ jsx(
|
|
711
|
+
Button,
|
|
712
|
+
{
|
|
713
|
+
variant: "secondary",
|
|
714
|
+
className: "w-full mt-4",
|
|
715
|
+
onClick: () => setIsAddPaymentModalOpen(true),
|
|
716
|
+
disabled: stripeLoading,
|
|
717
|
+
children: stripeLoading ? "Loading..." : "Add Payment Method"
|
|
718
|
+
}
|
|
719
|
+
)
|
|
462
720
|
] })
|
|
463
721
|
] }) })
|
|
464
722
|
}
|
|
465
723
|
];
|
|
466
|
-
return /* @__PURE__ */
|
|
724
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
725
|
+
/* @__PURE__ */ jsx(Tabs, { tabs, defaultIndex: 0 }),
|
|
726
|
+
/* @__PURE__ */ jsx(
|
|
727
|
+
Modal,
|
|
728
|
+
{
|
|
729
|
+
isOpen: isAddPaymentModalOpen,
|
|
730
|
+
onClose: () => setIsAddPaymentModalOpen(false),
|
|
731
|
+
title: "Add Payment Method",
|
|
732
|
+
children: stripePublishableKey ? /* @__PURE__ */ jsx(
|
|
733
|
+
AddPaymentMethodForm,
|
|
734
|
+
{
|
|
735
|
+
customerId: customer.id,
|
|
736
|
+
stripePublishableKey,
|
|
737
|
+
onSuccess: handleAddPaymentSuccess,
|
|
738
|
+
onCancel: () => setIsAddPaymentModalOpen(false),
|
|
739
|
+
onSubmit: handleAddPaymentMethod
|
|
740
|
+
}
|
|
741
|
+
) : /* @__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" }) })
|
|
742
|
+
}
|
|
743
|
+
),
|
|
744
|
+
/* @__PURE__ */ jsx(
|
|
745
|
+
Modal,
|
|
746
|
+
{
|
|
747
|
+
isOpen: isRemovePaymentModalOpen,
|
|
748
|
+
onClose: () => {
|
|
749
|
+
setIsRemovePaymentModalOpen(false);
|
|
750
|
+
setSelectedPaymentMethod(null);
|
|
751
|
+
},
|
|
752
|
+
title: "Remove Payment Method",
|
|
753
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
754
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: "Are you sure you want to remove this payment method?" }),
|
|
755
|
+
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: [
|
|
756
|
+
/* @__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" }) }) }),
|
|
757
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
758
|
+
/* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-900 dark:text-white", children: selectedPaymentMethod.card_brand || "Card" }),
|
|
759
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: [
|
|
760
|
+
"\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 ",
|
|
761
|
+
selectedPaymentMethod.card_last4 || "****"
|
|
762
|
+
] })
|
|
763
|
+
] })
|
|
764
|
+
] }) }),
|
|
765
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "This action cannot be undone." }),
|
|
766
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
|
|
767
|
+
/* @__PURE__ */ jsx(
|
|
768
|
+
Button,
|
|
769
|
+
{
|
|
770
|
+
variant: "secondary",
|
|
771
|
+
onClick: () => {
|
|
772
|
+
setIsRemovePaymentModalOpen(false);
|
|
773
|
+
setSelectedPaymentMethod(null);
|
|
774
|
+
},
|
|
775
|
+
disabled: isLoading,
|
|
776
|
+
children: "Cancel"
|
|
777
|
+
}
|
|
778
|
+
),
|
|
779
|
+
/* @__PURE__ */ jsx(
|
|
780
|
+
Button,
|
|
781
|
+
{
|
|
782
|
+
variant: "primary",
|
|
783
|
+
onClick: handleConfirmRemovePayment,
|
|
784
|
+
disabled: isLoading,
|
|
785
|
+
children: isLoading ? "Removing..." : "Remove Payment Method"
|
|
786
|
+
}
|
|
787
|
+
)
|
|
788
|
+
] })
|
|
789
|
+
] })
|
|
790
|
+
}
|
|
791
|
+
),
|
|
792
|
+
/* @__PURE__ */ jsx(
|
|
793
|
+
Modal,
|
|
794
|
+
{
|
|
795
|
+
isOpen: isCancelModalOpen,
|
|
796
|
+
onClose: () => setIsCancelModalOpen(false),
|
|
797
|
+
title: "Cancel Subscription",
|
|
798
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
799
|
+
/* @__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: [
|
|
800
|
+
/* @__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" }) }),
|
|
801
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
802
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-yellow-900 dark:text-yellow-100 mb-1", children: "Are you sure you want to cancel?" }),
|
|
803
|
+
/* @__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." })
|
|
804
|
+
] })
|
|
805
|
+
] }),
|
|
806
|
+
subscription && /* @__PURE__ */ jsxs("div", { className: "bg-gray-50 dark:bg-gray-800 rounded-lg p-4", children: [
|
|
807
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
808
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Current Plan:" }),
|
|
809
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: subscription.plan })
|
|
810
|
+
] }),
|
|
811
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm mt-2", children: [
|
|
812
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Access Until:" }),
|
|
813
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: subscription.nextBilling })
|
|
814
|
+
] })
|
|
815
|
+
] }),
|
|
816
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
|
|
817
|
+
/* @__PURE__ */ jsx(
|
|
818
|
+
Button,
|
|
819
|
+
{
|
|
820
|
+
variant: "secondary",
|
|
821
|
+
onClick: () => setIsCancelModalOpen(false),
|
|
822
|
+
disabled: isLoading,
|
|
823
|
+
children: "Keep Subscription"
|
|
824
|
+
}
|
|
825
|
+
),
|
|
826
|
+
/* @__PURE__ */ jsx(
|
|
827
|
+
Button,
|
|
828
|
+
{
|
|
829
|
+
variant: "primary",
|
|
830
|
+
onClick: handleCancelSubscription,
|
|
831
|
+
disabled: isLoading,
|
|
832
|
+
children: isLoading ? "Canceling..." : "Yes, Cancel Subscription"
|
|
833
|
+
}
|
|
834
|
+
)
|
|
835
|
+
] })
|
|
836
|
+
] })
|
|
837
|
+
}
|
|
838
|
+
)
|
|
839
|
+
] });
|
|
467
840
|
}
|
|
468
841
|
|
|
469
|
-
export { BillingContent };
|
|
470
|
-
//# sourceMappingURL=chunk-
|
|
471
|
-
//# sourceMappingURL=chunk-
|
|
842
|
+
export { AddPaymentMethodForm, BillingContent, Modal };
|
|
843
|
+
//# sourceMappingURL=chunk-2KDIPVL3.js.map
|
|
844
|
+
//# sourceMappingURL=chunk-2KDIPVL3.js.map
|