@thinkingcat/subscription-ui 1.0.4 → 1.0.6
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/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +191 -60
- package/dist/index.mjs +191 -60
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -85,6 +85,8 @@ interface SubscriptionManagementConfig {
|
|
|
85
85
|
subscriptionsApiPath?: string;
|
|
86
86
|
/** 결제 이력/취소 API 경로 (default: /api/subscribe/payments) */
|
|
87
87
|
paymentsApiPath?: string;
|
|
88
|
+
/** 카드 조회/등록/삭제 API 경로 (default: /api/subscribe/cards) */
|
|
89
|
+
cardsApiPath?: string;
|
|
88
90
|
/** 브랜드 색상 (default: #60A5FA) */
|
|
89
91
|
primaryColor?: string;
|
|
90
92
|
/** 테마 (default: "system") */
|
|
@@ -93,6 +95,6 @@ interface SubscriptionManagementConfig {
|
|
|
93
95
|
|
|
94
96
|
declare function SubscribePage({ plansApiPath, cardsApiPath, payApiPath, callbackUrl, serviceName, primaryColor, showExpiredBanner, theme, }: SubscribePageConfig): react_jsx_runtime.JSX.Element;
|
|
95
97
|
|
|
96
|
-
declare function SubscriptionManagement({ subscriptionsApiPath, paymentsApiPath, primaryColor, theme, }: SubscriptionManagementConfig): react_jsx_runtime.JSX.Element;
|
|
98
|
+
declare function SubscriptionManagement({ subscriptionsApiPath, paymentsApiPath, cardsApiPath, primaryColor, theme, }: SubscriptionManagementConfig): react_jsx_runtime.JSX.Element;
|
|
97
99
|
|
|
98
100
|
export { type Card, type Payment, type Plan, SubscribePage, type SubscribePageConfig, type Subscription, SubscriptionManagement, type SubscriptionManagementConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -85,6 +85,8 @@ interface SubscriptionManagementConfig {
|
|
|
85
85
|
subscriptionsApiPath?: string;
|
|
86
86
|
/** 결제 이력/취소 API 경로 (default: /api/subscribe/payments) */
|
|
87
87
|
paymentsApiPath?: string;
|
|
88
|
+
/** 카드 조회/등록/삭제 API 경로 (default: /api/subscribe/cards) */
|
|
89
|
+
cardsApiPath?: string;
|
|
88
90
|
/** 브랜드 색상 (default: #60A5FA) */
|
|
89
91
|
primaryColor?: string;
|
|
90
92
|
/** 테마 (default: "system") */
|
|
@@ -93,6 +95,6 @@ interface SubscriptionManagementConfig {
|
|
|
93
95
|
|
|
94
96
|
declare function SubscribePage({ plansApiPath, cardsApiPath, payApiPath, callbackUrl, serviceName, primaryColor, showExpiredBanner, theme, }: SubscribePageConfig): react_jsx_runtime.JSX.Element;
|
|
95
97
|
|
|
96
|
-
declare function SubscriptionManagement({ subscriptionsApiPath, paymentsApiPath, primaryColor, theme, }: SubscriptionManagementConfig): react_jsx_runtime.JSX.Element;
|
|
98
|
+
declare function SubscriptionManagement({ subscriptionsApiPath, paymentsApiPath, cardsApiPath, primaryColor, theme, }: SubscriptionManagementConfig): react_jsx_runtime.JSX.Element;
|
|
97
99
|
|
|
98
100
|
export { type Card, type Payment, type Plan, SubscribePage, type SubscribePageConfig, type Subscription, SubscriptionManagement, type SubscriptionManagementConfig };
|
package/dist/index.js
CHANGED
|
@@ -421,20 +421,32 @@ var DEFAULT_PRIMARY2 = "#60A5FA";
|
|
|
421
421
|
function SubscriptionManagement({
|
|
422
422
|
subscriptionsApiPath = "/api/subscribe/subscriptions",
|
|
423
423
|
paymentsApiPath = "/api/subscribe/payments",
|
|
424
|
+
cardsApiPath = "/api/subscribe/cards",
|
|
424
425
|
primaryColor = DEFAULT_PRIMARY2,
|
|
425
426
|
theme = "system"
|
|
426
427
|
}) {
|
|
427
428
|
const [tab, setTab] = (0, import_react2.useState)("subscription");
|
|
428
429
|
const [subscriptions, setSubscriptions] = (0, import_react2.useState)([]);
|
|
429
430
|
const [payments, setPayments] = (0, import_react2.useState)([]);
|
|
431
|
+
const [cards, setCards] = (0, import_react2.useState)([]);
|
|
430
432
|
const [loading, setLoading] = (0, import_react2.useState)(true);
|
|
431
433
|
const [error, setError] = (0, import_react2.useState)("");
|
|
432
434
|
const [actionLoading, setActionLoading] = (0, import_react2.useState)(null);
|
|
433
435
|
const [confirmModal, setConfirmModal] = (0, import_react2.useState)(null);
|
|
436
|
+
const [showCardForm, setShowCardForm] = (0, import_react2.useState)(false);
|
|
437
|
+
const [cardForm, setCardForm] = (0, import_react2.useState)({
|
|
438
|
+
cardNumber: "",
|
|
439
|
+
expiryDate: "",
|
|
440
|
+
cvc: "",
|
|
441
|
+
cardPassword: "",
|
|
442
|
+
cardHolderName: "",
|
|
443
|
+
birthNumber: ""
|
|
444
|
+
});
|
|
445
|
+
const [cardError, setCardError] = (0, import_react2.useState)("");
|
|
446
|
+
const [cardSubmitting, setCardSubmitting] = (0, import_react2.useState)(false);
|
|
434
447
|
const themeClass = theme === "dark" ? "dark" : theme === "light" ? "light-mode-override" : "";
|
|
435
448
|
(0, import_react2.useEffect)(() => {
|
|
436
|
-
fetchSubscriptions();
|
|
437
|
-
fetchPayments();
|
|
449
|
+
Promise.all([fetchSubscriptions(), fetchPayments(), fetchCards()]).finally(() => setLoading(false));
|
|
438
450
|
}, []);
|
|
439
451
|
async function fetchSubscriptions() {
|
|
440
452
|
try {
|
|
@@ -442,8 +454,6 @@ function SubscriptionManagement({
|
|
|
442
454
|
const data = await res.json();
|
|
443
455
|
if (data.success) setSubscriptions(data.subscriptions);
|
|
444
456
|
} catch {
|
|
445
|
-
} finally {
|
|
446
|
-
setLoading(false);
|
|
447
457
|
}
|
|
448
458
|
}
|
|
449
459
|
async function fetchPayments() {
|
|
@@ -454,6 +464,14 @@ function SubscriptionManagement({
|
|
|
454
464
|
} catch {
|
|
455
465
|
}
|
|
456
466
|
}
|
|
467
|
+
async function fetchCards() {
|
|
468
|
+
try {
|
|
469
|
+
const res = await fetch(cardsApiPath);
|
|
470
|
+
const data = await res.json();
|
|
471
|
+
if (data.success) setCards(data.cards);
|
|
472
|
+
} catch {
|
|
473
|
+
}
|
|
474
|
+
}
|
|
457
475
|
async function handleCancelSubscription(subscriptionId) {
|
|
458
476
|
setActionLoading(subscriptionId);
|
|
459
477
|
setError("");
|
|
@@ -490,8 +508,7 @@ function SubscriptionManagement({
|
|
|
490
508
|
setError(data.error || "\uACB0\uC81C \uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
491
509
|
return;
|
|
492
510
|
}
|
|
493
|
-
await fetchPayments();
|
|
494
|
-
await fetchSubscriptions();
|
|
511
|
+
await Promise.all([fetchPayments(), fetchSubscriptions()]);
|
|
495
512
|
} catch {
|
|
496
513
|
setError("\uACB0\uC81C \uCDE8\uC18C \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
497
514
|
} finally {
|
|
@@ -499,6 +516,51 @@ function SubscriptionManagement({
|
|
|
499
516
|
setConfirmModal(null);
|
|
500
517
|
}
|
|
501
518
|
}
|
|
519
|
+
async function handleDeleteCard(cardId) {
|
|
520
|
+
setActionLoading(cardId);
|
|
521
|
+
setError("");
|
|
522
|
+
try {
|
|
523
|
+
const res = await fetch(cardsApiPath, {
|
|
524
|
+
method: "DELETE",
|
|
525
|
+
headers: { "Content-Type": "application/json" },
|
|
526
|
+
body: JSON.stringify({ cardId })
|
|
527
|
+
});
|
|
528
|
+
const data = await res.json();
|
|
529
|
+
if (!data.success) {
|
|
530
|
+
setError(data.error || "\uCE74\uB4DC \uC0AD\uC81C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
await fetchCards();
|
|
534
|
+
} catch {
|
|
535
|
+
setError("\uCE74\uB4DC \uC0AD\uC81C \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
536
|
+
} finally {
|
|
537
|
+
setActionLoading(null);
|
|
538
|
+
setConfirmModal(null);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
async function handleRegisterCard() {
|
|
542
|
+
setCardError("");
|
|
543
|
+
setCardSubmitting(true);
|
|
544
|
+
try {
|
|
545
|
+
const res = await fetch(cardsApiPath, {
|
|
546
|
+
method: "POST",
|
|
547
|
+
headers: { "Content-Type": "application/json" },
|
|
548
|
+
body: JSON.stringify(cardForm)
|
|
549
|
+
});
|
|
550
|
+
const data = await res.json();
|
|
551
|
+
if (!data.success) {
|
|
552
|
+
setCardError(data.error || "\uCE74\uB4DC \uB4F1\uB85D\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
await fetchCards();
|
|
556
|
+
setShowCardForm(false);
|
|
557
|
+
setCardForm({ cardNumber: "", expiryDate: "", cvc: "", cardPassword: "", cardHolderName: "", birthNumber: "" });
|
|
558
|
+
} catch {
|
|
559
|
+
setCardError("\uCE74\uB4DC \uB4F1\uB85D \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
560
|
+
} finally {
|
|
561
|
+
setCardSubmitting(false);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
502
564
|
function fmt(price) {
|
|
503
565
|
return price.toLocaleString("ko-KR") + "\uC6D0";
|
|
504
566
|
}
|
|
@@ -506,35 +568,39 @@ function SubscriptionManagement({
|
|
|
506
568
|
return new Date(dateStr).toLocaleDateString("ko-KR", { year: "numeric", month: "long", day: "numeric" });
|
|
507
569
|
}
|
|
508
570
|
function statusBadge(status) {
|
|
509
|
-
if (status === "ACTIVE") return {
|
|
510
|
-
if (status === "CANCELLED") return {
|
|
511
|
-
return {
|
|
571
|
+
if (status === "ACTIVE") return { cls: "bg-green-100 dark:bg-green-500/20 text-green-700 dark:text-green-400", label: "\uD65C\uC131" };
|
|
572
|
+
if (status === "CANCELLED") return { cls: "bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400", label: "\uCDE8\uC18C\uB428" };
|
|
573
|
+
return { cls: "bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400", label: status };
|
|
512
574
|
}
|
|
513
575
|
function paymentStatusBadge(status) {
|
|
514
|
-
if (status === "COMPLETED") return {
|
|
515
|
-
if (status === "CANCELLED") return {
|
|
516
|
-
if (status === "FAILED") return {
|
|
517
|
-
return {
|
|
576
|
+
if (status === "COMPLETED") return { cls: "bg-green-100 dark:bg-green-500/20 text-green-700 dark:text-green-400", label: "\uC644\uB8CC" };
|
|
577
|
+
if (status === "CANCELLED") return { cls: "bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400", label: "\uCDE8\uC18C\uB428" };
|
|
578
|
+
if (status === "FAILED") return { cls: "bg-orange-100 dark:bg-orange-500/20 text-orange-700 dark:text-orange-400", label: "\uC2E4\uD328" };
|
|
579
|
+
return { cls: "bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400", label: status };
|
|
518
580
|
}
|
|
519
581
|
function canCancelPayment(p) {
|
|
520
582
|
if (p.status !== "COMPLETED") return false;
|
|
521
|
-
const
|
|
522
|
-
const daysDiff = Math.ceil((Date.now() - paidDate.getTime()) / (1e3 * 3600 * 24));
|
|
583
|
+
const daysDiff = Math.ceil((Date.now() - new Date(p.paidAt || p.createdAt).getTime()) / (1e3 * 3600 * 24));
|
|
523
584
|
return daysDiff <= 7;
|
|
524
585
|
}
|
|
525
586
|
if (loading) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: themeClass, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-gray-400 py-8 text-center", children: "\uBD88\uB7EC\uC624\uB294 \uC911..." }) });
|
|
587
|
+
const tabs = [
|
|
588
|
+
{ key: "subscription", label: "\uAD6C\uB3C5 \uC815\uBCF4" },
|
|
589
|
+
{ key: "cards", label: "\uACB0\uC81C\uC218\uB2E8" },
|
|
590
|
+
{ key: "payments", label: "\uACB0\uC81C \uC774\uB825" }
|
|
591
|
+
];
|
|
526
592
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: themeClass, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-4", children: [
|
|
527
593
|
error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "p-3 bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/30 rounded-lg text-red-600 dark:text-red-400 text-sm", children: error }),
|
|
528
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex border-b border-gray-200 dark:border-white/10", children:
|
|
529
|
-
{ key: "subscription", label: "\uAD6C\uB3C5 \uC815\uBCF4" },
|
|
530
|
-
{ key: "payments", label: "\uACB0\uC81C \uC774\uB825" }
|
|
531
|
-
].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
594
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex border-b border-gray-200 dark:border-white/10", children: tabs.map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
532
595
|
"button",
|
|
533
596
|
{
|
|
534
597
|
onClick: () => setTab(key),
|
|
535
|
-
className: `px-4 py-2.5 text-sm font-medium border-b-2 transition-colors -mb-px ${tab === key ? "border-current
|
|
598
|
+
className: `px-4 py-2.5 text-sm font-medium border-b-2 transition-colors -mb-px ${tab === key ? "border-current" : "border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"}`,
|
|
536
599
|
style: tab === key ? { color: primaryColor, borderColor: primaryColor } : void 0,
|
|
537
|
-
children:
|
|
600
|
+
children: [
|
|
601
|
+
label,
|
|
602
|
+
key === "cards" && cards.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-1.5 px-1.5 py-0.5 rounded-full text-xs bg-gray-100 dark:bg-white/10 text-gray-500 dark:text-gray-400", children: cards.length })
|
|
603
|
+
]
|
|
538
604
|
},
|
|
539
605
|
key
|
|
540
606
|
)) }),
|
|
@@ -544,42 +610,16 @@ function SubscriptionManagement({
|
|
|
544
610
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-2 flex-1 min-w-0", children: [
|
|
545
611
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
546
612
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-900 dark:text-white font-semibold text-base", children: sub.plan.name }),
|
|
547
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${badge.
|
|
613
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${badge.cls}`, children: badge.label }),
|
|
548
614
|
sub.isTrial && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 dark:bg-purple-500/20 text-purple-700 dark:text-purple-400", children: "\uCCB4\uD5D8" })
|
|
549
615
|
] }),
|
|
550
616
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-1 text-sm", children: [
|
|
551
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
"\uAC1C\uC6D4"
|
|
558
|
-
] })
|
|
559
|
-
] }),
|
|
560
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
561
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-400 dark:text-gray-500", children: "\uC0C1\uD0DC" }),
|
|
562
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-2 text-gray-700 dark:text-gray-300", children: sub.statusMessage })
|
|
563
|
-
] }),
|
|
564
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
565
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-400 dark:text-gray-500", children: "\uC2DC\uC791\uC77C" }),
|
|
566
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-2 text-gray-700 dark:text-gray-300", children: fmtDate(sub.startDate) })
|
|
567
|
-
] }),
|
|
568
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
569
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-400 dark:text-gray-500", children: "\uB9CC\uB8CC\uC77C" }),
|
|
570
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-2 text-gray-700 dark:text-gray-300", children: fmtDate(sub.endDate) })
|
|
571
|
-
] }),
|
|
572
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
573
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-400 dark:text-gray-500", children: "\uB0A8\uC740 \uAE30\uAC04" }),
|
|
574
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "ml-2 text-gray-700 dark:text-gray-300 font-medium", children: [
|
|
575
|
-
sub.remainingDays,
|
|
576
|
-
"\uC77C"
|
|
577
|
-
] })
|
|
578
|
-
] }),
|
|
579
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
580
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-400 dark:text-gray-500", children: "\uC790\uB3D9\uACB0\uC81C" }),
|
|
581
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-2 text-gray-700 dark:text-gray-300", children: sub.autoRenew ? "\uC0AC\uC6A9" : "\uD574\uC81C" })
|
|
582
|
-
] })
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(InfoRow, { label: "\uAE08\uC561", value: `${fmt(sub.plan.price)} / ${sub.plan.interval}\uAC1C\uC6D4`, bold: true }),
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(InfoRow, { label: "\uC0C1\uD0DC", value: sub.statusMessage }),
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(InfoRow, { label: "\uC2DC\uC791\uC77C", value: fmtDate(sub.startDate) }),
|
|
620
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(InfoRow, { label: "\uB9CC\uB8CC\uC77C", value: fmtDate(sub.endDate) }),
|
|
621
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(InfoRow, { label: "\uB0A8\uC740 \uAE30\uAC04", value: `${sub.remainingDays}\uC77C`, bold: true }),
|
|
622
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(InfoRow, { label: "\uC790\uB3D9\uACB0\uC81C", value: sub.autoRenew ? "\uC0AC\uC6A9" : "\uD574\uC81C" })
|
|
583
623
|
] })
|
|
584
624
|
] }),
|
|
585
625
|
sub.status === "ACTIVE" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -593,7 +633,92 @@ function SubscriptionManagement({
|
|
|
593
633
|
)
|
|
594
634
|
] }) }, sub.id);
|
|
595
635
|
}) }),
|
|
596
|
-
tab === "
|
|
636
|
+
tab === "cards" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3", children: [
|
|
637
|
+
cards.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-2", children: cards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-4 rounded-xl border border-gray-200 dark:border-white/10 bg-white dark:bg-white/5 flex items-center justify-between gap-3", children: [
|
|
638
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
639
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-10 h-7 rounded bg-gray-100 dark:bg-white/10 flex items-center justify-center text-xs font-bold text-gray-500 dark:text-gray-400 flex-shrink-0", children: card.cardBrand?.slice(0, 4) || "CARD" }),
|
|
640
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "min-w-0", children: [
|
|
641
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-900 dark:text-white font-medium text-sm", children: card.cardBrand }),
|
|
643
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-500 dark:text-gray-400 text-sm", children: card.maskedCardNumber }),
|
|
644
|
+
card.isDefault && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "px-1.5 py-0.5 rounded text-xs font-medium bg-blue-100 dark:bg-blue-500/20 text-blue-600 dark:text-blue-400", children: "\uAE30\uBCF8" })
|
|
645
|
+
] }),
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-xs text-gray-400 dark:text-gray-500 mt-0.5", children: [
|
|
647
|
+
card.cardHolderName,
|
|
648
|
+
" \xB7 ",
|
|
649
|
+
card.expiryMonth,
|
|
650
|
+
"/",
|
|
651
|
+
card.expiryYear
|
|
652
|
+
] })
|
|
653
|
+
] })
|
|
654
|
+
] }),
|
|
655
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
656
|
+
"button",
|
|
657
|
+
{
|
|
658
|
+
onClick: () => setConfirmModal({ type: "delete_card", id: card.id, label: `${card.cardBrand} ${card.maskedCardNumber}` }),
|
|
659
|
+
disabled: actionLoading === card.id,
|
|
660
|
+
className: "text-xs text-red-500 dark:text-red-400 hover:underline disabled:opacity-50 flex-shrink-0",
|
|
661
|
+
children: "\uC0AD\uC81C"
|
|
662
|
+
}
|
|
663
|
+
)
|
|
664
|
+
] }, card.id)) }),
|
|
665
|
+
!showCardForm ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
666
|
+
"button",
|
|
667
|
+
{
|
|
668
|
+
onClick: () => setShowCardForm(true),
|
|
669
|
+
className: "w-full p-4 rounded-xl border border-dashed border-gray-300 dark:border-white/20 text-gray-400 dark:text-gray-500 hover:border-gray-400 dark:hover:border-white/40 hover:text-gray-500 dark:hover:text-gray-300 transition-all text-sm",
|
|
670
|
+
children: "+ \uC0C8 \uCE74\uB4DC \uCD94\uAC00"
|
|
671
|
+
}
|
|
672
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-4 rounded-xl border border-gray-200 dark:border-white/10 bg-gray-50 dark:bg-white/5 space-y-3", children: [
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "text-gray-900 dark:text-white text-sm font-medium", children: "\uCE74\uB4DC \uC815\uBCF4 \uC785\uB825" }),
|
|
674
|
+
cardError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "p-3 bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/30 rounded-lg text-red-600 dark:text-red-400 text-xs", children: cardError }),
|
|
675
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: [
|
|
676
|
+
{ label: "\uCE74\uB4DC \uBC88\uD638", key: "cardNumber", placeholder: "0000-0000-0000-0000", type: "text", full: true },
|
|
677
|
+
{ label: "\uB9CC\uB8CC\uC77C", key: "expiryDate", placeholder: "MM/YY", type: "text", full: false },
|
|
678
|
+
{ label: "CVC", key: "cvc", placeholder: "3\uC790\uB9AC", type: "password", full: false },
|
|
679
|
+
{ label: "\uCE74\uB4DC \uBE44\uBC00\uBC88\uD638 \uC55E 2\uC790\uB9AC", key: "cardPassword", placeholder: "\u2022\u2022", type: "password", full: false },
|
|
680
|
+
{ label: "\uCE74\uB4DC \uC18C\uC720\uC790\uBA85", key: "cardHolderName", placeholder: "\uD64D\uAE38\uB3D9", type: "text", full: false },
|
|
681
|
+
{ label: "\uC0DD\uB144\uC6D4\uC77C 6\uC790\uB9AC / \uC0AC\uC5C5\uC790\uBC88\uD638 10\uC790\uB9AC", key: "birthNumber", placeholder: "990101", type: "text", full: true }
|
|
682
|
+
].map(({ label, key, placeholder, type, full }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: full ? "sm:col-span-2" : "", children: [
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "text-xs text-gray-500 dark:text-gray-400 block mb-1", children: label }),
|
|
684
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
685
|
+
"input",
|
|
686
|
+
{
|
|
687
|
+
type,
|
|
688
|
+
placeholder,
|
|
689
|
+
value: cardForm[key],
|
|
690
|
+
onChange: (e) => setCardForm((f) => ({ ...f, [key]: e.target.value })),
|
|
691
|
+
className: "w-full bg-white dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-lg px-3 py-2 text-gray-900 dark:text-white text-sm placeholder-gray-300 dark:placeholder-gray-600 focus:outline-none focus:border-blue-500 transition-colors"
|
|
692
|
+
}
|
|
693
|
+
)
|
|
694
|
+
] }, key)) }),
|
|
695
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 pt-1", children: [
|
|
696
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
697
|
+
"button",
|
|
698
|
+
{
|
|
699
|
+
onClick: () => {
|
|
700
|
+
setShowCardForm(false);
|
|
701
|
+
setCardError("");
|
|
702
|
+
},
|
|
703
|
+
className: "flex-1 py-2.5 rounded-lg border border-gray-200 dark:border-white/10 text-gray-500 dark:text-gray-400 text-sm hover:border-gray-300 dark:hover:border-white/20 transition-all",
|
|
704
|
+
children: "\uCDE8\uC18C"
|
|
705
|
+
}
|
|
706
|
+
),
|
|
707
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
708
|
+
"button",
|
|
709
|
+
{
|
|
710
|
+
onClick: handleRegisterCard,
|
|
711
|
+
disabled: cardSubmitting,
|
|
712
|
+
style: { backgroundColor: primaryColor },
|
|
713
|
+
className: "flex-1 py-2.5 rounded-lg text-white text-sm font-medium hover:opacity-90 disabled:opacity-50 transition-all",
|
|
714
|
+
children: cardSubmitting ? "\uB4F1\uB85D \uC911..." : "\uCE74\uB4DC \uB4F1\uB85D"
|
|
715
|
+
}
|
|
716
|
+
)
|
|
717
|
+
] })
|
|
718
|
+
] }),
|
|
719
|
+
cards.length === 0 && !showCardForm && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-center py-8 text-gray-400 dark:text-gray-500 text-sm", children: "\uB4F1\uB85D\uB41C \uACB0\uC81C\uC218\uB2E8\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." })
|
|
720
|
+
] }),
|
|
721
|
+
tab === "payments" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-2", children: payments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-center py-12 text-gray-400 dark:text-gray-500 text-sm", children: "\uACB0\uC81C \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "overflow-x-auto -mx-4 sm:mx-0", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("table", { className: "w-full text-sm min-w-[600px]", children: [
|
|
597
722
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: "border-b border-gray-200 dark:border-white/10", children: ["\uC77C\uC2DC", "\uB0B4\uC6A9", "\uAE08\uC561", "\uACB0\uC81C\uC218\uB2E8", "\uC0C1\uD0DC", ""].map((h) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { className: "text-left py-2.5 px-3 text-xs font-medium text-gray-400 dark:text-gray-500 whitespace-nowrap", children: h }, h)) }) }),
|
|
598
723
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { children: payments.map((p) => {
|
|
599
724
|
const badge = paymentStatusBadge(p.status);
|
|
@@ -602,7 +727,7 @@ function SubscriptionManagement({
|
|
|
602
727
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "py-3 px-3 text-gray-900 dark:text-white font-medium", children: p.orderName }),
|
|
603
728
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "py-3 px-3 text-gray-900 dark:text-white font-semibold whitespace-nowrap", children: fmt(p.amount) }),
|
|
604
729
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "py-3 px-3 text-gray-500 dark:text-gray-400 whitespace-nowrap", children: p.cardBrand && p.maskedCardNumber ? `${p.cardBrand} ${p.maskedCardNumber}` : "-" }),
|
|
605
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "py-3 px-3", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${badge.
|
|
730
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "py-3 px-3", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${badge.cls}`, children: badge.label }) }),
|
|
606
731
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "py-3 px-3", children: canCancelPayment(p) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
607
732
|
"button",
|
|
608
733
|
{
|
|
@@ -616,10 +741,10 @@ function SubscriptionManagement({
|
|
|
616
741
|
}) })
|
|
617
742
|
] }) }) }),
|
|
618
743
|
confirmModal && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-white dark:bg-gray-900 rounded-2xl p-6 max-w-sm w-full shadow-xl", children: [
|
|
619
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "text-gray-900 dark:text-white font-semibold text-base mb-2", children: confirmModal.type === "cancel_subscription" ? "\uAD6C\uB3C5 \uCDE8\uC18C" : "\uACB0\uC81C \uCDE8\uC18C" }),
|
|
744
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "text-gray-900 dark:text-white font-semibold text-base mb-2", children: confirmModal.type === "cancel_subscription" ? "\uAD6C\uB3C5 \uCDE8\uC18C" : confirmModal.type === "cancel_payment" ? "\uACB0\uC81C \uCDE8\uC18C" : "\uCE74\uB4DC \uC0AD\uC81C" }),
|
|
620
745
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-gray-500 dark:text-gray-400 text-sm mb-5", children: [
|
|
621
746
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-900 dark:text-white font-medium", children: confirmModal.label }),
|
|
622
|
-
confirmModal.type === "cancel_subscription" ? "\uC744(\uB97C) \uCDE8\uC18C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uD604\uC7AC \uAD6C\uB3C5 \uAE30\uAC04\uC774 \uB05D\uB098\uBA74 \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." : "\uC758 \uACB0\uC81C\uB97C \uCDE8\uC18C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uC774 \uC791\uC5C5\uC740 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
747
|
+
confirmModal.type === "cancel_subscription" ? "\uC744(\uB97C) \uCDE8\uC18C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uD604\uC7AC \uAD6C\uB3C5 \uAE30\uAC04\uC774 \uB05D\uB098\uBA74 \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." : confirmModal.type === "cancel_payment" ? "\uC758 \uACB0\uC81C\uB97C \uCDE8\uC18C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uC774 \uC791\uC5C5\uC740 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." : "\uC744(\uB97C) \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uC0AD\uC81C\uB41C \uCE74\uB4DC\uB294 \uBCF5\uAD6C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
623
748
|
] }),
|
|
624
749
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
|
|
625
750
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -633,16 +758,22 @@ function SubscriptionManagement({
|
|
|
633
758
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
634
759
|
"button",
|
|
635
760
|
{
|
|
636
|
-
onClick: () => confirmModal.type === "cancel_subscription" ? handleCancelSubscription(confirmModal.id) : handleCancelPayment(confirmModal.id),
|
|
761
|
+
onClick: () => confirmModal.type === "cancel_subscription" ? handleCancelSubscription(confirmModal.id) : confirmModal.type === "cancel_payment" ? handleCancelPayment(confirmModal.id) : handleDeleteCard(confirmModal.id),
|
|
637
762
|
disabled: !!actionLoading,
|
|
638
763
|
className: "flex-1 py-2.5 rounded-lg bg-red-500 text-white text-sm font-medium hover:bg-red-600 disabled:opacity-50 transition-all",
|
|
639
|
-
children: actionLoading ? "\uCC98\uB9AC \uC911..." : "\uC608, \
|
|
764
|
+
children: actionLoading ? "\uCC98\uB9AC \uC911..." : "\uC608, \uD655\uC778\uD569\uB2C8\uB2E4"
|
|
640
765
|
}
|
|
641
766
|
)
|
|
642
767
|
] })
|
|
643
768
|
] }) })
|
|
644
769
|
] }) });
|
|
645
770
|
}
|
|
771
|
+
function InfoRow({ label, value, bold }) {
|
|
772
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
773
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-400 dark:text-gray-500", children: label }),
|
|
774
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `ml-2 text-gray-700 dark:text-gray-300 ${bold ? "font-medium" : ""}`, children: value })
|
|
775
|
+
] });
|
|
776
|
+
}
|
|
646
777
|
// Annotate the CommonJS export names for ESM import in node:
|
|
647
778
|
0 && (module.exports = {
|
|
648
779
|
SubscribePage,
|
package/dist/index.mjs
CHANGED
|
@@ -395,20 +395,32 @@ var DEFAULT_PRIMARY2 = "#60A5FA";
|
|
|
395
395
|
function SubscriptionManagement({
|
|
396
396
|
subscriptionsApiPath = "/api/subscribe/subscriptions",
|
|
397
397
|
paymentsApiPath = "/api/subscribe/payments",
|
|
398
|
+
cardsApiPath = "/api/subscribe/cards",
|
|
398
399
|
primaryColor = DEFAULT_PRIMARY2,
|
|
399
400
|
theme = "system"
|
|
400
401
|
}) {
|
|
401
402
|
const [tab, setTab] = useState2("subscription");
|
|
402
403
|
const [subscriptions, setSubscriptions] = useState2([]);
|
|
403
404
|
const [payments, setPayments] = useState2([]);
|
|
405
|
+
const [cards, setCards] = useState2([]);
|
|
404
406
|
const [loading, setLoading] = useState2(true);
|
|
405
407
|
const [error, setError] = useState2("");
|
|
406
408
|
const [actionLoading, setActionLoading] = useState2(null);
|
|
407
409
|
const [confirmModal, setConfirmModal] = useState2(null);
|
|
410
|
+
const [showCardForm, setShowCardForm] = useState2(false);
|
|
411
|
+
const [cardForm, setCardForm] = useState2({
|
|
412
|
+
cardNumber: "",
|
|
413
|
+
expiryDate: "",
|
|
414
|
+
cvc: "",
|
|
415
|
+
cardPassword: "",
|
|
416
|
+
cardHolderName: "",
|
|
417
|
+
birthNumber: ""
|
|
418
|
+
});
|
|
419
|
+
const [cardError, setCardError] = useState2("");
|
|
420
|
+
const [cardSubmitting, setCardSubmitting] = useState2(false);
|
|
408
421
|
const themeClass = theme === "dark" ? "dark" : theme === "light" ? "light-mode-override" : "";
|
|
409
422
|
useEffect2(() => {
|
|
410
|
-
fetchSubscriptions();
|
|
411
|
-
fetchPayments();
|
|
423
|
+
Promise.all([fetchSubscriptions(), fetchPayments(), fetchCards()]).finally(() => setLoading(false));
|
|
412
424
|
}, []);
|
|
413
425
|
async function fetchSubscriptions() {
|
|
414
426
|
try {
|
|
@@ -416,8 +428,6 @@ function SubscriptionManagement({
|
|
|
416
428
|
const data = await res.json();
|
|
417
429
|
if (data.success) setSubscriptions(data.subscriptions);
|
|
418
430
|
} catch {
|
|
419
|
-
} finally {
|
|
420
|
-
setLoading(false);
|
|
421
431
|
}
|
|
422
432
|
}
|
|
423
433
|
async function fetchPayments() {
|
|
@@ -428,6 +438,14 @@ function SubscriptionManagement({
|
|
|
428
438
|
} catch {
|
|
429
439
|
}
|
|
430
440
|
}
|
|
441
|
+
async function fetchCards() {
|
|
442
|
+
try {
|
|
443
|
+
const res = await fetch(cardsApiPath);
|
|
444
|
+
const data = await res.json();
|
|
445
|
+
if (data.success) setCards(data.cards);
|
|
446
|
+
} catch {
|
|
447
|
+
}
|
|
448
|
+
}
|
|
431
449
|
async function handleCancelSubscription(subscriptionId) {
|
|
432
450
|
setActionLoading(subscriptionId);
|
|
433
451
|
setError("");
|
|
@@ -464,8 +482,7 @@ function SubscriptionManagement({
|
|
|
464
482
|
setError(data.error || "\uACB0\uC81C \uCDE8\uC18C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
465
483
|
return;
|
|
466
484
|
}
|
|
467
|
-
await fetchPayments();
|
|
468
|
-
await fetchSubscriptions();
|
|
485
|
+
await Promise.all([fetchPayments(), fetchSubscriptions()]);
|
|
469
486
|
} catch {
|
|
470
487
|
setError("\uACB0\uC81C \uCDE8\uC18C \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
471
488
|
} finally {
|
|
@@ -473,6 +490,51 @@ function SubscriptionManagement({
|
|
|
473
490
|
setConfirmModal(null);
|
|
474
491
|
}
|
|
475
492
|
}
|
|
493
|
+
async function handleDeleteCard(cardId) {
|
|
494
|
+
setActionLoading(cardId);
|
|
495
|
+
setError("");
|
|
496
|
+
try {
|
|
497
|
+
const res = await fetch(cardsApiPath, {
|
|
498
|
+
method: "DELETE",
|
|
499
|
+
headers: { "Content-Type": "application/json" },
|
|
500
|
+
body: JSON.stringify({ cardId })
|
|
501
|
+
});
|
|
502
|
+
const data = await res.json();
|
|
503
|
+
if (!data.success) {
|
|
504
|
+
setError(data.error || "\uCE74\uB4DC \uC0AD\uC81C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
await fetchCards();
|
|
508
|
+
} catch {
|
|
509
|
+
setError("\uCE74\uB4DC \uC0AD\uC81C \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
510
|
+
} finally {
|
|
511
|
+
setActionLoading(null);
|
|
512
|
+
setConfirmModal(null);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
async function handleRegisterCard() {
|
|
516
|
+
setCardError("");
|
|
517
|
+
setCardSubmitting(true);
|
|
518
|
+
try {
|
|
519
|
+
const res = await fetch(cardsApiPath, {
|
|
520
|
+
method: "POST",
|
|
521
|
+
headers: { "Content-Type": "application/json" },
|
|
522
|
+
body: JSON.stringify(cardForm)
|
|
523
|
+
});
|
|
524
|
+
const data = await res.json();
|
|
525
|
+
if (!data.success) {
|
|
526
|
+
setCardError(data.error || "\uCE74\uB4DC \uB4F1\uB85D\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
await fetchCards();
|
|
530
|
+
setShowCardForm(false);
|
|
531
|
+
setCardForm({ cardNumber: "", expiryDate: "", cvc: "", cardPassword: "", cardHolderName: "", birthNumber: "" });
|
|
532
|
+
} catch {
|
|
533
|
+
setCardError("\uCE74\uB4DC \uB4F1\uB85D \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
534
|
+
} finally {
|
|
535
|
+
setCardSubmitting(false);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
476
538
|
function fmt(price) {
|
|
477
539
|
return price.toLocaleString("ko-KR") + "\uC6D0";
|
|
478
540
|
}
|
|
@@ -480,35 +542,39 @@ function SubscriptionManagement({
|
|
|
480
542
|
return new Date(dateStr).toLocaleDateString("ko-KR", { year: "numeric", month: "long", day: "numeric" });
|
|
481
543
|
}
|
|
482
544
|
function statusBadge(status) {
|
|
483
|
-
if (status === "ACTIVE") return {
|
|
484
|
-
if (status === "CANCELLED") return {
|
|
485
|
-
return {
|
|
545
|
+
if (status === "ACTIVE") return { cls: "bg-green-100 dark:bg-green-500/20 text-green-700 dark:text-green-400", label: "\uD65C\uC131" };
|
|
546
|
+
if (status === "CANCELLED") return { cls: "bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400", label: "\uCDE8\uC18C\uB428" };
|
|
547
|
+
return { cls: "bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400", label: status };
|
|
486
548
|
}
|
|
487
549
|
function paymentStatusBadge(status) {
|
|
488
|
-
if (status === "COMPLETED") return {
|
|
489
|
-
if (status === "CANCELLED") return {
|
|
490
|
-
if (status === "FAILED") return {
|
|
491
|
-
return {
|
|
550
|
+
if (status === "COMPLETED") return { cls: "bg-green-100 dark:bg-green-500/20 text-green-700 dark:text-green-400", label: "\uC644\uB8CC" };
|
|
551
|
+
if (status === "CANCELLED") return { cls: "bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400", label: "\uCDE8\uC18C\uB428" };
|
|
552
|
+
if (status === "FAILED") return { cls: "bg-orange-100 dark:bg-orange-500/20 text-orange-700 dark:text-orange-400", label: "\uC2E4\uD328" };
|
|
553
|
+
return { cls: "bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400", label: status };
|
|
492
554
|
}
|
|
493
555
|
function canCancelPayment(p) {
|
|
494
556
|
if (p.status !== "COMPLETED") return false;
|
|
495
|
-
const
|
|
496
|
-
const daysDiff = Math.ceil((Date.now() - paidDate.getTime()) / (1e3 * 3600 * 24));
|
|
557
|
+
const daysDiff = Math.ceil((Date.now() - new Date(p.paidAt || p.createdAt).getTime()) / (1e3 * 3600 * 24));
|
|
497
558
|
return daysDiff <= 7;
|
|
498
559
|
}
|
|
499
560
|
if (loading) return /* @__PURE__ */ jsx2("div", { className: themeClass, children: /* @__PURE__ */ jsx2("div", { className: "text-gray-400 py-8 text-center", children: "\uBD88\uB7EC\uC624\uB294 \uC911..." }) });
|
|
561
|
+
const tabs = [
|
|
562
|
+
{ key: "subscription", label: "\uAD6C\uB3C5 \uC815\uBCF4" },
|
|
563
|
+
{ key: "cards", label: "\uACB0\uC81C\uC218\uB2E8" },
|
|
564
|
+
{ key: "payments", label: "\uACB0\uC81C \uC774\uB825" }
|
|
565
|
+
];
|
|
500
566
|
return /* @__PURE__ */ jsx2("div", { className: themeClass, children: /* @__PURE__ */ jsxs2("div", { className: "space-y-4", children: [
|
|
501
567
|
error && /* @__PURE__ */ jsx2("div", { className: "p-3 bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/30 rounded-lg text-red-600 dark:text-red-400 text-sm", children: error }),
|
|
502
|
-
/* @__PURE__ */ jsx2("div", { className: "flex border-b border-gray-200 dark:border-white/10", children:
|
|
503
|
-
{ key: "subscription", label: "\uAD6C\uB3C5 \uC815\uBCF4" },
|
|
504
|
-
{ key: "payments", label: "\uACB0\uC81C \uC774\uB825" }
|
|
505
|
-
].map(({ key, label }) => /* @__PURE__ */ jsx2(
|
|
568
|
+
/* @__PURE__ */ jsx2("div", { className: "flex border-b border-gray-200 dark:border-white/10", children: tabs.map(({ key, label }) => /* @__PURE__ */ jsxs2(
|
|
506
569
|
"button",
|
|
507
570
|
{
|
|
508
571
|
onClick: () => setTab(key),
|
|
509
|
-
className: `px-4 py-2.5 text-sm font-medium border-b-2 transition-colors -mb-px ${tab === key ? "border-current
|
|
572
|
+
className: `px-4 py-2.5 text-sm font-medium border-b-2 transition-colors -mb-px ${tab === key ? "border-current" : "border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"}`,
|
|
510
573
|
style: tab === key ? { color: primaryColor, borderColor: primaryColor } : void 0,
|
|
511
|
-
children:
|
|
574
|
+
children: [
|
|
575
|
+
label,
|
|
576
|
+
key === "cards" && cards.length > 0 && /* @__PURE__ */ jsx2("span", { className: "ml-1.5 px-1.5 py-0.5 rounded-full text-xs bg-gray-100 dark:bg-white/10 text-gray-500 dark:text-gray-400", children: cards.length })
|
|
577
|
+
]
|
|
512
578
|
},
|
|
513
579
|
key
|
|
514
580
|
)) }),
|
|
@@ -518,42 +584,16 @@ function SubscriptionManagement({
|
|
|
518
584
|
/* @__PURE__ */ jsxs2("div", { className: "space-y-2 flex-1 min-w-0", children: [
|
|
519
585
|
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
520
586
|
/* @__PURE__ */ jsx2("span", { className: "text-gray-900 dark:text-white font-semibold text-base", children: sub.plan.name }),
|
|
521
|
-
/* @__PURE__ */ jsx2("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${badge.
|
|
587
|
+
/* @__PURE__ */ jsx2("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${badge.cls}`, children: badge.label }),
|
|
522
588
|
sub.isTrial && /* @__PURE__ */ jsx2("span", { className: "px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 dark:bg-purple-500/20 text-purple-700 dark:text-purple-400", children: "\uCCB4\uD5D8" })
|
|
523
589
|
] }),
|
|
524
590
|
/* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-1 text-sm", children: [
|
|
525
|
-
/* @__PURE__ */
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
"\uAC1C\uC6D4"
|
|
532
|
-
] })
|
|
533
|
-
] }),
|
|
534
|
-
/* @__PURE__ */ jsxs2("div", { children: [
|
|
535
|
-
/* @__PURE__ */ jsx2("span", { className: "text-gray-400 dark:text-gray-500", children: "\uC0C1\uD0DC" }),
|
|
536
|
-
/* @__PURE__ */ jsx2("span", { className: "ml-2 text-gray-700 dark:text-gray-300", children: sub.statusMessage })
|
|
537
|
-
] }),
|
|
538
|
-
/* @__PURE__ */ jsxs2("div", { children: [
|
|
539
|
-
/* @__PURE__ */ jsx2("span", { className: "text-gray-400 dark:text-gray-500", children: "\uC2DC\uC791\uC77C" }),
|
|
540
|
-
/* @__PURE__ */ jsx2("span", { className: "ml-2 text-gray-700 dark:text-gray-300", children: fmtDate(sub.startDate) })
|
|
541
|
-
] }),
|
|
542
|
-
/* @__PURE__ */ jsxs2("div", { children: [
|
|
543
|
-
/* @__PURE__ */ jsx2("span", { className: "text-gray-400 dark:text-gray-500", children: "\uB9CC\uB8CC\uC77C" }),
|
|
544
|
-
/* @__PURE__ */ jsx2("span", { className: "ml-2 text-gray-700 dark:text-gray-300", children: fmtDate(sub.endDate) })
|
|
545
|
-
] }),
|
|
546
|
-
/* @__PURE__ */ jsxs2("div", { children: [
|
|
547
|
-
/* @__PURE__ */ jsx2("span", { className: "text-gray-400 dark:text-gray-500", children: "\uB0A8\uC740 \uAE30\uAC04" }),
|
|
548
|
-
/* @__PURE__ */ jsxs2("span", { className: "ml-2 text-gray-700 dark:text-gray-300 font-medium", children: [
|
|
549
|
-
sub.remainingDays,
|
|
550
|
-
"\uC77C"
|
|
551
|
-
] })
|
|
552
|
-
] }),
|
|
553
|
-
/* @__PURE__ */ jsxs2("div", { children: [
|
|
554
|
-
/* @__PURE__ */ jsx2("span", { className: "text-gray-400 dark:text-gray-500", children: "\uC790\uB3D9\uACB0\uC81C" }),
|
|
555
|
-
/* @__PURE__ */ jsx2("span", { className: "ml-2 text-gray-700 dark:text-gray-300", children: sub.autoRenew ? "\uC0AC\uC6A9" : "\uD574\uC81C" })
|
|
556
|
-
] })
|
|
591
|
+
/* @__PURE__ */ jsx2(InfoRow, { label: "\uAE08\uC561", value: `${fmt(sub.plan.price)} / ${sub.plan.interval}\uAC1C\uC6D4`, bold: true }),
|
|
592
|
+
/* @__PURE__ */ jsx2(InfoRow, { label: "\uC0C1\uD0DC", value: sub.statusMessage }),
|
|
593
|
+
/* @__PURE__ */ jsx2(InfoRow, { label: "\uC2DC\uC791\uC77C", value: fmtDate(sub.startDate) }),
|
|
594
|
+
/* @__PURE__ */ jsx2(InfoRow, { label: "\uB9CC\uB8CC\uC77C", value: fmtDate(sub.endDate) }),
|
|
595
|
+
/* @__PURE__ */ jsx2(InfoRow, { label: "\uB0A8\uC740 \uAE30\uAC04", value: `${sub.remainingDays}\uC77C`, bold: true }),
|
|
596
|
+
/* @__PURE__ */ jsx2(InfoRow, { label: "\uC790\uB3D9\uACB0\uC81C", value: sub.autoRenew ? "\uC0AC\uC6A9" : "\uD574\uC81C" })
|
|
557
597
|
] })
|
|
558
598
|
] }),
|
|
559
599
|
sub.status === "ACTIVE" && /* @__PURE__ */ jsx2(
|
|
@@ -567,7 +607,92 @@ function SubscriptionManagement({
|
|
|
567
607
|
)
|
|
568
608
|
] }) }, sub.id);
|
|
569
609
|
}) }),
|
|
570
|
-
tab === "
|
|
610
|
+
tab === "cards" && /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
|
|
611
|
+
cards.length > 0 && /* @__PURE__ */ jsx2("div", { className: "space-y-2", children: cards.map((card) => /* @__PURE__ */ jsxs2("div", { className: "p-4 rounded-xl border border-gray-200 dark:border-white/10 bg-white dark:bg-white/5 flex items-center justify-between gap-3", children: [
|
|
612
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
613
|
+
/* @__PURE__ */ jsx2("div", { className: "w-10 h-7 rounded bg-gray-100 dark:bg-white/10 flex items-center justify-center text-xs font-bold text-gray-500 dark:text-gray-400 flex-shrink-0", children: card.cardBrand?.slice(0, 4) || "CARD" }),
|
|
614
|
+
/* @__PURE__ */ jsxs2("div", { className: "min-w-0", children: [
|
|
615
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
|
|
616
|
+
/* @__PURE__ */ jsx2("span", { className: "text-gray-900 dark:text-white font-medium text-sm", children: card.cardBrand }),
|
|
617
|
+
/* @__PURE__ */ jsx2("span", { className: "text-gray-500 dark:text-gray-400 text-sm", children: card.maskedCardNumber }),
|
|
618
|
+
card.isDefault && /* @__PURE__ */ jsx2("span", { className: "px-1.5 py-0.5 rounded text-xs font-medium bg-blue-100 dark:bg-blue-500/20 text-blue-600 dark:text-blue-400", children: "\uAE30\uBCF8" })
|
|
619
|
+
] }),
|
|
620
|
+
/* @__PURE__ */ jsxs2("div", { className: "text-xs text-gray-400 dark:text-gray-500 mt-0.5", children: [
|
|
621
|
+
card.cardHolderName,
|
|
622
|
+
" \xB7 ",
|
|
623
|
+
card.expiryMonth,
|
|
624
|
+
"/",
|
|
625
|
+
card.expiryYear
|
|
626
|
+
] })
|
|
627
|
+
] })
|
|
628
|
+
] }),
|
|
629
|
+
/* @__PURE__ */ jsx2(
|
|
630
|
+
"button",
|
|
631
|
+
{
|
|
632
|
+
onClick: () => setConfirmModal({ type: "delete_card", id: card.id, label: `${card.cardBrand} ${card.maskedCardNumber}` }),
|
|
633
|
+
disabled: actionLoading === card.id,
|
|
634
|
+
className: "text-xs text-red-500 dark:text-red-400 hover:underline disabled:opacity-50 flex-shrink-0",
|
|
635
|
+
children: "\uC0AD\uC81C"
|
|
636
|
+
}
|
|
637
|
+
)
|
|
638
|
+
] }, card.id)) }),
|
|
639
|
+
!showCardForm ? /* @__PURE__ */ jsx2(
|
|
640
|
+
"button",
|
|
641
|
+
{
|
|
642
|
+
onClick: () => setShowCardForm(true),
|
|
643
|
+
className: "w-full p-4 rounded-xl border border-dashed border-gray-300 dark:border-white/20 text-gray-400 dark:text-gray-500 hover:border-gray-400 dark:hover:border-white/40 hover:text-gray-500 dark:hover:text-gray-300 transition-all text-sm",
|
|
644
|
+
children: "+ \uC0C8 \uCE74\uB4DC \uCD94\uAC00"
|
|
645
|
+
}
|
|
646
|
+
) : /* @__PURE__ */ jsxs2("div", { className: "p-4 rounded-xl border border-gray-200 dark:border-white/10 bg-gray-50 dark:bg-white/5 space-y-3", children: [
|
|
647
|
+
/* @__PURE__ */ jsx2("h3", { className: "text-gray-900 dark:text-white text-sm font-medium", children: "\uCE74\uB4DC \uC815\uBCF4 \uC785\uB825" }),
|
|
648
|
+
cardError && /* @__PURE__ */ jsx2("div", { className: "p-3 bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/30 rounded-lg text-red-600 dark:text-red-400 text-xs", children: cardError }),
|
|
649
|
+
/* @__PURE__ */ jsx2("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: [
|
|
650
|
+
{ label: "\uCE74\uB4DC \uBC88\uD638", key: "cardNumber", placeholder: "0000-0000-0000-0000", type: "text", full: true },
|
|
651
|
+
{ label: "\uB9CC\uB8CC\uC77C", key: "expiryDate", placeholder: "MM/YY", type: "text", full: false },
|
|
652
|
+
{ label: "CVC", key: "cvc", placeholder: "3\uC790\uB9AC", type: "password", full: false },
|
|
653
|
+
{ label: "\uCE74\uB4DC \uBE44\uBC00\uBC88\uD638 \uC55E 2\uC790\uB9AC", key: "cardPassword", placeholder: "\u2022\u2022", type: "password", full: false },
|
|
654
|
+
{ label: "\uCE74\uB4DC \uC18C\uC720\uC790\uBA85", key: "cardHolderName", placeholder: "\uD64D\uAE38\uB3D9", type: "text", full: false },
|
|
655
|
+
{ label: "\uC0DD\uB144\uC6D4\uC77C 6\uC790\uB9AC / \uC0AC\uC5C5\uC790\uBC88\uD638 10\uC790\uB9AC", key: "birthNumber", placeholder: "990101", type: "text", full: true }
|
|
656
|
+
].map(({ label, key, placeholder, type, full }) => /* @__PURE__ */ jsxs2("div", { className: full ? "sm:col-span-2" : "", children: [
|
|
657
|
+
/* @__PURE__ */ jsx2("label", { className: "text-xs text-gray-500 dark:text-gray-400 block mb-1", children: label }),
|
|
658
|
+
/* @__PURE__ */ jsx2(
|
|
659
|
+
"input",
|
|
660
|
+
{
|
|
661
|
+
type,
|
|
662
|
+
placeholder,
|
|
663
|
+
value: cardForm[key],
|
|
664
|
+
onChange: (e) => setCardForm((f) => ({ ...f, [key]: e.target.value })),
|
|
665
|
+
className: "w-full bg-white dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-lg px-3 py-2 text-gray-900 dark:text-white text-sm placeholder-gray-300 dark:placeholder-gray-600 focus:outline-none focus:border-blue-500 transition-colors"
|
|
666
|
+
}
|
|
667
|
+
)
|
|
668
|
+
] }, key)) }),
|
|
669
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex gap-2 pt-1", children: [
|
|
670
|
+
/* @__PURE__ */ jsx2(
|
|
671
|
+
"button",
|
|
672
|
+
{
|
|
673
|
+
onClick: () => {
|
|
674
|
+
setShowCardForm(false);
|
|
675
|
+
setCardError("");
|
|
676
|
+
},
|
|
677
|
+
className: "flex-1 py-2.5 rounded-lg border border-gray-200 dark:border-white/10 text-gray-500 dark:text-gray-400 text-sm hover:border-gray-300 dark:hover:border-white/20 transition-all",
|
|
678
|
+
children: "\uCDE8\uC18C"
|
|
679
|
+
}
|
|
680
|
+
),
|
|
681
|
+
/* @__PURE__ */ jsx2(
|
|
682
|
+
"button",
|
|
683
|
+
{
|
|
684
|
+
onClick: handleRegisterCard,
|
|
685
|
+
disabled: cardSubmitting,
|
|
686
|
+
style: { backgroundColor: primaryColor },
|
|
687
|
+
className: "flex-1 py-2.5 rounded-lg text-white text-sm font-medium hover:opacity-90 disabled:opacity-50 transition-all",
|
|
688
|
+
children: cardSubmitting ? "\uB4F1\uB85D \uC911..." : "\uCE74\uB4DC \uB4F1\uB85D"
|
|
689
|
+
}
|
|
690
|
+
)
|
|
691
|
+
] })
|
|
692
|
+
] }),
|
|
693
|
+
cards.length === 0 && !showCardForm && /* @__PURE__ */ jsx2("div", { className: "text-center py-8 text-gray-400 dark:text-gray-500 text-sm", children: "\uB4F1\uB85D\uB41C \uACB0\uC81C\uC218\uB2E8\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." })
|
|
694
|
+
] }),
|
|
695
|
+
tab === "payments" && /* @__PURE__ */ jsx2("div", { className: "space-y-2", children: payments.length === 0 ? /* @__PURE__ */ jsx2("div", { className: "text-center py-12 text-gray-400 dark:text-gray-500 text-sm", children: "\uACB0\uC81C \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." }) : /* @__PURE__ */ jsx2("div", { className: "overflow-x-auto -mx-4 sm:mx-0", children: /* @__PURE__ */ jsxs2("table", { className: "w-full text-sm min-w-[600px]", children: [
|
|
571
696
|
/* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsx2("tr", { className: "border-b border-gray-200 dark:border-white/10", children: ["\uC77C\uC2DC", "\uB0B4\uC6A9", "\uAE08\uC561", "\uACB0\uC81C\uC218\uB2E8", "\uC0C1\uD0DC", ""].map((h) => /* @__PURE__ */ jsx2("th", { className: "text-left py-2.5 px-3 text-xs font-medium text-gray-400 dark:text-gray-500 whitespace-nowrap", children: h }, h)) }) }),
|
|
572
697
|
/* @__PURE__ */ jsx2("tbody", { children: payments.map((p) => {
|
|
573
698
|
const badge = paymentStatusBadge(p.status);
|
|
@@ -576,7 +701,7 @@ function SubscriptionManagement({
|
|
|
576
701
|
/* @__PURE__ */ jsx2("td", { className: "py-3 px-3 text-gray-900 dark:text-white font-medium", children: p.orderName }),
|
|
577
702
|
/* @__PURE__ */ jsx2("td", { className: "py-3 px-3 text-gray-900 dark:text-white font-semibold whitespace-nowrap", children: fmt(p.amount) }),
|
|
578
703
|
/* @__PURE__ */ jsx2("td", { className: "py-3 px-3 text-gray-500 dark:text-gray-400 whitespace-nowrap", children: p.cardBrand && p.maskedCardNumber ? `${p.cardBrand} ${p.maskedCardNumber}` : "-" }),
|
|
579
|
-
/* @__PURE__ */ jsx2("td", { className: "py-3 px-3", children: /* @__PURE__ */ jsx2("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${badge.
|
|
704
|
+
/* @__PURE__ */ jsx2("td", { className: "py-3 px-3", children: /* @__PURE__ */ jsx2("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${badge.cls}`, children: badge.label }) }),
|
|
580
705
|
/* @__PURE__ */ jsx2("td", { className: "py-3 px-3", children: canCancelPayment(p) && /* @__PURE__ */ jsx2(
|
|
581
706
|
"button",
|
|
582
707
|
{
|
|
@@ -590,10 +715,10 @@ function SubscriptionManagement({
|
|
|
590
715
|
}) })
|
|
591
716
|
] }) }) }),
|
|
592
717
|
confirmModal && /* @__PURE__ */ jsx2("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ jsxs2("div", { className: "bg-white dark:bg-gray-900 rounded-2xl p-6 max-w-sm w-full shadow-xl", children: [
|
|
593
|
-
/* @__PURE__ */ jsx2("h3", { className: "text-gray-900 dark:text-white font-semibold text-base mb-2", children: confirmModal.type === "cancel_subscription" ? "\uAD6C\uB3C5 \uCDE8\uC18C" : "\uACB0\uC81C \uCDE8\uC18C" }),
|
|
718
|
+
/* @__PURE__ */ jsx2("h3", { className: "text-gray-900 dark:text-white font-semibold text-base mb-2", children: confirmModal.type === "cancel_subscription" ? "\uAD6C\uB3C5 \uCDE8\uC18C" : confirmModal.type === "cancel_payment" ? "\uACB0\uC81C \uCDE8\uC18C" : "\uCE74\uB4DC \uC0AD\uC81C" }),
|
|
594
719
|
/* @__PURE__ */ jsxs2("p", { className: "text-gray-500 dark:text-gray-400 text-sm mb-5", children: [
|
|
595
720
|
/* @__PURE__ */ jsx2("span", { className: "text-gray-900 dark:text-white font-medium", children: confirmModal.label }),
|
|
596
|
-
confirmModal.type === "cancel_subscription" ? "\uC744(\uB97C) \uCDE8\uC18C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uD604\uC7AC \uAD6C\uB3C5 \uAE30\uAC04\uC774 \uB05D\uB098\uBA74 \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." : "\uC758 \uACB0\uC81C\uB97C \uCDE8\uC18C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uC774 \uC791\uC5C5\uC740 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
721
|
+
confirmModal.type === "cancel_subscription" ? "\uC744(\uB97C) \uCDE8\uC18C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uD604\uC7AC \uAD6C\uB3C5 \uAE30\uAC04\uC774 \uB05D\uB098\uBA74 \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." : confirmModal.type === "cancel_payment" ? "\uC758 \uACB0\uC81C\uB97C \uCDE8\uC18C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uC774 \uC791\uC5C5\uC740 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4." : "\uC744(\uB97C) \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? \uC0AD\uC81C\uB41C \uCE74\uB4DC\uB294 \uBCF5\uAD6C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
597
722
|
] }),
|
|
598
723
|
/* @__PURE__ */ jsxs2("div", { className: "flex gap-2", children: [
|
|
599
724
|
/* @__PURE__ */ jsx2(
|
|
@@ -607,16 +732,22 @@ function SubscriptionManagement({
|
|
|
607
732
|
/* @__PURE__ */ jsx2(
|
|
608
733
|
"button",
|
|
609
734
|
{
|
|
610
|
-
onClick: () => confirmModal.type === "cancel_subscription" ? handleCancelSubscription(confirmModal.id) : handleCancelPayment(confirmModal.id),
|
|
735
|
+
onClick: () => confirmModal.type === "cancel_subscription" ? handleCancelSubscription(confirmModal.id) : confirmModal.type === "cancel_payment" ? handleCancelPayment(confirmModal.id) : handleDeleteCard(confirmModal.id),
|
|
611
736
|
disabled: !!actionLoading,
|
|
612
737
|
className: "flex-1 py-2.5 rounded-lg bg-red-500 text-white text-sm font-medium hover:bg-red-600 disabled:opacity-50 transition-all",
|
|
613
|
-
children: actionLoading ? "\uCC98\uB9AC \uC911..." : "\uC608, \
|
|
738
|
+
children: actionLoading ? "\uCC98\uB9AC \uC911..." : "\uC608, \uD655\uC778\uD569\uB2C8\uB2E4"
|
|
614
739
|
}
|
|
615
740
|
)
|
|
616
741
|
] })
|
|
617
742
|
] }) })
|
|
618
743
|
] }) });
|
|
619
744
|
}
|
|
745
|
+
function InfoRow({ label, value, bold }) {
|
|
746
|
+
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
747
|
+
/* @__PURE__ */ jsx2("span", { className: "text-gray-400 dark:text-gray-500", children: label }),
|
|
748
|
+
/* @__PURE__ */ jsx2("span", { className: `ml-2 text-gray-700 dark:text-gray-300 ${bold ? "font-medium" : ""}`, children: value })
|
|
749
|
+
] });
|
|
750
|
+
}
|
|
620
751
|
export {
|
|
621
752
|
SubscribePage,
|
|
622
753
|
SubscriptionManagement
|