@carlonicora/nextjs-jsonapi 1.36.1 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BlockNoteEditor-4MDHRUS2.js → BlockNoteEditor-3S2B36O3.js} +15 -15
- package/dist/{BlockNoteEditor-4MDHRUS2.js.map → BlockNoteEditor-3S2B36O3.js.map} +1 -1
- package/dist/{BlockNoteEditor-SZWO3MDO.mjs → BlockNoteEditor-WQUJTVJL.mjs} +5 -5
- package/dist/BlockNoteEditor-WQUJTVJL.mjs.map +1 -0
- package/dist/billing/index.d.mts +15 -5
- package/dist/billing/index.d.ts +15 -5
- package/dist/billing/index.js +750 -520
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +665 -435
- package/dist/billing/index.mjs.map +1 -1
- package/dist/{chunk-53IPQJVH.js → chunk-3EZX4G2E.js} +147 -23
- package/dist/chunk-3EZX4G2E.js.map +1 -0
- package/dist/{chunk-I7DFEJFF.mjs → chunk-4PHADEKA.mjs} +738 -1418
- package/dist/chunk-4PHADEKA.mjs.map +1 -0
- package/dist/{chunk-E6PQQTWF.js → chunk-T2JCZYWK.js} +999 -1679
- package/dist/chunk-T2JCZYWK.js.map +1 -0
- package/dist/{chunk-P7R2DPD6.mjs → chunk-TQ5GRRTM.mjs} +125 -1
- package/dist/chunk-TQ5GRRTM.mjs.map +1 -0
- package/dist/client/index.js +3 -3
- package/dist/client/index.mjs +2 -2
- package/dist/components/index.d.mts +23 -8
- package/dist/components/index.d.ts +23 -8
- package/dist/components/index.js +3 -3
- package/dist/components/index.mjs +2 -2
- package/dist/contexts/index.d.mts +1 -1
- package/dist/contexts/index.d.ts +1 -1
- package/dist/contexts/index.js +3 -3
- package/dist/contexts/index.mjs +2 -2
- package/dist/core/index.d.mts +47 -3
- package/dist/core/index.d.ts +47 -3
- package/dist/core/index.js +8 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +7 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +1 -1
- package/dist/{stripe-subscription.interface-DK7BJaNd.d.ts → stripe-promotion-code.interface-BcJty0rv.d.ts} +18 -1
- package/dist/{stripe-subscription.interface-C8uhCYIZ.d.mts → stripe-promotion-code.interface-Dnm2DJKQ.d.mts} +18 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/billing/index.ts +1 -0
- package/src/client/context/JsonApiProvider.tsx +1 -5
- package/src/client/hooks/__tests__/useJsonApiGet.test.tsx +9 -9
- package/src/client/hooks/__tests__/useJsonApiMutation.test.tsx +11 -11
- package/src/client/hooks/__tests__/useRehydration.test.ts +13 -34
- package/src/components/editors/BlockNoteEditor.tsx +2 -2
- package/src/components/forms/CommonEditorTrigger.tsx +1 -1
- package/src/components/forms/FormCheckbox.tsx +2 -12
- package/src/components/forms/FormDate.tsx +1 -6
- package/src/components/forms/FormInput.tsx +1 -1
- package/src/components/forms/FormPassword.tsx +1 -7
- package/src/components/forms/FormSelect.tsx +2 -8
- package/src/components/forms/FormSlider.tsx +1 -5
- package/src/components/forms/FormSwitch.tsx +1 -5
- package/src/components/forms/GdprConsentCheckbox.tsx +2 -8
- package/src/components/forms/PasswordInput.tsx +28 -26
- package/src/components/forms/__tests__/FormCheckbox.test.tsx +16 -18
- package/src/components/forms/__tests__/FormDate.test.tsx +14 -30
- package/src/components/forms/__tests__/FormInput.test.tsx +21 -37
- package/src/components/forms/__tests__/FormSelect.test.tsx +15 -21
- package/src/components/tables/ContentListTable.tsx +1 -1
- package/src/components/tables/__tests__/ContentListTable.test.tsx +17 -89
- package/src/components/tables/cells/cell.component.tsx +1 -1
- package/src/contexts/HeaderChildrenContext.tsx +3 -1
- package/src/core/endpoint/__tests__/EndpointCreator.test.ts +2 -7
- package/src/core/factories/__tests__/JsonApiDataFactory.test.ts +3 -3
- package/src/core/factories/__tests__/RehydrationFactory.test.ts +4 -6
- package/src/core/index.ts +1 -0
- package/src/core/registry/ModuleRegistry.ts +1 -0
- package/src/core/registry/__tests__/DataClassRegistry.test.ts +5 -15
- package/src/core/registry/__tests__/ModuleRegistrar.test.ts +5 -15
- package/src/features/auth/components/GdprConsentSection.tsx +1 -6
- package/src/features/auth/components/details/LandingComponent.tsx +6 -1
- package/src/features/auth/components/forms/AcceptInvitation.tsx +1 -1
- package/src/features/auth/components/forms/ResetPassword.tsx +1 -1
- package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +13 -18
- package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +12 -17
- package/src/features/billing/components/modals/BillingDetailModal.tsx +2 -13
- package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +8 -1
- package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +2 -13
- package/src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx +2 -12
- package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +6 -1
- package/src/features/billing/stripe-invoice/data/stripe-invoice.interface.ts +1 -0
- package/src/features/billing/stripe-price/components/lists/PricesList.tsx +13 -5
- package/src/features/billing/stripe-product/components/lists/ProductsList.tsx +5 -5
- package/src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx +108 -0
- package/src/features/billing/stripe-promotion-code/components/index.ts +1 -0
- package/src/features/billing/stripe-promotion-code/data/index.ts +3 -0
- package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.interface.ts +14 -0
- package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.service.ts +64 -0
- package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.ts +66 -0
- package/src/features/billing/stripe-promotion-code/index.ts +2 -0
- package/src/features/billing/stripe-promotion-code/stripe-promotion-code.module.ts +9 -0
- package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +1 -3
- package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +4 -1
- package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +1 -1
- package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +24 -4
- package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +9 -2
- package/src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx +3 -1
- package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +7 -7
- package/src/features/billing/stripe-subscription/components/wizards/WizardProgressIndicator.tsx +2 -10
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx +3 -13
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +134 -23
- package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +2 -0
- package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +8 -0
- package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +93 -7
- package/src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx +1 -1
- package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +1 -1
- package/src/features/company/components/details/CompanyDetails.tsx +2 -2
- package/src/features/company/components/forms/CompanyConfigurationSecurityForm.tsx +1 -1
- package/src/features/index.ts +1 -0
- package/src/features/notification/components/containers/NotificationsListContainer.tsx +1 -1
- package/src/features/notification/components/modals/NotificationModal.tsx +6 -2
- package/src/features/notification/contexts/NotificationContext.tsx +1 -3
- package/src/features/oauth/components/OAuthClientCard.tsx +15 -17
- package/src/features/oauth/components/OAuthClientDetail.tsx +7 -19
- package/src/features/oauth/components/OAuthClientForm.tsx +4 -13
- package/src/features/oauth/components/OAuthClientSecretDisplay.tsx +4 -20
- package/src/features/oauth/components/OAuthRedirectUriInput.tsx +5 -12
- package/src/features/oauth/components/OAuthScopeSelector.tsx +17 -23
- package/src/features/oauth/components/consent/OAuthConsentActions.tsx +3 -16
- package/src/features/oauth/components/consent/OAuthConsentHeader.tsx +3 -12
- package/src/features/oauth/components/consent/OAuthConsentScreen.tsx +5 -20
- package/src/features/oauth/components/consent/OAuthScopeList.tsx +3 -18
- package/src/features/onboarding/contexts/OnboardingContext.tsx +3 -3
- package/src/features/role/components/forms/FormRoles.tsx +1 -7
- package/src/features/user/components/containers/UserContainer.tsx +1 -1
- package/src/features/user/components/details/UserDetails.tsx +1 -1
- package/src/features/user/components/forms/UserDeleter.tsx +1 -1
- package/src/features/user/components/forms/UserEditor.tsx +1 -1
- package/src/features/user/components/forms/UserMultiSelect.tsx +7 -7
- package/src/features/user/components/lists/UserListInAdd.tsx +2 -2
- package/src/features/user/components/lists/UsersList.tsx +7 -1
- package/src/features/user/contexts/CurrentUserContext.tsx +36 -33
- package/src/hooks/__tests__/useDataListRetriever.test.ts +15 -21
- package/src/hooks/__tests__/useDebounce.test.ts +2 -7
- package/src/hooks/useCustomD3Graph.tsx +2 -2
- package/src/shadcnui/custom/multi-select.tsx +28 -2
- package/src/shadcnui/ui/accordion.tsx +21 -23
- package/src/shadcnui/ui/alert-dialog.tsx +45 -62
- package/src/shadcnui/ui/alert.tsx +25 -41
- package/src/shadcnui/ui/avatar.tsx +23 -36
- package/src/shadcnui/ui/badge.tsx +13 -11
- package/src/shadcnui/ui/breadcrumb.tsx +21 -55
- package/src/shadcnui/ui/button.tsx +17 -18
- package/src/shadcnui/ui/calendar.tsx +44 -93
- package/src/shadcnui/ui/carousel.tsx +72 -100
- package/src/shadcnui/ui/chart.tsx +102 -161
- package/src/shadcnui/ui/checkbox.tsx +8 -9
- package/src/shadcnui/ui/combobox.tsx +52 -83
- package/src/shadcnui/ui/command.tsx +43 -77
- package/src/shadcnui/ui/context-menu.tsx +47 -86
- package/src/shadcnui/ui/dialog.tsx +34 -60
- package/src/shadcnui/ui/drawer.tsx +32 -53
- package/src/shadcnui/ui/dropdown-menu.tsx +48 -65
- package/src/shadcnui/ui/field.tsx +39 -48
- package/src/shadcnui/ui/hover-card.tsx +9 -14
- package/src/shadcnui/ui/input-group.tsx +44 -55
- package/src/shadcnui/ui/input-otp.tsx +22 -26
- package/src/shadcnui/ui/input.tsx +6 -6
- package/src/shadcnui/ui/label.tsx +6 -6
- package/src/shadcnui/ui/navigation-menu.tsx +36 -60
- package/src/shadcnui/ui/popover.tsx +15 -38
- package/src/shadcnui/ui/progress.tsx +12 -29
- package/src/shadcnui/ui/radio-group.tsx +9 -15
- package/src/shadcnui/ui/resizable.tsx +14 -24
- package/src/shadcnui/ui/scroll-area.tsx +12 -27
- package/src/shadcnui/ui/select.tsx +41 -65
- package/src/shadcnui/ui/separator.tsx +7 -11
- package/src/shadcnui/ui/sheet.tsx +30 -55
- package/src/shadcnui/ui/sidebar.tsx +141 -189
- package/src/shadcnui/ui/skeleton.tsx +3 -9
- package/src/shadcnui/ui/slider.tsx +11 -23
- package/src/shadcnui/ui/switch.tsx +8 -8
- package/src/shadcnui/ui/tabs.tsx +14 -21
- package/src/shadcnui/ui/textarea.tsx +5 -5
- package/src/shadcnui/ui/toggle.tsx +8 -14
- package/src/shadcnui/ui/tooltip.tsx +11 -23
- package/src/testing/providers/MockJsonApiProvider.tsx +1 -5
- package/src/testing/utils/renderWithProviders.tsx +6 -10
- package/dist/BlockNoteEditor-SZWO3MDO.mjs.map +0 -1
- package/dist/chunk-53IPQJVH.js.map +0 -1
- package/dist/chunk-E6PQQTWF.js.map +0 -1
- package/dist/chunk-I7DFEJFF.mjs.map +0 -1
- package/dist/chunk-P7R2DPD6.mjs.map +0 -1
package/dist/billing/index.mjs
CHANGED
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
TabsList,
|
|
48
48
|
TabsTrigger,
|
|
49
49
|
useCurrentUserContext
|
|
50
|
-
} from "../chunk-
|
|
50
|
+
} from "../chunk-4PHADEKA.mjs";
|
|
51
51
|
import {
|
|
52
52
|
getRoleId,
|
|
53
53
|
getStripePublishableKey
|
|
@@ -58,10 +58,11 @@ import {
|
|
|
58
58
|
StripeInvoiceService,
|
|
59
59
|
StripePriceService,
|
|
60
60
|
StripeProductService,
|
|
61
|
+
StripePromotionCodeService,
|
|
61
62
|
StripeSubscriptionService,
|
|
62
63
|
StripeUsageService,
|
|
63
64
|
cn
|
|
64
|
-
} from "../chunk-
|
|
65
|
+
} from "../chunk-TQ5GRRTM.mjs";
|
|
65
66
|
import "../chunk-AUXK7QSA.mjs";
|
|
66
67
|
import "../chunk-C7C7VY4F.mjs";
|
|
67
68
|
import "../chunk-U4MTVHOC.mjs";
|
|
@@ -96,15 +97,6 @@ function formatDate(date) {
|
|
|
96
97
|
});
|
|
97
98
|
}
|
|
98
99
|
__name(formatDate, "formatDate");
|
|
99
|
-
function formatPrice(amount, currency) {
|
|
100
|
-
if (amount === void 0) return "N/A";
|
|
101
|
-
const currencyCode = currency?.toUpperCase() || "USD";
|
|
102
|
-
return new Intl.NumberFormat(void 0, {
|
|
103
|
-
style: "currency",
|
|
104
|
-
currency: currencyCode
|
|
105
|
-
}).format(amount / 100);
|
|
106
|
-
}
|
|
107
|
-
__name(formatPrice, "formatPrice");
|
|
108
100
|
function formatPlanName(subscription) {
|
|
109
101
|
const productName = subscription.price?.product?.name || "";
|
|
110
102
|
const nickname = subscription.price?.nickname || "";
|
|
@@ -173,16 +165,15 @@ function SubscriptionSummaryCard({
|
|
|
173
165
|
] }) : primarySubscription ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
174
166
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
175
167
|
/* @__PURE__ */ jsx("p", { className: "text-xl font-bold", children: formatPlanName(primarySubscription) }),
|
|
176
|
-
/* @__PURE__ */ jsx(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
] })
|
|
168
|
+
/* @__PURE__ */ jsx(
|
|
169
|
+
Badge,
|
|
170
|
+
{
|
|
171
|
+
variant: primarySubscription.cancelAtPeriodEnd ? "secondary" : getStatusBadgeVariant(primarySubscription.status),
|
|
172
|
+
children: primarySubscription.cancelAtPeriodEnd ? "Canceling" : primarySubscription.status
|
|
173
|
+
}
|
|
174
|
+
)
|
|
184
175
|
] }),
|
|
185
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: primarySubscription.cancelAtPeriodEnd ? `Cancels on ${formatDate(primarySubscription.currentPeriodEnd)}` : `Renews on ${formatDate(primarySubscription.currentPeriodEnd)}` }),
|
|
176
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: !primarySubscription.price?.isTrial ? `Ends on ${formatDate(primarySubscription.currentPeriodEnd)}` : primarySubscription.cancelAtPeriodEnd ? `Cancels on ${formatDate(primarySubscription.currentPeriodEnd)}` : `Renews on ${formatDate(primarySubscription.currentPeriodEnd)}` }),
|
|
186
177
|
activeSubscriptions.length > 1 && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
187
178
|
"+",
|
|
188
179
|
activeSubscriptions.length - 1,
|
|
@@ -246,13 +237,22 @@ function PaymentMethodSummaryCard({
|
|
|
246
237
|
/* @__PURE__ */ jsx2(CardContent, { children: paymentMethods.length === 0 ? /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
247
238
|
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-muted-foreground", children: "No payment method" }),
|
|
248
239
|
/* @__PURE__ */ jsx2("p", { className: "text-xs text-muted-foreground", children: "Add a card to enable subscriptions" }),
|
|
249
|
-
/* @__PURE__ */ jsxs2(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
240
|
+
/* @__PURE__ */ jsxs2(
|
|
241
|
+
Button,
|
|
242
|
+
{
|
|
243
|
+
variant: "outline",
|
|
244
|
+
size: "sm",
|
|
245
|
+
className: "mt-2",
|
|
246
|
+
onClick: (e) => {
|
|
247
|
+
e.stopPropagation();
|
|
248
|
+
onManageClick();
|
|
249
|
+
},
|
|
250
|
+
children: [
|
|
251
|
+
"Add Card",
|
|
252
|
+
/* @__PURE__ */ jsx2(ChevronRight2, { className: "h-4 w-4 ml-1" })
|
|
253
|
+
]
|
|
254
|
+
}
|
|
255
|
+
)
|
|
256
256
|
] }) : defaultMethod?.card ? /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
257
257
|
/* @__PURE__ */ jsxs2("p", { className: "text-xl font-bold", children: [
|
|
258
258
|
getCardBrandIcon(defaultMethod.card.brand),
|
|
@@ -533,9 +533,9 @@ function BillingUsageSummaryCard({
|
|
|
533
533
|
__name(BillingUsageSummaryCard, "BillingUsageSummaryCard");
|
|
534
534
|
|
|
535
535
|
// src/features/billing/components/containers/BillingDashboardContainer.tsx
|
|
536
|
-
import { CreditCard as CreditCard4, Loader2 as
|
|
536
|
+
import { CreditCard as CreditCard4, Loader2 as Loader23, Wallet as Wallet2 } from "lucide-react";
|
|
537
537
|
import { useSearchParams } from "next/navigation";
|
|
538
|
-
import { useCallback as useCallback4, useEffect as useEffect9, useMemo as useMemo3, useState as
|
|
538
|
+
import { useCallback as useCallback4, useEffect as useEffect9, useMemo as useMemo3, useState as useState14 } from "react";
|
|
539
539
|
|
|
540
540
|
// src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx
|
|
541
541
|
import { CreditCard as CreditCard2 } from "lucide-react";
|
|
@@ -634,14 +634,7 @@ function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }) {
|
|
|
634
634
|
}
|
|
635
635
|
) }),
|
|
636
636
|
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-x-2", children: [
|
|
637
|
-
/* @__PURE__ */ jsx6(
|
|
638
|
-
Checkbox,
|
|
639
|
-
{
|
|
640
|
-
id: "setAsDefault",
|
|
641
|
-
checked: setAsDefault,
|
|
642
|
-
onCheckedChange: (checked) => setSetAsDefault(!!checked)
|
|
643
|
-
}
|
|
644
|
-
),
|
|
637
|
+
/* @__PURE__ */ jsx6(Checkbox, { id: "setAsDefault", checked: setAsDefault, onCheckedChange: (checked) => setSetAsDefault(!!checked) }),
|
|
645
638
|
/* @__PURE__ */ jsx6(Label, { htmlFor: "setAsDefault", className: "text-sm font-normal", children: "Set as default payment method" })
|
|
646
639
|
] }),
|
|
647
640
|
error && /* @__PURE__ */ jsx6(Alert, { variant: "destructive", className: "bg-red-50 border-red-200", children: /* @__PURE__ */ jsx6(AlertDescription, { children: error }) }),
|
|
@@ -668,13 +661,7 @@ function PaymentMethodEditor({ open, onOpenChange, onSuccess }) {
|
|
|
668
661
|
/* @__PURE__ */ jsx7(DialogTitle, { children: "Add Payment Method" }),
|
|
669
662
|
/* @__PURE__ */ jsx7(DialogDescription, { children: "Add a new payment method to your account. Your card information is securely processed by Stripe." })
|
|
670
663
|
] }),
|
|
671
|
-
open && /* @__PURE__ */ jsx7(
|
|
672
|
-
PaymentMethodForm,
|
|
673
|
-
{
|
|
674
|
-
onSuccess: handleSuccess,
|
|
675
|
-
onCancel: handleCancel
|
|
676
|
-
}
|
|
677
|
-
)
|
|
664
|
+
open && /* @__PURE__ */ jsx7(PaymentMethodForm, { onSuccess: handleSuccess, onCancel: handleCancel })
|
|
678
665
|
] }) });
|
|
679
666
|
}
|
|
680
667
|
__name(PaymentMethodEditor, "PaymentMethodEditor");
|
|
@@ -741,7 +728,18 @@ function PaymentMethodCard({ paymentMethod, onUpdate }) {
|
|
|
741
728
|
/* @__PURE__ */ jsx8("span", { className: "text-sm font-medium capitalize", children: brand })
|
|
742
729
|
] }),
|
|
743
730
|
/* @__PURE__ */ jsxs8(DropdownMenu, { children: [
|
|
744
|
-
/* @__PURE__ */ jsx8(DropdownMenuTrigger, { children: /* @__PURE__ */ jsx8(
|
|
731
|
+
/* @__PURE__ */ jsx8(DropdownMenuTrigger, { children: /* @__PURE__ */ jsx8(
|
|
732
|
+
Button,
|
|
733
|
+
{
|
|
734
|
+
render: /* @__PURE__ */ jsx8("div", {}),
|
|
735
|
+
nativeButton: false,
|
|
736
|
+
variant: "ghost",
|
|
737
|
+
size: "sm",
|
|
738
|
+
disabled: loading,
|
|
739
|
+
className: "h-8 w-8 p-0",
|
|
740
|
+
children: /* @__PURE__ */ jsx8(MoreVertical, { className: "h-4 w-4" })
|
|
741
|
+
}
|
|
742
|
+
) }),
|
|
745
743
|
/* @__PURE__ */ jsxs8(DropdownMenuContent, { align: "end", children: [
|
|
746
744
|
!isDefault && /* @__PURE__ */ jsx8(DropdownMenuItem, { onClick: handleSetDefault, disabled: loading, children: "Set as Default" }),
|
|
747
745
|
/* @__PURE__ */ jsx8(DropdownMenuItem, { onClick: () => setShowRemoveDialog(true), disabled: loading, className: "text-red-600", children: "Remove" })
|
|
@@ -925,7 +923,12 @@ __name(InvoiceStatusBadge, "InvoiceStatusBadge");
|
|
|
925
923
|
|
|
926
924
|
// src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx
|
|
927
925
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
928
|
-
function InvoiceDetails({
|
|
926
|
+
function InvoiceDetails({
|
|
927
|
+
invoice,
|
|
928
|
+
open,
|
|
929
|
+
onOpenChange,
|
|
930
|
+
onInvoiceChange: _onInvoiceChange
|
|
931
|
+
}) {
|
|
929
932
|
const handleDownloadPDF = /* @__PURE__ */ __name(() => {
|
|
930
933
|
if (invoice.stripePdfUrl) {
|
|
931
934
|
window.open(invoice.stripePdfUrl, "_blank");
|
|
@@ -1169,7 +1172,7 @@ function CancelSubscriptionDialog({
|
|
|
1169
1172
|
reason: ""
|
|
1170
1173
|
}
|
|
1171
1174
|
});
|
|
1172
|
-
const onSubmit = /* @__PURE__ */ __name(async (
|
|
1175
|
+
const onSubmit = /* @__PURE__ */ __name(async (_values) => {
|
|
1173
1176
|
setIsSubmitting(true);
|
|
1174
1177
|
try {
|
|
1175
1178
|
await StripeSubscriptionService.cancelSubscription({
|
|
@@ -1338,7 +1341,13 @@ function SubscriptionDetails({
|
|
|
1338
1341
|
/* @__PURE__ */ jsxs14("div", { className: "space-y-6", children: [
|
|
1339
1342
|
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-x-3", children: [
|
|
1340
1343
|
/* @__PURE__ */ jsx17("span", { className: "text-sm font-medium text-muted-foreground", children: "Status:" }),
|
|
1341
|
-
/* @__PURE__ */ jsx17(
|
|
1344
|
+
/* @__PURE__ */ jsx17(
|
|
1345
|
+
SubscriptionStatusBadge,
|
|
1346
|
+
{
|
|
1347
|
+
status: subscription.status,
|
|
1348
|
+
cancelAtPeriodEnd: subscription.cancelAtPeriodEnd
|
|
1349
|
+
}
|
|
1350
|
+
)
|
|
1342
1351
|
] }),
|
|
1343
1352
|
/* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
|
|
1344
1353
|
/* @__PURE__ */ jsxs14("div", { className: "flex justify-between", children: [
|
|
@@ -1425,11 +1434,12 @@ function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan
|
|
|
1425
1434
|
/* @__PURE__ */ jsx18(TableHead, { children: "Status" }),
|
|
1426
1435
|
/* @__PURE__ */ jsx18(TableHead, { children: "Plan" }),
|
|
1427
1436
|
/* @__PURE__ */ jsx18(TableHead, { children: "Period" }),
|
|
1428
|
-
/* @__PURE__ */ jsx18(TableHead, { className: "text-right", children: "Amount" })
|
|
1437
|
+
/* @__PURE__ */ jsx18(TableHead, { className: "text-right", children: "Amount" }),
|
|
1438
|
+
/* @__PURE__ */ jsx18(TableHead, { className: "text-right", children: "Actions" })
|
|
1429
1439
|
] }) }),
|
|
1430
1440
|
/* @__PURE__ */ jsx18(TableBody, { children: subscriptions.map((subscription) => {
|
|
1431
1441
|
const price = subscription.price;
|
|
1432
|
-
const amount = price?.unitAmount ? formatCurrency(price.unitAmount, price.currency) : "
|
|
1442
|
+
const amount = price?.unitAmount ? formatCurrency(price.unitAmount, price.currency) : "0";
|
|
1433
1443
|
const period = `${formatDate3(subscription.currentPeriodStart)} - ${formatDate3(subscription.currentPeriodEnd)}`;
|
|
1434
1444
|
return /* @__PURE__ */ jsxs15(
|
|
1435
1445
|
TableRow,
|
|
@@ -1437,10 +1447,28 @@ function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan
|
|
|
1437
1447
|
onClick: () => handleRowClick(subscription),
|
|
1438
1448
|
className: "cursor-pointer hover:bg-muted/50",
|
|
1439
1449
|
children: [
|
|
1440
|
-
/* @__PURE__ */ jsx18(TableCell, { children: /* @__PURE__ */ jsx18(
|
|
1450
|
+
/* @__PURE__ */ jsx18(TableCell, { children: /* @__PURE__ */ jsx18(
|
|
1451
|
+
SubscriptionStatusBadge,
|
|
1452
|
+
{
|
|
1453
|
+
status: subscription.status,
|
|
1454
|
+
cancelAtPeriodEnd: subscription.cancelAtPeriodEnd
|
|
1455
|
+
}
|
|
1456
|
+
) }),
|
|
1441
1457
|
/* @__PURE__ */ jsx18(TableCell, { className: "font-medium", children: formatPlanName3(price) }),
|
|
1442
1458
|
/* @__PURE__ */ jsx18(TableCell, { className: "text-muted-foreground text-sm", children: period }),
|
|
1443
|
-
/* @__PURE__ */ jsx18(TableCell, { className: "text-right font-medium", children: amount })
|
|
1459
|
+
/* @__PURE__ */ jsx18(TableCell, { className: "text-right font-medium", children: amount }),
|
|
1460
|
+
/* @__PURE__ */ jsx18(TableCell, { className: "text-right", children: (subscription.status === "active" /* ACTIVE */ || subscription.status === "trialing" /* TRIALING */) && onChangePlan && /* @__PURE__ */ jsx18(
|
|
1461
|
+
Button,
|
|
1462
|
+
{
|
|
1463
|
+
size: "sm",
|
|
1464
|
+
variant: "outline",
|
|
1465
|
+
onClick: (e) => {
|
|
1466
|
+
e.stopPropagation();
|
|
1467
|
+
onChangePlan(subscription);
|
|
1468
|
+
},
|
|
1469
|
+
children: "Upgrade"
|
|
1470
|
+
}
|
|
1471
|
+
) })
|
|
1444
1472
|
]
|
|
1445
1473
|
},
|
|
1446
1474
|
subscription.id
|
|
@@ -1537,7 +1565,14 @@ __name(IntervalToggle, "IntervalToggle");
|
|
|
1537
1565
|
// src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx
|
|
1538
1566
|
import { Check } from "lucide-react";
|
|
1539
1567
|
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1540
|
-
function PricingCard({
|
|
1568
|
+
function PricingCard({
|
|
1569
|
+
price,
|
|
1570
|
+
isCurrentPlan = false,
|
|
1571
|
+
isSelected = false,
|
|
1572
|
+
isDisabled = false,
|
|
1573
|
+
isLoading = false,
|
|
1574
|
+
onSelect
|
|
1575
|
+
}) {
|
|
1541
1576
|
const description = price.description || price.nickname || "Standard";
|
|
1542
1577
|
const features = price.features || [];
|
|
1543
1578
|
const formattedPrice = formatCurrency(price.unitAmount, price.currency);
|
|
@@ -1800,7 +1835,11 @@ var initialState = {
|
|
|
1800
1835
|
hasPaymentMethod: false,
|
|
1801
1836
|
isProcessing: false,
|
|
1802
1837
|
error: null,
|
|
1803
|
-
prorationPreview: null
|
|
1838
|
+
prorationPreview: null,
|
|
1839
|
+
promotionCode: null,
|
|
1840
|
+
isValidatingPromoCode: false,
|
|
1841
|
+
promoCodeError: null,
|
|
1842
|
+
isTrialSubscription: false
|
|
1804
1843
|
};
|
|
1805
1844
|
function wizardReducer(state, action) {
|
|
1806
1845
|
switch (action.type) {
|
|
@@ -1818,6 +1857,14 @@ function wizardReducer(state, action) {
|
|
|
1818
1857
|
return { ...state, error: action.error };
|
|
1819
1858
|
case "SET_PRORATION_PREVIEW":
|
|
1820
1859
|
return { ...state, prorationPreview: action.preview };
|
|
1860
|
+
case "SET_PROMOTION_CODE":
|
|
1861
|
+
return { ...state, promotionCode: action.code, promoCodeError: null };
|
|
1862
|
+
case "SET_VALIDATING_PROMO_CODE":
|
|
1863
|
+
return { ...state, isValidatingPromoCode: action.isValidating };
|
|
1864
|
+
case "SET_PROMO_CODE_ERROR":
|
|
1865
|
+
return { ...state, promoCodeError: action.error };
|
|
1866
|
+
case "SET_IS_TRIAL_SUBSCRIPTION":
|
|
1867
|
+
return { ...state, isTrialSubscription: action.isTrial };
|
|
1821
1868
|
case "RESET":
|
|
1822
1869
|
return initialState;
|
|
1823
1870
|
default:
|
|
@@ -1857,6 +1904,19 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1857
1904
|
dispatch({ type: "SET_PROCESSING", isProcessing: true });
|
|
1858
1905
|
try {
|
|
1859
1906
|
await checkPaymentMethod();
|
|
1907
|
+
const isTrialUpgrade = subscription?.status === "trialing" /* TRIALING */;
|
|
1908
|
+
dispatch({ type: "SET_IS_TRIAL_SUBSCRIPTION", isTrial: isTrialUpgrade });
|
|
1909
|
+
if (isTrialUpgrade && !state.hasPaymentMethod) {
|
|
1910
|
+
const methods = await StripeCustomerService.listPaymentMethods();
|
|
1911
|
+
if (methods.length === 0) {
|
|
1912
|
+
dispatch({ type: "SET_STEP", step: "payment-method" });
|
|
1913
|
+
dispatch({
|
|
1914
|
+
type: "SET_ERROR",
|
|
1915
|
+
error: "A payment method is required to upgrade from your trial."
|
|
1916
|
+
});
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1860
1920
|
if (subscription && state.selectedPrice.id !== subscription.price?.id) {
|
|
1861
1921
|
const preview = await StripeSubscriptionService.getProrationPreview({
|
|
1862
1922
|
subscriptionId: subscription.id,
|
|
@@ -1871,22 +1931,31 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1871
1931
|
} finally {
|
|
1872
1932
|
dispatch({ type: "SET_PROCESSING", isProcessing: false });
|
|
1873
1933
|
}
|
|
1874
|
-
}, [state.selectedPrice, subscription, checkPaymentMethod]);
|
|
1934
|
+
}, [state.selectedPrice, state.hasPaymentMethod, subscription, checkPaymentMethod]);
|
|
1875
1935
|
const confirmSubscription = useCallback2(async () => {
|
|
1876
1936
|
if (!state.selectedPrice) return;
|
|
1937
|
+
console.log("[useSubscriptionWizard] confirmSubscription called");
|
|
1938
|
+
console.log("[useSubscriptionWizard] state.promotionCode:", JSON.stringify(state.promotionCode, null, 2));
|
|
1939
|
+
console.log("[useSubscriptionWizard] promotionCodeId to send:", state.promotionCode?.promotionCodeId);
|
|
1877
1940
|
dispatch({ type: "SET_PROCESSING", isProcessing: true });
|
|
1878
1941
|
dispatch({ type: "SET_ERROR", error: null });
|
|
1879
1942
|
try {
|
|
1880
1943
|
if (subscription) {
|
|
1881
|
-
|
|
1944
|
+
const changePlanParams = {
|
|
1882
1945
|
id: subscription.id,
|
|
1883
|
-
newPriceId: state.selectedPrice.id
|
|
1884
|
-
|
|
1946
|
+
newPriceId: state.selectedPrice.id,
|
|
1947
|
+
promotionCode: state.promotionCode?.promotionCodeId
|
|
1948
|
+
};
|
|
1949
|
+
console.log("[useSubscriptionWizard] changePlan params:", JSON.stringify(changePlanParams, null, 2));
|
|
1950
|
+
await StripeSubscriptionService.changePlan(changePlanParams);
|
|
1885
1951
|
} else {
|
|
1886
|
-
|
|
1952
|
+
const createParams = {
|
|
1887
1953
|
id: v4(),
|
|
1888
|
-
priceId: state.selectedPrice.id
|
|
1889
|
-
|
|
1954
|
+
priceId: state.selectedPrice.id,
|
|
1955
|
+
promotionCode: state.promotionCode?.promotionCodeId
|
|
1956
|
+
};
|
|
1957
|
+
console.log("[useSubscriptionWizard] createSubscription params:", JSON.stringify(createParams, null, 2));
|
|
1958
|
+
await StripeSubscriptionService.createSubscription(createParams);
|
|
1890
1959
|
}
|
|
1891
1960
|
onSuccessRef.current();
|
|
1892
1961
|
onCloseRef.current();
|
|
@@ -1908,7 +1977,7 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1908
1977
|
} finally {
|
|
1909
1978
|
dispatch({ type: "SET_PROCESSING", isProcessing: false });
|
|
1910
1979
|
}
|
|
1911
|
-
}, [state.selectedPrice, subscription]);
|
|
1980
|
+
}, [state.selectedPrice, state.promotionCode, subscription]);
|
|
1912
1981
|
const handlePaymentMethodSuccess = useCallback2(async () => {
|
|
1913
1982
|
dispatch({ type: "SET_HAS_PAYMENT_METHOD", hasMethod: true });
|
|
1914
1983
|
dispatch({ type: "SET_STEP", step: "review" });
|
|
@@ -1916,6 +1985,34 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1916
1985
|
const reset = useCallback2(() => {
|
|
1917
1986
|
dispatch({ type: "RESET" });
|
|
1918
1987
|
}, []);
|
|
1988
|
+
const validatePromoCode = useCallback2(
|
|
1989
|
+
async (code) => {
|
|
1990
|
+
dispatch({ type: "SET_VALIDATING_PROMO_CODE", isValidating: true });
|
|
1991
|
+
dispatch({ type: "SET_PROMO_CODE_ERROR", error: null });
|
|
1992
|
+
try {
|
|
1993
|
+
const result = await StripePromotionCodeService.validatePromotionCode({
|
|
1994
|
+
code,
|
|
1995
|
+
stripePriceId: state.selectedPrice?.id
|
|
1996
|
+
});
|
|
1997
|
+
if (result.valid) {
|
|
1998
|
+
dispatch({ type: "SET_PROMOTION_CODE", code: result });
|
|
1999
|
+
} else {
|
|
2000
|
+
dispatch({ type: "SET_PROMO_CODE_ERROR", error: result.errorMessage || "Invalid promotion code" });
|
|
2001
|
+
}
|
|
2002
|
+
} catch (error) {
|
|
2003
|
+
console.error("[useSubscriptionWizard] Promo code validation error:", error);
|
|
2004
|
+
dispatch({ type: "SET_PROMO_CODE_ERROR", error: error?.message || "Failed to validate promotion code" });
|
|
2005
|
+
} finally {
|
|
2006
|
+
dispatch({ type: "SET_VALIDATING_PROMO_CODE", isValidating: false });
|
|
2007
|
+
}
|
|
2008
|
+
},
|
|
2009
|
+
[state.selectedPrice?.id]
|
|
2010
|
+
);
|
|
2011
|
+
const clearPromoCode = useCallback2(() => {
|
|
2012
|
+
dispatch({ type: "SET_PROMOTION_CODE", code: null });
|
|
2013
|
+
dispatch({ type: "SET_PROMO_CODE_ERROR", error: null });
|
|
2014
|
+
dispatch({ type: "SET_ERROR", error: null });
|
|
2015
|
+
}, []);
|
|
1919
2016
|
const actions = useMemo(
|
|
1920
2017
|
() => ({
|
|
1921
2018
|
selectPrice,
|
|
@@ -1925,7 +2022,9 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1925
2022
|
confirmSubscription,
|
|
1926
2023
|
handlePaymentMethodSuccess,
|
|
1927
2024
|
checkPaymentMethod,
|
|
1928
|
-
reset
|
|
2025
|
+
reset,
|
|
2026
|
+
validatePromoCode,
|
|
2027
|
+
clearPromoCode
|
|
1929
2028
|
}),
|
|
1930
2029
|
[
|
|
1931
2030
|
selectPrice,
|
|
@@ -1935,7 +2034,9 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1935
2034
|
confirmSubscription,
|
|
1936
2035
|
handlePaymentMethodSuccess,
|
|
1937
2036
|
checkPaymentMethod,
|
|
1938
|
-
reset
|
|
2037
|
+
reset,
|
|
2038
|
+
validatePromoCode,
|
|
2039
|
+
clearPromoCode
|
|
1939
2040
|
]
|
|
1940
2041
|
);
|
|
1941
2042
|
return {
|
|
@@ -1970,19 +2071,8 @@ function WizardProgressIndicator({ currentStep }) {
|
|
|
1970
2071
|
children: isCompleted ? /* @__PURE__ */ jsx26(Check3, { className: "h-4 w-4" }) : index + 1
|
|
1971
2072
|
}
|
|
1972
2073
|
),
|
|
1973
|
-
/* @__PURE__ */ jsx26(
|
|
1974
|
-
|
|
1975
|
-
{
|
|
1976
|
-
className: `text-sm ${isCurrent ? "font-medium text-foreground" : "text-muted-foreground"}`,
|
|
1977
|
-
children: step.label
|
|
1978
|
-
}
|
|
1979
|
-
),
|
|
1980
|
-
index < STEPS.length - 1 && /* @__PURE__ */ jsx26(
|
|
1981
|
-
"div",
|
|
1982
|
-
{
|
|
1983
|
-
className: `h-0.5 w-8 ${index < currentIndex ? "bg-primary" : "bg-muted"}`
|
|
1984
|
-
}
|
|
1985
|
-
)
|
|
2074
|
+
/* @__PURE__ */ jsx26("span", { className: `text-sm ${isCurrent ? "font-medium text-foreground" : "text-muted-foreground"}`, children: step.label }),
|
|
2075
|
+
index < STEPS.length - 1 && /* @__PURE__ */ jsx26("div", { className: `h-0.5 w-8 ${index < currentIndex ? "bg-primary" : "bg-muted"}` })
|
|
1986
2076
|
] }, step.key);
|
|
1987
2077
|
}) });
|
|
1988
2078
|
}
|
|
@@ -2065,7 +2155,96 @@ __name(WizardStepPlanSelection, "WizardStepPlanSelection");
|
|
|
2065
2155
|
|
|
2066
2156
|
// src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx
|
|
2067
2157
|
import { AlertCircle } from "lucide-react";
|
|
2158
|
+
|
|
2159
|
+
// src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx
|
|
2160
|
+
import { useState as useState12 } from "react";
|
|
2161
|
+
import { Check as Check4, X, Loader2 as Loader22 } from "lucide-react";
|
|
2068
2162
|
import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2163
|
+
function PromoCodeInput({
|
|
2164
|
+
appliedCode,
|
|
2165
|
+
isValidating,
|
|
2166
|
+
error,
|
|
2167
|
+
onApply,
|
|
2168
|
+
onRemove,
|
|
2169
|
+
disabled = false
|
|
2170
|
+
}) {
|
|
2171
|
+
const [code, setCode] = useState12("");
|
|
2172
|
+
const handleApply = /* @__PURE__ */ __name(() => {
|
|
2173
|
+
if (code.trim()) {
|
|
2174
|
+
onApply(code.trim().toUpperCase());
|
|
2175
|
+
}
|
|
2176
|
+
}, "handleApply");
|
|
2177
|
+
const handleKeyDown = /* @__PURE__ */ __name((e) => {
|
|
2178
|
+
if (e.key === "Enter") {
|
|
2179
|
+
e.preventDefault();
|
|
2180
|
+
handleApply();
|
|
2181
|
+
}
|
|
2182
|
+
}, "handleKeyDown");
|
|
2183
|
+
const formatDiscount = /* @__PURE__ */ __name((result) => {
|
|
2184
|
+
if (result.discountType === "percent_off") {
|
|
2185
|
+
return `${result.discountValue}% off`;
|
|
2186
|
+
}
|
|
2187
|
+
const amount = (result.discountValue || 0) / 100;
|
|
2188
|
+
const currency = result.currency?.toUpperCase() || "USD";
|
|
2189
|
+
return `${currency} ${amount.toFixed(2)} off`;
|
|
2190
|
+
}, "formatDiscount");
|
|
2191
|
+
const formatDuration = /* @__PURE__ */ __name((result) => {
|
|
2192
|
+
switch (result.duration) {
|
|
2193
|
+
case "forever":
|
|
2194
|
+
return "Applied to all payments";
|
|
2195
|
+
case "once":
|
|
2196
|
+
return "Applied to first payment only";
|
|
2197
|
+
case "repeating":
|
|
2198
|
+
return `Applied for ${result.durationInMonths} months`;
|
|
2199
|
+
default:
|
|
2200
|
+
return "";
|
|
2201
|
+
}
|
|
2202
|
+
}, "formatDuration");
|
|
2203
|
+
if (appliedCode?.valid) {
|
|
2204
|
+
return /* @__PURE__ */ jsxs25("div", { className: "space-y-2", children: [
|
|
2205
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between p-3 bg-green-50 border border-green-200 rounded-lg", children: [
|
|
2206
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2", children: [
|
|
2207
|
+
/* @__PURE__ */ jsx28(Check4, { className: "h-4 w-4 text-green-600" }),
|
|
2208
|
+
/* @__PURE__ */ jsx28("span", { className: "font-medium text-green-800", children: appliedCode.code }),
|
|
2209
|
+
/* @__PURE__ */ jsx28("span", { className: "text-sm text-green-600", children: formatDiscount(appliedCode) })
|
|
2210
|
+
] }),
|
|
2211
|
+
/* @__PURE__ */ jsx28(
|
|
2212
|
+
Button,
|
|
2213
|
+
{
|
|
2214
|
+
variant: "ghost",
|
|
2215
|
+
size: "sm",
|
|
2216
|
+
onClick: onRemove,
|
|
2217
|
+
disabled,
|
|
2218
|
+
className: "text-green-700 hover:text-green-900 hover:bg-green-100",
|
|
2219
|
+
children: /* @__PURE__ */ jsx28(X, { className: "h-4 w-4" })
|
|
2220
|
+
}
|
|
2221
|
+
)
|
|
2222
|
+
] }),
|
|
2223
|
+
/* @__PURE__ */ jsx28("p", { className: "text-sm text-green-600", children: formatDuration(appliedCode) })
|
|
2224
|
+
] });
|
|
2225
|
+
}
|
|
2226
|
+
return /* @__PURE__ */ jsxs25("div", { className: "space-y-2", children: [
|
|
2227
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex gap-2", children: [
|
|
2228
|
+
/* @__PURE__ */ jsx28(
|
|
2229
|
+
Input,
|
|
2230
|
+
{
|
|
2231
|
+
placeholder: "Enter promo code",
|
|
2232
|
+
value: code,
|
|
2233
|
+
onChange: (e) => setCode(e.target.value.toUpperCase()),
|
|
2234
|
+
onKeyDown: handleKeyDown,
|
|
2235
|
+
disabled: disabled || isValidating,
|
|
2236
|
+
className: "flex-1"
|
|
2237
|
+
}
|
|
2238
|
+
),
|
|
2239
|
+
/* @__PURE__ */ jsx28(Button, { variant: "outline", onClick: handleApply, disabled: disabled || isValidating || !code.trim(), children: isValidating ? /* @__PURE__ */ jsx28(Loader22, { className: "h-4 w-4 animate-spin" }) : "Apply" })
|
|
2240
|
+
] }),
|
|
2241
|
+
error && /* @__PURE__ */ jsx28("p", { className: "text-sm text-red-500", children: error })
|
|
2242
|
+
] });
|
|
2243
|
+
}
|
|
2244
|
+
__name(PromoCodeInput, "PromoCodeInput");
|
|
2245
|
+
|
|
2246
|
+
// src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx
|
|
2247
|
+
import { Fragment as Fragment6, jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2069
2248
|
function WizardStepReview({
|
|
2070
2249
|
selectedPrice,
|
|
2071
2250
|
subscription,
|
|
@@ -2075,10 +2254,16 @@ function WizardStepReview({
|
|
|
2075
2254
|
isProcessing,
|
|
2076
2255
|
onBack,
|
|
2077
2256
|
onAddPaymentMethod,
|
|
2078
|
-
onConfirm
|
|
2257
|
+
onConfirm,
|
|
2258
|
+
promotionCode,
|
|
2259
|
+
isValidatingPromoCode,
|
|
2260
|
+
promoCodeError,
|
|
2261
|
+
onApplyPromoCode,
|
|
2262
|
+
onRemovePromoCode,
|
|
2263
|
+
isTrialUpgrade
|
|
2079
2264
|
}) {
|
|
2080
2265
|
if (!selectedPrice) {
|
|
2081
|
-
return /* @__PURE__ */
|
|
2266
|
+
return /* @__PURE__ */ jsx29("div", { className: "text-center py-8 text-muted-foreground", children: "No plan selected. Please go back and select a plan." });
|
|
2082
2267
|
}
|
|
2083
2268
|
const isChangingPlan = subscription && subscription.price?.id !== selectedPrice.id;
|
|
2084
2269
|
const formatInterval2 = /* @__PURE__ */ __name((price) => {
|
|
@@ -2086,80 +2271,124 @@ function WizardStepReview({
|
|
|
2086
2271
|
const interval = price.recurring?.interval || "month";
|
|
2087
2272
|
return interval === "year" ? "yearly" : "monthly";
|
|
2088
2273
|
}, "formatInterval");
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2274
|
+
const calculateDiscountedPrice = /* @__PURE__ */ __name(() => {
|
|
2275
|
+
if (!promotionCode?.valid || !selectedPrice.unitAmount) return null;
|
|
2276
|
+
const originalPrice = selectedPrice.unitAmount;
|
|
2277
|
+
if (promotionCode.discountType === "percent_off" && promotionCode.discountValue) {
|
|
2278
|
+
return originalPrice * (1 - promotionCode.discountValue / 100);
|
|
2279
|
+
}
|
|
2280
|
+
if (promotionCode.discountType === "amount_off" && promotionCode.discountValue) {
|
|
2281
|
+
return Math.max(0, originalPrice - promotionCode.discountValue);
|
|
2282
|
+
}
|
|
2283
|
+
return null;
|
|
2284
|
+
}, "calculateDiscountedPrice");
|
|
2285
|
+
const discountedPrice = calculateDiscountedPrice();
|
|
2286
|
+
const calculateDiscountedImmediateCharge = /* @__PURE__ */ __name(() => {
|
|
2287
|
+
if (!promotionCode?.valid || !prorationPreview?.immediateCharge) return null;
|
|
2288
|
+
const originalCharge = prorationPreview.immediateCharge;
|
|
2289
|
+
if (promotionCode.discountType === "percent_off" && promotionCode.discountValue) {
|
|
2290
|
+
return originalCharge * (1 - promotionCode.discountValue / 100);
|
|
2291
|
+
}
|
|
2292
|
+
if (promotionCode.discountType === "amount_off" && promotionCode.discountValue) {
|
|
2293
|
+
return Math.max(0, originalCharge - promotionCode.discountValue);
|
|
2294
|
+
}
|
|
2295
|
+
return null;
|
|
2296
|
+
}, "calculateDiscountedImmediateCharge");
|
|
2297
|
+
const discountedImmediateCharge = calculateDiscountedImmediateCharge();
|
|
2298
|
+
const getDiscountDescription = /* @__PURE__ */ __name(() => {
|
|
2299
|
+
if (!promotionCode?.valid) return null;
|
|
2300
|
+
if (promotionCode.discountType === "percent_off" && promotionCode.discountValue) {
|
|
2301
|
+
return `${promotionCode.discountValue}% off`;
|
|
2302
|
+
}
|
|
2303
|
+
if (promotionCode.discountType === "amount_off" && promotionCode.discountValue) {
|
|
2304
|
+
return `${formatCurrency(promotionCode.discountValue, promotionCode.currency || selectedPrice.currency)} off`;
|
|
2305
|
+
}
|
|
2306
|
+
return null;
|
|
2307
|
+
}, "getDiscountDescription");
|
|
2308
|
+
const discountDescription = getDiscountDescription();
|
|
2309
|
+
return /* @__PURE__ */ jsxs26("div", { className: "space-y-6", children: [
|
|
2310
|
+
/* @__PURE__ */ jsxs26("div", { className: "bg-muted/50 rounded-lg p-4 space-y-3", children: [
|
|
2311
|
+
/* @__PURE__ */ jsx29("h3", { className: "font-semibold text-lg", children: "Selected Plan" }),
|
|
2312
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex justify-between items-center", children: [
|
|
2313
|
+
/* @__PURE__ */ jsxs26("div", { children: [
|
|
2314
|
+
/* @__PURE__ */ jsx29("p", { className: "font-medium", children: selectedPrice.product?.name }),
|
|
2315
|
+
selectedPrice.nickname && /* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: selectedPrice.nickname })
|
|
2096
2316
|
] }),
|
|
2097
|
-
/* @__PURE__ */
|
|
2098
|
-
/* @__PURE__ */
|
|
2099
|
-
|
|
2317
|
+
/* @__PURE__ */ jsxs26("div", { className: "text-right", children: [
|
|
2318
|
+
discountedPrice !== null ? /* @__PURE__ */ jsxs26(Fragment6, { children: [
|
|
2319
|
+
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground line-through", children: formatCurrency(selectedPrice.unitAmount || 0, selectedPrice.currency) }),
|
|
2320
|
+
/* @__PURE__ */ jsx29("p", { className: "font-semibold text-lg text-green-600", children: formatCurrency(discountedPrice, selectedPrice.currency) }),
|
|
2321
|
+
discountDescription && /* @__PURE__ */ jsx29("span", { className: "inline-block text-xs bg-green-100 text-green-700 px-2 py-0.5 rounded-full", children: discountDescription })
|
|
2322
|
+
] }) : /* @__PURE__ */ jsx29("p", { className: "font-semibold text-lg", children: formatCurrency(selectedPrice.unitAmount || 0, selectedPrice.currency) }),
|
|
2323
|
+
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: formatInterval2(selectedPrice) })
|
|
2100
2324
|
] })
|
|
2101
2325
|
] })
|
|
2102
2326
|
] }),
|
|
2103
|
-
isChangingPlan && prorationPreview && /* @__PURE__ */
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2327
|
+
isChangingPlan && prorationPreview && /* @__PURE__ */ jsxs26(
|
|
2328
|
+
"div",
|
|
2329
|
+
{
|
|
2330
|
+
className: `${isTrialUpgrade ? "bg-amber-50 border-amber-200" : "bg-blue-50 border-blue-200"} border rounded-lg p-4 space-y-2`,
|
|
2331
|
+
children: [
|
|
2332
|
+
/* @__PURE__ */ jsx29("h4", { className: `font-medium ${isTrialUpgrade ? "text-amber-800" : "text-blue-800"}`, children: isTrialUpgrade ? "Trial Upgrade" : "Proration Summary" }),
|
|
2333
|
+
/* @__PURE__ */ jsx29("p", { className: `text-sm ${isTrialUpgrade ? "text-amber-700" : "text-blue-700"}`, children: isTrialUpgrade ? "Your trial will end immediately and you will be charged the full price." : "Your next charge will be adjusted to account for the plan change." }),
|
|
2334
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex justify-between text-sm", children: [
|
|
2335
|
+
/* @__PURE__ */ jsx29("span", { className: `${isTrialUpgrade ? "text-amber-600" : "text-blue-600"}`, children: isTrialUpgrade ? "Amount to charge now:" : "Amount due now:" }),
|
|
2336
|
+
/* @__PURE__ */ jsx29("span", { className: `font-medium ${isTrialUpgrade ? "text-amber-800" : "text-blue-800"}`, children: discountedImmediateCharge !== null ? /* @__PURE__ */ jsxs26(Fragment6, { children: [
|
|
2337
|
+
/* @__PURE__ */ jsx29("span", { className: "line-through text-muted-foreground mr-2", children: formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency) }),
|
|
2338
|
+
/* @__PURE__ */ jsx29("span", { className: "text-green-600", children: formatCurrency(discountedImmediateCharge, prorationPreview.currency) })
|
|
2339
|
+
] }) : formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency) })
|
|
2340
|
+
] })
|
|
2341
|
+
]
|
|
2342
|
+
}
|
|
2343
|
+
),
|
|
2344
|
+
/* @__PURE__ */ jsxs26("div", { className: "border rounded-lg p-4 space-y-3", children: [
|
|
2345
|
+
/* @__PURE__ */ jsx29("h4", { className: "font-medium", children: "Promotion Code" }),
|
|
2346
|
+
/* @__PURE__ */ jsx29(
|
|
2347
|
+
PromoCodeInput,
|
|
2348
|
+
{
|
|
2349
|
+
appliedCode: promotionCode,
|
|
2350
|
+
isValidating: isValidatingPromoCode,
|
|
2351
|
+
error: promoCodeError,
|
|
2352
|
+
onApply: onApplyPromoCode,
|
|
2353
|
+
onRemove: onRemovePromoCode,
|
|
2354
|
+
disabled: isProcessing
|
|
2355
|
+
}
|
|
2356
|
+
)
|
|
2110
2357
|
] }),
|
|
2111
|
-
/* @__PURE__ */
|
|
2112
|
-
/* @__PURE__ */
|
|
2113
|
-
/* @__PURE__ */
|
|
2114
|
-
/* @__PURE__ */
|
|
2358
|
+
/* @__PURE__ */ jsx29("div", { className: "border rounded-lg p-4", children: /* @__PURE__ */ jsxs26("div", { className: "flex justify-between items-center", children: [
|
|
2359
|
+
/* @__PURE__ */ jsxs26("div", { children: [
|
|
2360
|
+
/* @__PURE__ */ jsx29("h4", { className: "font-medium", children: "Payment Method" }),
|
|
2361
|
+
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: hasPaymentMethod ? "A payment method is on file" : "No payment method on file" })
|
|
2115
2362
|
] }),
|
|
2116
|
-
!hasPaymentMethod && /* @__PURE__ */
|
|
2363
|
+
!hasPaymentMethod && /* @__PURE__ */ jsx29(Button, { variant: "outline", onClick: onAddPaymentMethod, children: "Add Payment Method" })
|
|
2117
2364
|
] }) }),
|
|
2118
|
-
error && /* @__PURE__ */
|
|
2119
|
-
/* @__PURE__ */
|
|
2120
|
-
/* @__PURE__ */
|
|
2365
|
+
error && /* @__PURE__ */ jsxs26(Alert, { variant: "destructive", children: [
|
|
2366
|
+
/* @__PURE__ */ jsx29(AlertCircle, { className: "h-4 w-4" }),
|
|
2367
|
+
/* @__PURE__ */ jsx29(AlertDescription, { children: error })
|
|
2121
2368
|
] }),
|
|
2122
|
-
/* @__PURE__ */
|
|
2123
|
-
/* @__PURE__ */
|
|
2124
|
-
/* @__PURE__ */
|
|
2125
|
-
Button,
|
|
2126
|
-
{
|
|
2127
|
-
onClick: hasPaymentMethod ? onConfirm : onAddPaymentMethod,
|
|
2128
|
-
disabled: isProcessing,
|
|
2129
|
-
children: isProcessing ? "Processing..." : hasPaymentMethod ? isChangingPlan ? "Confirm Plan Change" : "Subscribe Now" : "Add Payment Method"
|
|
2130
|
-
}
|
|
2131
|
-
)
|
|
2369
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex justify-between pt-4 border-t", children: [
|
|
2370
|
+
/* @__PURE__ */ jsx29(Button, { variant: "outline", onClick: onBack, disabled: isProcessing, children: "Back" }),
|
|
2371
|
+
/* @__PURE__ */ jsx29(Button, { onClick: hasPaymentMethod ? onConfirm : onAddPaymentMethod, disabled: isProcessing, children: isProcessing ? "Processing..." : hasPaymentMethod ? isChangingPlan ? "Confirm Plan Change" : "Subscribe Now" : "Add Payment Method" })
|
|
2132
2372
|
] })
|
|
2133
2373
|
] });
|
|
2134
2374
|
}
|
|
2135
2375
|
__name(WizardStepReview, "WizardStepReview");
|
|
2136
2376
|
|
|
2137
2377
|
// src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx
|
|
2138
|
-
import { jsx as
|
|
2139
|
-
function WizardStepPaymentMethod({
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
})
|
|
2144
|
-
return /* @__PURE__ */ jsxs26("div", { className: "space-y-6", children: [
|
|
2145
|
-
/* @__PURE__ */ jsxs26("div", { className: "text-center", children: [
|
|
2146
|
-
/* @__PURE__ */ jsx29("h3", { className: "font-semibold text-lg", children: "Add Payment Method" }),
|
|
2147
|
-
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: "Enter your card details to complete your subscription" })
|
|
2378
|
+
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2379
|
+
function WizardStepPaymentMethod({ onBack, onSuccess, isProcessing }) {
|
|
2380
|
+
return /* @__PURE__ */ jsxs27("div", { className: "space-y-6", children: [
|
|
2381
|
+
/* @__PURE__ */ jsxs27("div", { className: "text-center", children: [
|
|
2382
|
+
/* @__PURE__ */ jsx30("h3", { className: "font-semibold text-lg", children: "Add Payment Method" }),
|
|
2383
|
+
/* @__PURE__ */ jsx30("p", { className: "text-sm text-muted-foreground", children: "Enter your card details to complete your subscription" })
|
|
2148
2384
|
] }),
|
|
2149
|
-
/* @__PURE__ */
|
|
2150
|
-
PaymentMethodForm,
|
|
2151
|
-
{
|
|
2152
|
-
onSuccess,
|
|
2153
|
-
onCancel: onBack,
|
|
2154
|
-
isLoading: isProcessing
|
|
2155
|
-
}
|
|
2156
|
-
)
|
|
2385
|
+
/* @__PURE__ */ jsx30(PaymentMethodForm, { onSuccess, onCancel: onBack, isLoading: isProcessing })
|
|
2157
2386
|
] });
|
|
2158
2387
|
}
|
|
2159
2388
|
__name(WizardStepPaymentMethod, "WizardStepPaymentMethod");
|
|
2160
2389
|
|
|
2161
2390
|
// src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx
|
|
2162
|
-
import { jsx as
|
|
2391
|
+
import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2163
2392
|
function SubscriptionWizard({
|
|
2164
2393
|
open,
|
|
2165
2394
|
onOpenChange,
|
|
@@ -2192,13 +2421,13 @@ function SubscriptionWizard({
|
|
|
2192
2421
|
const isChangePlanMode = !!subscription;
|
|
2193
2422
|
const dialogTitle = subscription ? "Change Subscription Plan" : isPurchasingAddons ? "Purchase Add-ons" : "Subscribe to a Plan";
|
|
2194
2423
|
const dialogDescription = subscription ? "Select a new plan for your subscription" : isPurchasingAddons ? "Select one-time products to purchase" : "Choose a subscription plan to get started";
|
|
2195
|
-
return /* @__PURE__ */
|
|
2196
|
-
/* @__PURE__ */
|
|
2197
|
-
/* @__PURE__ */
|
|
2198
|
-
/* @__PURE__ */
|
|
2424
|
+
return /* @__PURE__ */ jsx31(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs28(DialogContent, { className: "max-w-2xl", children: [
|
|
2425
|
+
/* @__PURE__ */ jsxs28(DialogHeader, { children: [
|
|
2426
|
+
/* @__PURE__ */ jsx31(DialogTitle, { children: dialogTitle }),
|
|
2427
|
+
/* @__PURE__ */ jsx31(DialogDescription, { children: dialogDescription })
|
|
2199
2428
|
] }),
|
|
2200
|
-
/* @__PURE__ */
|
|
2201
|
-
state.step === "plan-selection" && /* @__PURE__ */
|
|
2429
|
+
/* @__PURE__ */ jsx31(WizardProgressIndicator, { currentStep: state.step }),
|
|
2430
|
+
state.step === "plan-selection" && /* @__PURE__ */ jsx31(
|
|
2202
2431
|
WizardStepPlanSelection,
|
|
2203
2432
|
{
|
|
2204
2433
|
selectedPrice: state.selectedPrice,
|
|
@@ -2212,7 +2441,7 @@ function SubscriptionWizard({
|
|
|
2212
2441
|
isProcessing: state.isProcessing
|
|
2213
2442
|
}
|
|
2214
2443
|
),
|
|
2215
|
-
state.step === "review" && /* @__PURE__ */
|
|
2444
|
+
state.step === "review" && /* @__PURE__ */ jsx31(
|
|
2216
2445
|
WizardStepReview,
|
|
2217
2446
|
{
|
|
2218
2447
|
selectedPrice: state.selectedPrice,
|
|
@@ -2223,10 +2452,16 @@ function SubscriptionWizard({
|
|
|
2223
2452
|
isProcessing: state.isProcessing,
|
|
2224
2453
|
onBack: () => actions.goToStep("plan-selection"),
|
|
2225
2454
|
onAddPaymentMethod: () => actions.goToStep("payment-method"),
|
|
2226
|
-
onConfirm: actions.confirmSubscription
|
|
2455
|
+
onConfirm: actions.confirmSubscription,
|
|
2456
|
+
promotionCode: state.promotionCode,
|
|
2457
|
+
isValidatingPromoCode: state.isValidatingPromoCode,
|
|
2458
|
+
promoCodeError: state.promoCodeError,
|
|
2459
|
+
onApplyPromoCode: actions.validatePromoCode,
|
|
2460
|
+
onRemovePromoCode: actions.clearPromoCode,
|
|
2461
|
+
isTrialUpgrade: state.isTrialSubscription
|
|
2227
2462
|
}
|
|
2228
2463
|
),
|
|
2229
|
-
state.step === "payment-method" && /* @__PURE__ */
|
|
2464
|
+
state.step === "payment-method" && /* @__PURE__ */ jsx31(
|
|
2230
2465
|
WizardStepPaymentMethod,
|
|
2231
2466
|
{
|
|
2232
2467
|
onBack: () => actions.goToStep("review"),
|
|
@@ -2240,11 +2475,11 @@ __name(SubscriptionWizard, "SubscriptionWizard");
|
|
|
2240
2475
|
|
|
2241
2476
|
// src/features/billing/stripe-usage/components/containers/UsageContainer.tsx
|
|
2242
2477
|
import { Activity as Activity3 } from "lucide-react";
|
|
2243
|
-
import { useEffect as useEffect8, useState as
|
|
2478
|
+
import { useEffect as useEffect8, useState as useState13 } from "react";
|
|
2244
2479
|
|
|
2245
2480
|
// src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx
|
|
2246
2481
|
import { Activity as Activity2 } from "lucide-react";
|
|
2247
|
-
import { jsx as
|
|
2482
|
+
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2248
2483
|
function getProgressColor(percentage) {
|
|
2249
2484
|
if (percentage === null) return "bg-blue-500";
|
|
2250
2485
|
if (percentage >= 90) return "bg-red-500";
|
|
@@ -2259,7 +2494,7 @@ function formatDate4(date) {
|
|
|
2259
2494
|
month: "short",
|
|
2260
2495
|
day: "numeric"
|
|
2261
2496
|
}).format(new Date(date));
|
|
2262
|
-
} catch (
|
|
2497
|
+
} catch (_error) {
|
|
2263
2498
|
return "Invalid Date";
|
|
2264
2499
|
}
|
|
2265
2500
|
}
|
|
@@ -2272,31 +2507,31 @@ function UsageSummaryCard({ meter, summary }) {
|
|
|
2272
2507
|
const progressWidth = percentage !== null ? Math.min(percentage, 100) : 0;
|
|
2273
2508
|
const displayName = meter.displayName || meter.eventName;
|
|
2274
2509
|
const hasLimit = limit !== null && limit !== void 0;
|
|
2275
|
-
return /* @__PURE__ */
|
|
2276
|
-
/* @__PURE__ */
|
|
2277
|
-
/* @__PURE__ */
|
|
2278
|
-
/* @__PURE__ */
|
|
2279
|
-
/* @__PURE__ */
|
|
2280
|
-
/* @__PURE__ */
|
|
2510
|
+
return /* @__PURE__ */ jsxs29(Card, { children: [
|
|
2511
|
+
/* @__PURE__ */ jsxs29(CardHeader, { className: "flex flex-row items-center gap-x-3 pb-3", children: [
|
|
2512
|
+
/* @__PURE__ */ jsx32("div", { className: "flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600", children: /* @__PURE__ */ jsx32(Activity2, { className: "h-5 w-5" }) }),
|
|
2513
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex flex-col", children: [
|
|
2514
|
+
/* @__PURE__ */ jsx32("h3", { className: "font-semibold", children: displayName }),
|
|
2515
|
+
/* @__PURE__ */ jsx32("p", { className: "text-xs text-gray-500", children: meter.id })
|
|
2281
2516
|
] })
|
|
2282
2517
|
] }),
|
|
2283
|
-
/* @__PURE__ */
|
|
2284
|
-
/* @__PURE__ */
|
|
2285
|
-
/* @__PURE__ */
|
|
2286
|
-
hasLimit && /* @__PURE__ */
|
|
2518
|
+
/* @__PURE__ */ jsxs29(CardContent, { className: "flex flex-col gap-y-4", children: [
|
|
2519
|
+
/* @__PURE__ */ jsxs29("div", { children: [
|
|
2520
|
+
/* @__PURE__ */ jsx32("p", { className: "text-3xl font-bold", children: currentUsage.toLocaleString() }),
|
|
2521
|
+
hasLimit && /* @__PURE__ */ jsxs29("p", { className: "text-sm text-gray-500", children: [
|
|
2287
2522
|
"of ",
|
|
2288
2523
|
limit.toLocaleString(),
|
|
2289
2524
|
" used"
|
|
2290
2525
|
] })
|
|
2291
2526
|
] }),
|
|
2292
|
-
hasLimit ? /* @__PURE__ */
|
|
2293
|
-
/* @__PURE__ */
|
|
2294
|
-
/* @__PURE__ */
|
|
2527
|
+
hasLimit ? /* @__PURE__ */ jsxs29("div", { className: "flex flex-col gap-y-2", children: [
|
|
2528
|
+
/* @__PURE__ */ jsx32("div", { className: "h-2 w-full overflow-hidden rounded-full bg-gray-200", children: /* @__PURE__ */ jsx32("div", { className: `h-full transition-all ${progressColor}`, style: { width: `${progressWidth}%` } }) }),
|
|
2529
|
+
/* @__PURE__ */ jsxs29("p", { className: "text-sm text-gray-500", children: [
|
|
2295
2530
|
percentage?.toFixed(1),
|
|
2296
2531
|
"% used"
|
|
2297
2532
|
] })
|
|
2298
|
-
] }) : /* @__PURE__ */
|
|
2299
|
-
summary && summary.start && summary.end && /* @__PURE__ */
|
|
2533
|
+
] }) : /* @__PURE__ */ jsx32("p", { className: "text-sm text-gray-500", children: "No limit set" }),
|
|
2534
|
+
summary && summary.start && summary.end && /* @__PURE__ */ jsx32("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsxs29("p", { className: "text-xs text-gray-500", children: [
|
|
2300
2535
|
"Period: ",
|
|
2301
2536
|
formatDate4(summary.start),
|
|
2302
2537
|
" - ",
|
|
@@ -2308,19 +2543,19 @@ function UsageSummaryCard({ meter, summary }) {
|
|
|
2308
2543
|
__name(UsageSummaryCard, "UsageSummaryCard");
|
|
2309
2544
|
|
|
2310
2545
|
// src/features/billing/stripe-usage/components/widgets/UsageSummaryCards.tsx
|
|
2311
|
-
import { jsx as
|
|
2546
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
2312
2547
|
function UsageSummaryCards({ meters, summaries }) {
|
|
2313
|
-
return /* @__PURE__ */
|
|
2548
|
+
return /* @__PURE__ */ jsx33("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", children: meters.map((meter) => /* @__PURE__ */ jsx33(UsageSummaryCard, { meter, summary: summaries[meter.id] || null }, meter.id)) });
|
|
2314
2549
|
}
|
|
2315
2550
|
__name(UsageSummaryCards, "UsageSummaryCards");
|
|
2316
2551
|
|
|
2317
2552
|
// src/features/billing/stripe-usage/components/containers/UsageContainer.tsx
|
|
2318
|
-
import { jsx as
|
|
2553
|
+
import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2319
2554
|
function UsageContainer() {
|
|
2320
|
-
const [meters, setMeters] =
|
|
2321
|
-
const [summaries, setSummaries] =
|
|
2322
|
-
const [loading, setLoading] =
|
|
2323
|
-
const [subscriptions, setSubscriptions] =
|
|
2555
|
+
const [meters, setMeters] = useState13([]);
|
|
2556
|
+
const [summaries, setSummaries] = useState13({});
|
|
2557
|
+
const [loading, setLoading] = useState13(true);
|
|
2558
|
+
const [subscriptions, setSubscriptions] = useState13([]);
|
|
2324
2559
|
useEffect8(() => {
|
|
2325
2560
|
loadUsageData();
|
|
2326
2561
|
}, []);
|
|
@@ -2365,27 +2600,27 @@ function UsageContainer() {
|
|
|
2365
2600
|
return null;
|
|
2366
2601
|
}
|
|
2367
2602
|
if (loading) {
|
|
2368
|
-
return /* @__PURE__ */
|
|
2603
|
+
return /* @__PURE__ */ jsx34("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx34("p", { className: "text-muted-foreground", children: "Loading usage data..." }) });
|
|
2369
2604
|
}
|
|
2370
|
-
return /* @__PURE__ */
|
|
2371
|
-
/* @__PURE__ */
|
|
2372
|
-
/* @__PURE__ */
|
|
2373
|
-
/* @__PURE__ */
|
|
2605
|
+
return /* @__PURE__ */ jsxs30("div", { className: "flex w-full flex-col gap-y-6", children: [
|
|
2606
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-x-3", children: [
|
|
2607
|
+
/* @__PURE__ */ jsx34(Activity3, { className: "h-8 w-8" }),
|
|
2608
|
+
/* @__PURE__ */ jsx34("h1", { className: "text-3xl font-bold", children: "Usage Tracking" })
|
|
2374
2609
|
] }),
|
|
2375
|
-
meters.length === 0 && /* @__PURE__ */
|
|
2376
|
-
/* @__PURE__ */
|
|
2377
|
-
/* @__PURE__ */
|
|
2378
|
-
/* @__PURE__ */
|
|
2379
|
-
/* @__PURE__ */
|
|
2610
|
+
meters.length === 0 && /* @__PURE__ */ jsxs30("div", { className: "bg-muted/50 flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed border-gray-300 p-12", children: [
|
|
2611
|
+
/* @__PURE__ */ jsx34(Activity3, { className: "text-muted-foreground h-16 w-16" }),
|
|
2612
|
+
/* @__PURE__ */ jsxs30("div", { className: "text-center", children: [
|
|
2613
|
+
/* @__PURE__ */ jsx34("h3", { className: "mb-2 text-xl font-semibold", children: "No usage meters configured" }),
|
|
2614
|
+
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground", children: "Usage tracking will appear here when you have metered subscriptions with configured meters." })
|
|
2380
2615
|
] })
|
|
2381
2616
|
] }),
|
|
2382
|
-
meters.length > 0 && /* @__PURE__ */
|
|
2617
|
+
meters.length > 0 && /* @__PURE__ */ jsx34(UsageSummaryCards, { meters, summaries })
|
|
2383
2618
|
] });
|
|
2384
2619
|
}
|
|
2385
2620
|
__name(UsageContainer, "UsageContainer");
|
|
2386
2621
|
|
|
2387
2622
|
// src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx
|
|
2388
|
-
import { jsx as
|
|
2623
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2389
2624
|
function formatDateTime(date) {
|
|
2390
2625
|
if (!date) return "N/A";
|
|
2391
2626
|
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
@@ -2397,32 +2632,32 @@ function formatDateTime(date) {
|
|
|
2397
2632
|
hour: "numeric",
|
|
2398
2633
|
minute: "2-digit"
|
|
2399
2634
|
}).format(dateObj);
|
|
2400
|
-
} catch (
|
|
2635
|
+
} catch (_error) {
|
|
2401
2636
|
return "Invalid Date";
|
|
2402
2637
|
}
|
|
2403
2638
|
}
|
|
2404
2639
|
__name(formatDateTime, "formatDateTime");
|
|
2405
2640
|
function UsageHistoryTable({ usageRecords }) {
|
|
2406
2641
|
if (usageRecords.length === 0) {
|
|
2407
|
-
return /* @__PURE__ */
|
|
2642
|
+
return /* @__PURE__ */ jsx35("div", { className: "rounded-lg border p-8 text-center", children: /* @__PURE__ */ jsx35("p", { className: "text-muted-foreground", children: "No usage history available." }) });
|
|
2408
2643
|
}
|
|
2409
|
-
return /* @__PURE__ */
|
|
2410
|
-
/* @__PURE__ */
|
|
2411
|
-
/* @__PURE__ */
|
|
2412
|
-
/* @__PURE__ */
|
|
2413
|
-
/* @__PURE__ */
|
|
2414
|
-
/* @__PURE__ */
|
|
2415
|
-
/* @__PURE__ */
|
|
2416
|
-
/* @__PURE__ */
|
|
2644
|
+
return /* @__PURE__ */ jsxs31("div", { className: "flex w-full flex-col gap-y-4", children: [
|
|
2645
|
+
/* @__PURE__ */ jsx35("h2", { className: "text-xl font-semibold", children: "Usage History" }),
|
|
2646
|
+
/* @__PURE__ */ jsx35("div", { className: "overflow-clip rounded-lg border", children: /* @__PURE__ */ jsxs31(Table, { children: [
|
|
2647
|
+
/* @__PURE__ */ jsx35(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs31(TableRow, { children: [
|
|
2648
|
+
/* @__PURE__ */ jsx35(TableHead, { children: "Date & Time" }),
|
|
2649
|
+
/* @__PURE__ */ jsx35(TableHead, { children: "Meter Event" }),
|
|
2650
|
+
/* @__PURE__ */ jsx35(TableHead, { className: "text-right", children: "Quantity" }),
|
|
2651
|
+
/* @__PURE__ */ jsx35(TableHead, { children: "Event ID" })
|
|
2417
2652
|
] }) }),
|
|
2418
|
-
/* @__PURE__ */
|
|
2653
|
+
/* @__PURE__ */ jsx35(TableBody, { children: usageRecords.map((record) => {
|
|
2419
2654
|
const dateTime = formatDateTime(record.timestamp);
|
|
2420
2655
|
const quantity = record.quantity.toLocaleString();
|
|
2421
|
-
return /* @__PURE__ */
|
|
2422
|
-
/* @__PURE__ */
|
|
2423
|
-
/* @__PURE__ */
|
|
2424
|
-
/* @__PURE__ */
|
|
2425
|
-
/* @__PURE__ */
|
|
2656
|
+
return /* @__PURE__ */ jsxs31(TableRow, { children: [
|
|
2657
|
+
/* @__PURE__ */ jsx35(TableCell, { className: "font-medium", children: dateTime }),
|
|
2658
|
+
/* @__PURE__ */ jsx35(TableCell, { className: "text-muted-foreground", children: record.meterEventName }),
|
|
2659
|
+
/* @__PURE__ */ jsx35(TableCell, { className: "text-right font-medium", children: quantity }),
|
|
2660
|
+
/* @__PURE__ */ jsx35(TableCell, { className: "text-muted-foreground text-sm font-mono", children: record.stripeEventId })
|
|
2426
2661
|
] }, record.id);
|
|
2427
2662
|
}) })
|
|
2428
2663
|
] }) })
|
|
@@ -2431,16 +2666,10 @@ function UsageHistoryTable({ usageRecords }) {
|
|
|
2431
2666
|
__name(UsageHistoryTable, "UsageHistoryTable");
|
|
2432
2667
|
|
|
2433
2668
|
// src/features/billing/components/modals/BillingDetailModal.tsx
|
|
2434
|
-
import { jsx as
|
|
2435
|
-
function BillingDetailModal({
|
|
2436
|
-
open,
|
|
2437
|
-
|
|
2438
|
-
title,
|
|
2439
|
-
children,
|
|
2440
|
-
className
|
|
2441
|
-
}) {
|
|
2442
|
-
return /* @__PURE__ */ jsx35(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs31(DialogContent, { className: className ?? "max-w-4xl max-h-[90vh] overflow-y-auto", children: [
|
|
2443
|
-
/* @__PURE__ */ jsx35(DialogHeader, { children: /* @__PURE__ */ jsx35(DialogTitle, { children: title }) }),
|
|
2669
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2670
|
+
function BillingDetailModal({ open, onOpenChange, title, children, className }) {
|
|
2671
|
+
return /* @__PURE__ */ jsx36(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs32(DialogContent, { className: className ?? "max-w-4xl max-h-[90vh] overflow-y-auto", children: [
|
|
2672
|
+
/* @__PURE__ */ jsx36(DialogHeader, { children: /* @__PURE__ */ jsx36(DialogTitle, { children: title }) }),
|
|
2444
2673
|
children
|
|
2445
2674
|
] }) });
|
|
2446
2675
|
}
|
|
@@ -2448,16 +2677,16 @@ __name(BillingDetailModal, "BillingDetailModal");
|
|
|
2448
2677
|
|
|
2449
2678
|
// src/features/billing/components/widgets/BillingAlertBanner.tsx
|
|
2450
2679
|
import { AlertCircle as AlertCircle2 } from "lucide-react";
|
|
2451
|
-
import { jsx as
|
|
2680
|
+
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2452
2681
|
function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
2453
2682
|
if (subscription.status === "past_due" /* PAST_DUE */) {
|
|
2454
|
-
return /* @__PURE__ */
|
|
2455
|
-
/* @__PURE__ */
|
|
2456
|
-
/* @__PURE__ */
|
|
2457
|
-
/* @__PURE__ */
|
|
2458
|
-
/* @__PURE__ */
|
|
2683
|
+
return /* @__PURE__ */ jsxs33("div", { className: "bg-red-50 border border-red-200 rounded-lg p-4 flex items-start gap-x-3", children: [
|
|
2684
|
+
/* @__PURE__ */ jsx37(AlertCircle2, { className: "h-5 w-5 text-red-600 mt-0.5" }),
|
|
2685
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex-1", children: [
|
|
2686
|
+
/* @__PURE__ */ jsx37("h3", { className: "font-semibold text-red-900", children: "Payment Failed" }),
|
|
2687
|
+
/* @__PURE__ */ jsx37("p", { className: "text-sm text-red-700 mt-1", children: "Your last payment failed. Please update your payment method to avoid service interruption." })
|
|
2459
2688
|
] }),
|
|
2460
|
-
onUpdatePayment && /* @__PURE__ */
|
|
2689
|
+
onUpdatePayment && /* @__PURE__ */ jsx37(Button, { variant: "outline", size: "sm", onClick: onUpdatePayment, className: "border-red-300 text-red-700", children: "Update Payment Method" })
|
|
2461
2690
|
] });
|
|
2462
2691
|
}
|
|
2463
2692
|
if (subscription.status === "trialing" /* TRIALING */ && subscription.trialEnd) {
|
|
@@ -2465,11 +2694,11 @@ function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
|
2465
2694
|
const now = /* @__PURE__ */ new Date();
|
|
2466
2695
|
const daysRemaining = Math.ceil((trialEnd.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
|
|
2467
2696
|
if (daysRemaining <= 7) {
|
|
2468
|
-
return /* @__PURE__ */
|
|
2469
|
-
/* @__PURE__ */
|
|
2470
|
-
/* @__PURE__ */
|
|
2471
|
-
/* @__PURE__ */
|
|
2472
|
-
/* @__PURE__ */
|
|
2697
|
+
return /* @__PURE__ */ jsxs33("div", { className: "bg-yellow-50 border border-yellow-200 rounded-lg p-4 flex items-start gap-x-3", children: [
|
|
2698
|
+
/* @__PURE__ */ jsx37(AlertCircle2, { className: "h-5 w-5 text-yellow-600 mt-0.5" }),
|
|
2699
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex-1", children: [
|
|
2700
|
+
/* @__PURE__ */ jsx37("h3", { className: "font-semibold text-yellow-900", children: "Trial Ending Soon" }),
|
|
2701
|
+
/* @__PURE__ */ jsxs33("p", { className: "text-sm text-yellow-700 mt-1", children: [
|
|
2473
2702
|
"Your trial ends in ",
|
|
2474
2703
|
daysRemaining,
|
|
2475
2704
|
" ",
|
|
@@ -2477,7 +2706,7 @@ function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
|
2477
2706
|
". Add a payment method to continue your subscription."
|
|
2478
2707
|
] })
|
|
2479
2708
|
] }),
|
|
2480
|
-
onAddPayment && /* @__PURE__ */
|
|
2709
|
+
onAddPayment && /* @__PURE__ */ jsx37(Button, { variant: "outline", size: "sm", onClick: onAddPayment, className: "border-yellow-300 text-yellow-700", children: "Add Payment Method" })
|
|
2481
2710
|
] });
|
|
2482
2711
|
}
|
|
2483
2712
|
}
|
|
@@ -2486,9 +2715,9 @@ function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
|
2486
2715
|
__name(BillingAlertBanner, "BillingAlertBanner");
|
|
2487
2716
|
|
|
2488
2717
|
// src/features/billing/components/containers/BillingDashboardContainer.tsx
|
|
2489
|
-
import { Fragment as
|
|
2718
|
+
import { Fragment as Fragment7, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2490
2719
|
function BillingDashboardContainer() {
|
|
2491
|
-
const [data, setData] =
|
|
2720
|
+
const [data, setData] = useState14({
|
|
2492
2721
|
customer: null,
|
|
2493
2722
|
subscriptions: [],
|
|
2494
2723
|
paymentMethods: [],
|
|
@@ -2496,26 +2725,26 @@ function BillingDashboardContainer() {
|
|
|
2496
2725
|
meters: [],
|
|
2497
2726
|
meterSummaries: {}
|
|
2498
2727
|
});
|
|
2499
|
-
const [loading, setLoading] =
|
|
2728
|
+
const [loading, setLoading] = useState14({
|
|
2500
2729
|
customer: true,
|
|
2501
2730
|
subscriptions: true,
|
|
2502
2731
|
paymentMethods: true,
|
|
2503
2732
|
invoices: true,
|
|
2504
2733
|
usage: true
|
|
2505
2734
|
});
|
|
2506
|
-
const [errors, setErrors] =
|
|
2735
|
+
const [errors, setErrors] = useState14({
|
|
2507
2736
|
customer: null,
|
|
2508
2737
|
subscriptions: null,
|
|
2509
2738
|
paymentMethods: null,
|
|
2510
2739
|
invoices: null,
|
|
2511
2740
|
usage: null
|
|
2512
2741
|
});
|
|
2513
|
-
const [activeModal, setActiveModal] =
|
|
2514
|
-
const [noCustomerExists, setNoCustomerExists] =
|
|
2515
|
-
const [creatingCustomer, setCreatingCustomer] =
|
|
2742
|
+
const [activeModal, setActiveModal] = useState14(null);
|
|
2743
|
+
const [noCustomerExists, setNoCustomerExists] = useState14(false);
|
|
2744
|
+
const [creatingCustomer, setCreatingCustomer] = useState14(false);
|
|
2516
2745
|
const searchParams = useSearchParams();
|
|
2517
|
-
const [showWizard, setShowWizard] =
|
|
2518
|
-
const [editingSubscription, setEditingSubscription] =
|
|
2746
|
+
const [showWizard, setShowWizard] = useState14(false);
|
|
2747
|
+
const [editingSubscription, setEditingSubscription] = useState14(null);
|
|
2519
2748
|
const hasMeteredSubscriptions = useCallback4(() => {
|
|
2520
2749
|
return data.subscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
|
|
2521
2750
|
}, [data.subscriptions]);
|
|
@@ -2696,26 +2925,26 @@ function BillingDashboardContainer() {
|
|
|
2696
2925
|
}
|
|
2697
2926
|
}, "getModalTitle");
|
|
2698
2927
|
const isInitialLoading = loading.customer && !noCustomerExists && !data.customer;
|
|
2699
|
-
return /* @__PURE__ */
|
|
2700
|
-
/* @__PURE__ */
|
|
2701
|
-
/* @__PURE__ */
|
|
2702
|
-
/* @__PURE__ */
|
|
2928
|
+
return /* @__PURE__ */ jsxs34("div", { className: "flex w-full flex-col gap-y-6", children: [
|
|
2929
|
+
/* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-x-3", children: [
|
|
2930
|
+
/* @__PURE__ */ jsx38(Wallet2, { className: "h-8 w-8" }),
|
|
2931
|
+
/* @__PURE__ */ jsx38("h1", { className: "text-3xl font-bold", children: "Billing" })
|
|
2703
2932
|
] }),
|
|
2704
|
-
isInitialLoading && /* @__PURE__ */
|
|
2705
|
-
noCustomerExists && !isInitialLoading && /* @__PURE__ */
|
|
2706
|
-
/* @__PURE__ */
|
|
2707
|
-
/* @__PURE__ */
|
|
2708
|
-
/* @__PURE__ */
|
|
2709
|
-
/* @__PURE__ */
|
|
2933
|
+
isInitialLoading && /* @__PURE__ */ jsx38(Card, { children: /* @__PURE__ */ jsx38(CardContent, { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx38(Loader23, { className: "h-8 w-8 animate-spin text-muted-foreground" }) }) }),
|
|
2934
|
+
noCustomerExists && !isInitialLoading && /* @__PURE__ */ jsxs34(Card, { children: [
|
|
2935
|
+
/* @__PURE__ */ jsxs34(CardHeader, { className: "text-center", children: [
|
|
2936
|
+
/* @__PURE__ */ jsx38("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx38(CreditCard4, { className: "h-8 w-8 text-primary" }) }),
|
|
2937
|
+
/* @__PURE__ */ jsx38(CardTitle, { children: "Set Up Billing" }),
|
|
2938
|
+
/* @__PURE__ */ jsx38(CardDescription, { children: "Your company doesn't have a billing account yet. Set one up to manage subscriptions, payment methods, and view invoices." })
|
|
2710
2939
|
] }),
|
|
2711
|
-
/* @__PURE__ */
|
|
2712
|
-
/* @__PURE__ */
|
|
2940
|
+
/* @__PURE__ */ jsx38(CardContent, { className: "flex justify-center pb-8", children: /* @__PURE__ */ jsx38(Button, { onClick: handleCreateCustomer, disabled: creatingCustomer, size: "lg", children: creatingCustomer ? /* @__PURE__ */ jsxs34(Fragment7, { children: [
|
|
2941
|
+
/* @__PURE__ */ jsx38(Loader23, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
2713
2942
|
"Setting up..."
|
|
2714
2943
|
] }) : "Set Up Billing Account" }) }),
|
|
2715
|
-
errors.customer && /* @__PURE__ */
|
|
2944
|
+
errors.customer && /* @__PURE__ */ jsx38(CardContent, { className: "pt-0", children: /* @__PURE__ */ jsx38("p", { className: "text-center text-sm text-destructive", children: errors.customer }) })
|
|
2716
2945
|
] }),
|
|
2717
|
-
!noCustomerExists && !isInitialLoading && /* @__PURE__ */
|
|
2718
|
-
criticalSubscriptions.map((subscription) => /* @__PURE__ */
|
|
2946
|
+
!noCustomerExists && !isInitialLoading && /* @__PURE__ */ jsxs34(Fragment7, { children: [
|
|
2947
|
+
criticalSubscriptions.map((subscription) => /* @__PURE__ */ jsx38(
|
|
2719
2948
|
BillingAlertBanner,
|
|
2720
2949
|
{
|
|
2721
2950
|
subscription,
|
|
@@ -2724,8 +2953,8 @@ function BillingDashboardContainer() {
|
|
|
2724
2953
|
},
|
|
2725
2954
|
subscription.id
|
|
2726
2955
|
)),
|
|
2727
|
-
/* @__PURE__ */
|
|
2728
|
-
/* @__PURE__ */
|
|
2956
|
+
/* @__PURE__ */ jsxs34("div", { className: "grid gap-4 md:grid-cols-2", children: [
|
|
2957
|
+
/* @__PURE__ */ jsx38(
|
|
2729
2958
|
SubscriptionSummaryCard,
|
|
2730
2959
|
{
|
|
2731
2960
|
subscriptions: data.subscriptions,
|
|
@@ -2740,7 +2969,7 @@ function BillingDashboardContainer() {
|
|
|
2740
2969
|
}
|
|
2741
2970
|
}
|
|
2742
2971
|
),
|
|
2743
|
-
/* @__PURE__ */
|
|
2972
|
+
/* @__PURE__ */ jsx38(
|
|
2744
2973
|
PaymentMethodSummaryCard,
|
|
2745
2974
|
{
|
|
2746
2975
|
paymentMethods: data.paymentMethods,
|
|
@@ -2750,7 +2979,7 @@ function BillingDashboardContainer() {
|
|
|
2750
2979
|
onManageClick: () => setActiveModal("payment-methods")
|
|
2751
2980
|
}
|
|
2752
2981
|
),
|
|
2753
|
-
/* @__PURE__ */
|
|
2982
|
+
/* @__PURE__ */ jsx38(
|
|
2754
2983
|
CustomerInfoCard,
|
|
2755
2984
|
{
|
|
2756
2985
|
customer: data.customer,
|
|
@@ -2758,7 +2987,7 @@ function BillingDashboardContainer() {
|
|
|
2758
2987
|
error: errors.customer || void 0
|
|
2759
2988
|
}
|
|
2760
2989
|
),
|
|
2761
|
-
/* @__PURE__ */
|
|
2990
|
+
/* @__PURE__ */ jsx38(
|
|
2762
2991
|
InvoicesSummaryCard,
|
|
2763
2992
|
{
|
|
2764
2993
|
invoices: data.invoices,
|
|
@@ -2767,7 +2996,7 @@ function BillingDashboardContainer() {
|
|
|
2767
2996
|
onViewAllClick: () => setActiveModal("invoices")
|
|
2768
2997
|
}
|
|
2769
2998
|
),
|
|
2770
|
-
hasMeteredSubscriptions() && /* @__PURE__ */
|
|
2999
|
+
hasMeteredSubscriptions() && /* @__PURE__ */ jsx38(
|
|
2771
3000
|
BillingUsageSummaryCard,
|
|
2772
3001
|
{
|
|
2773
3002
|
meters: data.meters,
|
|
@@ -2778,13 +3007,13 @@ function BillingDashboardContainer() {
|
|
|
2778
3007
|
}
|
|
2779
3008
|
)
|
|
2780
3009
|
] }),
|
|
2781
|
-
/* @__PURE__ */
|
|
3010
|
+
/* @__PURE__ */ jsx38(
|
|
2782
3011
|
BillingDetailModal,
|
|
2783
3012
|
{
|
|
2784
3013
|
open: activeModal === "subscriptions",
|
|
2785
3014
|
onOpenChange: handleModalClose,
|
|
2786
3015
|
title: getModalTitle("subscriptions"),
|
|
2787
|
-
children: /* @__PURE__ */
|
|
3016
|
+
children: /* @__PURE__ */ jsx38(
|
|
2788
3017
|
SubscriptionsContainer,
|
|
2789
3018
|
{
|
|
2790
3019
|
onOpenWizard: handleOpenWizard,
|
|
@@ -2793,34 +3022,34 @@ function BillingDashboardContainer() {
|
|
|
2793
3022
|
)
|
|
2794
3023
|
}
|
|
2795
3024
|
),
|
|
2796
|
-
/* @__PURE__ */
|
|
3025
|
+
/* @__PURE__ */ jsx38(
|
|
2797
3026
|
BillingDetailModal,
|
|
2798
3027
|
{
|
|
2799
3028
|
open: activeModal === "payment-methods",
|
|
2800
3029
|
onOpenChange: handleModalClose,
|
|
2801
3030
|
title: getModalTitle("payment-methods"),
|
|
2802
|
-
children: /* @__PURE__ */
|
|
3031
|
+
children: /* @__PURE__ */ jsx38(PaymentMethodsContainer, {})
|
|
2803
3032
|
}
|
|
2804
3033
|
),
|
|
2805
|
-
/* @__PURE__ */
|
|
3034
|
+
/* @__PURE__ */ jsx38(
|
|
2806
3035
|
BillingDetailModal,
|
|
2807
3036
|
{
|
|
2808
3037
|
open: activeModal === "invoices",
|
|
2809
3038
|
onOpenChange: handleModalClose,
|
|
2810
3039
|
title: getModalTitle("invoices"),
|
|
2811
|
-
children: /* @__PURE__ */
|
|
3040
|
+
children: /* @__PURE__ */ jsx38(InvoicesContainer, {})
|
|
2812
3041
|
}
|
|
2813
3042
|
),
|
|
2814
|
-
/* @__PURE__ */
|
|
3043
|
+
/* @__PURE__ */ jsx38(
|
|
2815
3044
|
BillingDetailModal,
|
|
2816
3045
|
{
|
|
2817
3046
|
open: activeModal === "usage",
|
|
2818
3047
|
onOpenChange: handleModalClose,
|
|
2819
3048
|
title: getModalTitle("usage"),
|
|
2820
|
-
children: /* @__PURE__ */
|
|
3049
|
+
children: /* @__PURE__ */ jsx38(UsageContainer, {})
|
|
2821
3050
|
}
|
|
2822
3051
|
),
|
|
2823
|
-
/* @__PURE__ */
|
|
3052
|
+
/* @__PURE__ */ jsx38(
|
|
2824
3053
|
SubscriptionWizard,
|
|
2825
3054
|
{
|
|
2826
3055
|
open: showWizard,
|
|
@@ -2839,7 +3068,7 @@ __name(BillingDashboardContainer, "BillingDashboardContainer");
|
|
|
2839
3068
|
import { Elements } from "@stripe/react-stripe-js";
|
|
2840
3069
|
import { loadStripe } from "@stripe/stripe-js";
|
|
2841
3070
|
import { useMemo as useMemo4 } from "react";
|
|
2842
|
-
import { Fragment as
|
|
3071
|
+
import { Fragment as Fragment8, jsx as jsx39 } from "react/jsx-runtime";
|
|
2843
3072
|
var stripePromiseCache = null;
|
|
2844
3073
|
function getStripePromise(publishableKey) {
|
|
2845
3074
|
if (!publishableKey) {
|
|
@@ -2858,9 +3087,9 @@ function StripeProvider({ children }) {
|
|
|
2858
3087
|
const stripePromise = useMemo4(() => getStripePromise(publishableKey), [publishableKey]);
|
|
2859
3088
|
const options = useMemo4(() => ({}), []);
|
|
2860
3089
|
if (!publishableKey) {
|
|
2861
|
-
return /* @__PURE__ */
|
|
3090
|
+
return /* @__PURE__ */ jsx39(Fragment8, { children });
|
|
2862
3091
|
}
|
|
2863
|
-
return /* @__PURE__ */
|
|
3092
|
+
return /* @__PURE__ */ jsx39(Elements, { stripe: stripePromise, options, children });
|
|
2864
3093
|
}
|
|
2865
3094
|
__name(StripeProvider, "StripeProvider");
|
|
2866
3095
|
function isStripeConfigured() {
|
|
@@ -2871,14 +3100,14 @@ __name(isStripeConfigured, "isStripeConfigured");
|
|
|
2871
3100
|
// src/features/billing/stripe-price/components/forms/PriceEditor.tsx
|
|
2872
3101
|
import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
|
|
2873
3102
|
import { AlertCircle as AlertCircle3, PlusIcon, XIcon } from "lucide-react";
|
|
2874
|
-
import { useEffect as useEffect10, useState as
|
|
3103
|
+
import { useEffect as useEffect10, useState as useState15 } from "react";
|
|
2875
3104
|
import { useForm as useForm2 } from "react-hook-form";
|
|
2876
3105
|
import { v4 as v42 } from "uuid";
|
|
2877
3106
|
import { z as z2 } from "zod";
|
|
2878
|
-
import { jsx as
|
|
3107
|
+
import { jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2879
3108
|
function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
2880
|
-
const [isSubmitting, setIsSubmitting] =
|
|
2881
|
-
const [allFeatures, setAllFeatures] =
|
|
3109
|
+
const [isSubmitting, setIsSubmitting] = useState15(false);
|
|
3110
|
+
const [allFeatures, setAllFeatures] = useState15([]);
|
|
2882
3111
|
useEffect10(() => {
|
|
2883
3112
|
const fetchFeatures = /* @__PURE__ */ __name(async () => {
|
|
2884
3113
|
try {
|
|
@@ -3028,21 +3257,21 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3028
3257
|
{ id: "licensed", text: "Licensed (per unit)" },
|
|
3029
3258
|
{ id: "metered", text: "Metered (usage-based)" }
|
|
3030
3259
|
];
|
|
3031
|
-
return /* @__PURE__ */
|
|
3032
|
-
/* @__PURE__ */
|
|
3033
|
-
/* @__PURE__ */
|
|
3034
|
-
/* @__PURE__ */
|
|
3260
|
+
return /* @__PURE__ */ jsx40(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs35(DialogContent, { className: "max-w-2xl", children: [
|
|
3261
|
+
/* @__PURE__ */ jsxs35(DialogHeader, { children: [
|
|
3262
|
+
/* @__PURE__ */ jsx40(DialogTitle, { children: isEditMode ? "Edit Price" : "Create Price" }),
|
|
3263
|
+
/* @__PURE__ */ jsx40(DialogDescription, { children: isEditMode ? "Update the price details. Note: Only nickname and active status can be changed." : "Create a new price for this product" })
|
|
3035
3264
|
] }),
|
|
3036
|
-
isEditMode && /* @__PURE__ */
|
|
3037
|
-
/* @__PURE__ */
|
|
3038
|
-
/* @__PURE__ */
|
|
3039
|
-
/* @__PURE__ */
|
|
3040
|
-
/* @__PURE__ */
|
|
3265
|
+
isEditMode && /* @__PURE__ */ jsxs35("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-4 flex gap-x-3", children: [
|
|
3266
|
+
/* @__PURE__ */ jsx40(AlertCircle3, { className: "h-5 w-5 text-blue-600 flex-shrink-0 mt-0.5" }),
|
|
3267
|
+
/* @__PURE__ */ jsxs35("div", { className: "text-sm text-blue-800", children: [
|
|
3268
|
+
/* @__PURE__ */ jsx40("p", { className: "font-semibold mb-1", children: "Stripe Price Immutability" }),
|
|
3269
|
+
/* @__PURE__ */ jsx40("p", { children: "Due to Stripe's architecture, only the nickname and active status can be modified after creation. To change amount, currency, or billing interval, create a new price." })
|
|
3041
3270
|
] })
|
|
3042
3271
|
] }),
|
|
3043
|
-
/* @__PURE__ */
|
|
3044
|
-
/* @__PURE__ */
|
|
3045
|
-
/* @__PURE__ */
|
|
3272
|
+
/* @__PURE__ */ jsx40(Form, { ...form, children: /* @__PURE__ */ jsxs35("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
|
|
3273
|
+
/* @__PURE__ */ jsxs35("div", { className: "grid grid-cols-2 gap-x-4", children: [
|
|
3274
|
+
/* @__PURE__ */ jsx40(
|
|
3046
3275
|
FormInput,
|
|
3047
3276
|
{
|
|
3048
3277
|
form,
|
|
@@ -3053,9 +3282,9 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3053
3282
|
isRequired: true
|
|
3054
3283
|
}
|
|
3055
3284
|
),
|
|
3056
|
-
/* @__PURE__ */
|
|
3285
|
+
/* @__PURE__ */ jsx40(FormSelect, { form, id: "currency", name: "Currency", values: currencyOptions, disabled: isEditMode })
|
|
3057
3286
|
] }),
|
|
3058
|
-
/* @__PURE__ */
|
|
3287
|
+
/* @__PURE__ */ jsx40(
|
|
3059
3288
|
FormSelect,
|
|
3060
3289
|
{
|
|
3061
3290
|
form,
|
|
@@ -3065,8 +3294,8 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3065
3294
|
disabled: isEditMode
|
|
3066
3295
|
}
|
|
3067
3296
|
),
|
|
3068
|
-
isRecurring && /* @__PURE__ */
|
|
3069
|
-
/* @__PURE__ */
|
|
3297
|
+
isRecurring && /* @__PURE__ */ jsxs35("div", { className: "grid grid-cols-2 gap-x-4", children: [
|
|
3298
|
+
/* @__PURE__ */ jsx40(
|
|
3070
3299
|
FormInput,
|
|
3071
3300
|
{
|
|
3072
3301
|
form,
|
|
@@ -3077,7 +3306,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3077
3306
|
disabled: isEditMode
|
|
3078
3307
|
}
|
|
3079
3308
|
),
|
|
3080
|
-
/* @__PURE__ */
|
|
3309
|
+
/* @__PURE__ */ jsx40(
|
|
3081
3310
|
FormSelect,
|
|
3082
3311
|
{
|
|
3083
3312
|
form,
|
|
@@ -3088,7 +3317,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3088
3317
|
}
|
|
3089
3318
|
)
|
|
3090
3319
|
] }),
|
|
3091
|
-
/* @__PURE__ */
|
|
3320
|
+
/* @__PURE__ */ jsx40(
|
|
3092
3321
|
FormInput,
|
|
3093
3322
|
{
|
|
3094
3323
|
form,
|
|
@@ -3097,7 +3326,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3097
3326
|
placeholder: "e.g., Standard Plan, Pro Tier"
|
|
3098
3327
|
}
|
|
3099
3328
|
),
|
|
3100
|
-
/* @__PURE__ */
|
|
3329
|
+
/* @__PURE__ */ jsx40(
|
|
3101
3330
|
FormTextarea,
|
|
3102
3331
|
{
|
|
3103
3332
|
form,
|
|
@@ -3107,12 +3336,12 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3107
3336
|
className: "min-h-24"
|
|
3108
3337
|
}
|
|
3109
3338
|
),
|
|
3110
|
-
/* @__PURE__ */
|
|
3111
|
-
/* @__PURE__ */
|
|
3112
|
-
/* @__PURE__ */
|
|
3113
|
-
/* @__PURE__ */
|
|
3114
|
-
form.watch("features").map((_, index) => /* @__PURE__ */
|
|
3115
|
-
/* @__PURE__ */
|
|
3339
|
+
/* @__PURE__ */ jsx40(FormInput, { form, id: "token", name: "Token (optional)", placeholder: "Enter token value" }),
|
|
3340
|
+
/* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
|
|
3341
|
+
/* @__PURE__ */ jsx40(Label, { children: "Features (optional)" }),
|
|
3342
|
+
/* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
|
|
3343
|
+
form.watch("features").map((_, index) => /* @__PURE__ */ jsxs35("div", { className: "flex gap-2", children: [
|
|
3344
|
+
/* @__PURE__ */ jsx40(
|
|
3116
3345
|
Input,
|
|
3117
3346
|
{
|
|
3118
3347
|
...form.register(`features.${index}`),
|
|
@@ -3120,7 +3349,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3120
3349
|
className: "flex-1"
|
|
3121
3350
|
}
|
|
3122
3351
|
),
|
|
3123
|
-
/* @__PURE__ */
|
|
3352
|
+
/* @__PURE__ */ jsx40(
|
|
3124
3353
|
Button,
|
|
3125
3354
|
{
|
|
3126
3355
|
type: "button",
|
|
@@ -3133,11 +3362,11 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3133
3362
|
currentFeatures.filter((_2, i) => i !== index)
|
|
3134
3363
|
);
|
|
3135
3364
|
},
|
|
3136
|
-
children: /* @__PURE__ */
|
|
3365
|
+
children: /* @__PURE__ */ jsx40(XIcon, { className: "h-4 w-4" })
|
|
3137
3366
|
}
|
|
3138
3367
|
)
|
|
3139
3368
|
] }, index)),
|
|
3140
|
-
/* @__PURE__ */
|
|
3369
|
+
/* @__PURE__ */ jsxs35(
|
|
3141
3370
|
Button,
|
|
3142
3371
|
{
|
|
3143
3372
|
type: "button",
|
|
@@ -3149,20 +3378,20 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3149
3378
|
},
|
|
3150
3379
|
className: "mt-2",
|
|
3151
3380
|
children: [
|
|
3152
|
-
/* @__PURE__ */
|
|
3381
|
+
/* @__PURE__ */ jsx40(PlusIcon, { className: "h-4 w-4 mr-2" }),
|
|
3153
3382
|
"Add Feature"
|
|
3154
3383
|
]
|
|
3155
3384
|
}
|
|
3156
3385
|
)
|
|
3157
3386
|
] })
|
|
3158
3387
|
] }),
|
|
3159
|
-
isRecurring && allFeatures.length > 0 && /* @__PURE__ */
|
|
3160
|
-
/* @__PURE__ */
|
|
3161
|
-
/* @__PURE__ */
|
|
3388
|
+
isRecurring && allFeatures.length > 0 && /* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
|
|
3389
|
+
/* @__PURE__ */ jsx40(Label, { children: "Platform Features" }),
|
|
3390
|
+
/* @__PURE__ */ jsx40("div", { className: "border rounded-md p-4 space-y-2 max-h-48 overflow-y-auto", children: allFeatures.map((feature) => {
|
|
3162
3391
|
const isCore = feature.isCore;
|
|
3163
3392
|
const isChecked = form.watch("featureIds").includes(feature.id);
|
|
3164
|
-
return /* @__PURE__ */
|
|
3165
|
-
/* @__PURE__ */
|
|
3393
|
+
return /* @__PURE__ */ jsxs35("div", { className: "flex items-center space-x-2", children: [
|
|
3394
|
+
/* @__PURE__ */ jsx40(
|
|
3166
3395
|
"input",
|
|
3167
3396
|
{
|
|
3168
3397
|
type: "checkbox",
|
|
@@ -3185,22 +3414,22 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3185
3414
|
className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary disabled:opacity-50"
|
|
3186
3415
|
}
|
|
3187
3416
|
),
|
|
3188
|
-
/* @__PURE__ */
|
|
3417
|
+
/* @__PURE__ */ jsxs35(
|
|
3189
3418
|
"label",
|
|
3190
3419
|
{
|
|
3191
3420
|
htmlFor: `feature-${feature.id}`,
|
|
3192
3421
|
className: `text-sm ${isCore ? "text-muted-foreground" : ""}`,
|
|
3193
3422
|
children: [
|
|
3194
3423
|
feature.name,
|
|
3195
|
-
isCore && /* @__PURE__ */
|
|
3424
|
+
isCore && /* @__PURE__ */ jsx40("span", { className: "ml-2 text-xs text-muted-foreground", children: "(Core - Required)" })
|
|
3196
3425
|
]
|
|
3197
3426
|
}
|
|
3198
3427
|
)
|
|
3199
3428
|
] }, feature.id);
|
|
3200
3429
|
}) })
|
|
3201
3430
|
] }),
|
|
3202
|
-
/* @__PURE__ */
|
|
3203
|
-
isRecurring && /* @__PURE__ */
|
|
3431
|
+
/* @__PURE__ */ jsx40(FormCheckbox, { form, id: "active", name: "Active" }),
|
|
3432
|
+
isRecurring && /* @__PURE__ */ jsx40(
|
|
3204
3433
|
FormCheckbox,
|
|
3205
3434
|
{
|
|
3206
3435
|
form,
|
|
@@ -3209,7 +3438,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3209
3438
|
description: "Mark this as the trial subscription plan (only one price should be marked as trial)"
|
|
3210
3439
|
}
|
|
3211
3440
|
),
|
|
3212
|
-
/* @__PURE__ */
|
|
3441
|
+
/* @__PURE__ */ jsx40(CommonEditorButtons, { isEdit: isEditMode, form, disabled: isSubmitting, setOpen: onOpenChange })
|
|
3213
3442
|
] }) })
|
|
3214
3443
|
] }) });
|
|
3215
3444
|
}
|
|
@@ -3217,17 +3446,17 @@ __name(PriceEditor, "PriceEditor");
|
|
|
3217
3446
|
|
|
3218
3447
|
// src/features/billing/stripe-price/components/lists/PricesList.tsx
|
|
3219
3448
|
import { Archive, DollarSign, Edit, RotateCcw } from "lucide-react";
|
|
3220
|
-
import { useEffect as useEffect11, useState as
|
|
3221
|
-
import { jsx as
|
|
3449
|
+
import { useEffect as useEffect11, useState as useState16 } from "react";
|
|
3450
|
+
import { jsx as jsx41, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3222
3451
|
function PricesList({ productId, onPricesChange }) {
|
|
3223
|
-
const [prices, setPrices] =
|
|
3224
|
-
const [loading, setLoading] =
|
|
3225
|
-
const [showCreatePrice, setShowCreatePrice] =
|
|
3226
|
-
const [editingPrice, setEditingPrice] =
|
|
3227
|
-
const [priceToArchive, setPriceToArchive] =
|
|
3228
|
-
const [priceToReactivate, setPriceToReactivate] =
|
|
3229
|
-
const [archivingPriceId, setArchivingPriceId] =
|
|
3230
|
-
const [reactivatingPriceId, setReactivatingPriceId] =
|
|
3452
|
+
const [prices, setPrices] = useState16([]);
|
|
3453
|
+
const [loading, setLoading] = useState16(true);
|
|
3454
|
+
const [showCreatePrice, setShowCreatePrice] = useState16(false);
|
|
3455
|
+
const [editingPrice, setEditingPrice] = useState16(null);
|
|
3456
|
+
const [priceToArchive, setPriceToArchive] = useState16(null);
|
|
3457
|
+
const [priceToReactivate, setPriceToReactivate] = useState16(null);
|
|
3458
|
+
const [archivingPriceId, setArchivingPriceId] = useState16(null);
|
|
3459
|
+
const [reactivatingPriceId, setReactivatingPriceId] = useState16(null);
|
|
3231
3460
|
const loadPrices = /* @__PURE__ */ __name(async () => {
|
|
3232
3461
|
setLoading(true);
|
|
3233
3462
|
try {
|
|
@@ -3290,27 +3519,27 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3290
3519
|
return "";
|
|
3291
3520
|
}, "formatInterval");
|
|
3292
3521
|
if (loading) {
|
|
3293
|
-
return /* @__PURE__ */
|
|
3522
|
+
return /* @__PURE__ */ jsx41("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx41("p", { className: "text-muted-foreground", children: "Loading prices..." }) });
|
|
3294
3523
|
}
|
|
3295
|
-
return /* @__PURE__ */
|
|
3296
|
-
/* @__PURE__ */
|
|
3297
|
-
/* @__PURE__ */
|
|
3298
|
-
/* @__PURE__ */
|
|
3524
|
+
return /* @__PURE__ */ jsxs36("div", { className: "flex flex-col gap-y-4", children: [
|
|
3525
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between mb-4", children: [
|
|
3526
|
+
/* @__PURE__ */ jsx41("h4", { className: "text-lg font-semibold", children: "Prices" }),
|
|
3527
|
+
/* @__PURE__ */ jsx41(Button, { size: "sm", onClick: () => setShowCreatePrice(true), children: "Add Price" })
|
|
3299
3528
|
] }),
|
|
3300
|
-
prices.length === 0 && /* @__PURE__ */
|
|
3301
|
-
/* @__PURE__ */
|
|
3302
|
-
/* @__PURE__ */
|
|
3303
|
-
/* @__PURE__ */
|
|
3529
|
+
prices.length === 0 && /* @__PURE__ */ jsxs36("div", { className: "bg-background flex flex-col items-center justify-center gap-y-3 rounded-lg border border-dashed p-8", children: [
|
|
3530
|
+
/* @__PURE__ */ jsx41(DollarSign, { className: "text-muted-foreground h-12 w-12" }),
|
|
3531
|
+
/* @__PURE__ */ jsx41("p", { className: "text-muted-foreground text-sm", children: "No prices yet. Add a price to enable subscriptions." }),
|
|
3532
|
+
/* @__PURE__ */ jsx41(Button, { size: "sm", onClick: () => setShowCreatePrice(true), children: "Add Price" })
|
|
3304
3533
|
] }),
|
|
3305
|
-
prices.length > 0 && /* @__PURE__ */
|
|
3534
|
+
prices.length > 0 && /* @__PURE__ */ jsx41("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: prices.map((price) => {
|
|
3306
3535
|
const isArchiving = archivingPriceId === price.id;
|
|
3307
3536
|
const isReactivating = reactivatingPriceId === price.id;
|
|
3308
|
-
return /* @__PURE__ */
|
|
3309
|
-
/* @__PURE__ */
|
|
3310
|
-
/* @__PURE__ */
|
|
3311
|
-
/* @__PURE__ */
|
|
3312
|
-
/* @__PURE__ */
|
|
3313
|
-
price.active ? /* @__PURE__ */
|
|
3537
|
+
return /* @__PURE__ */ jsxs36("div", { className: "border rounded-lg bg-white p-4 hover:shadow-sm transition-shadow", children: [
|
|
3538
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-start justify-between mb-3", children: [
|
|
3539
|
+
/* @__PURE__ */ jsx41(DollarSign, { className: "h-5 w-5 text-primary" }),
|
|
3540
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex gap-1", children: [
|
|
3541
|
+
/* @__PURE__ */ jsx41(Button, { variant: "ghost", size: "sm", onClick: () => setEditingPrice(price), className: "h-8 w-8 p-0", children: /* @__PURE__ */ jsx41(Edit, { className: "h-4 w-4" }) }),
|
|
3542
|
+
price.active ? /* @__PURE__ */ jsx41(
|
|
3314
3543
|
Button,
|
|
3315
3544
|
{
|
|
3316
3545
|
variant: "ghost",
|
|
@@ -3318,9 +3547,9 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3318
3547
|
onClick: () => setPriceToArchive(price),
|
|
3319
3548
|
className: "h-8 w-8 p-0",
|
|
3320
3549
|
disabled: isArchiving,
|
|
3321
|
-
children: /* @__PURE__ */
|
|
3550
|
+
children: /* @__PURE__ */ jsx41(Archive, { className: "h-4 w-4" })
|
|
3322
3551
|
}
|
|
3323
|
-
) : /* @__PURE__ */
|
|
3552
|
+
) : /* @__PURE__ */ jsx41(
|
|
3324
3553
|
Button,
|
|
3325
3554
|
{
|
|
3326
3555
|
variant: "ghost",
|
|
@@ -3328,25 +3557,25 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3328
3557
|
onClick: () => setPriceToReactivate(price),
|
|
3329
3558
|
className: "h-8 w-8 p-0",
|
|
3330
3559
|
disabled: isReactivating,
|
|
3331
|
-
children: /* @__PURE__ */
|
|
3560
|
+
children: /* @__PURE__ */ jsx41(RotateCcw, { className: "h-4 w-4" })
|
|
3332
3561
|
}
|
|
3333
3562
|
)
|
|
3334
3563
|
] })
|
|
3335
3564
|
] }),
|
|
3336
|
-
/* @__PURE__ */
|
|
3565
|
+
/* @__PURE__ */ jsx41("div", { className: "mb-2", children: /* @__PURE__ */ jsxs36("div", { className: "text-2xl font-bold", children: [
|
|
3337
3566
|
formatCurrency(price.unitAmount, price.currency),
|
|
3338
3567
|
" ",
|
|
3339
|
-
/* @__PURE__ */
|
|
3568
|
+
/* @__PURE__ */ jsx41("span", { className: "text-muted-foreground text-sm font-normal", children: formatInterval2(price) })
|
|
3340
3569
|
] }) }),
|
|
3341
|
-
price.metadata?.nickname && /* @__PURE__ */
|
|
3342
|
-
/* @__PURE__ */
|
|
3343
|
-
price.active ? /* @__PURE__ */
|
|
3344
|
-
price.recurring?.usageType === "metered" && /* @__PURE__ */
|
|
3345
|
-
/* @__PURE__ */
|
|
3570
|
+
price.metadata?.nickname && /* @__PURE__ */ jsx41("p", { className: "text-sm font-medium mb-2", children: price.metadata.nickname }),
|
|
3571
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex flex-wrap gap-2", children: [
|
|
3572
|
+
price.active ? /* @__PURE__ */ jsx41("span", { className: "bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full font-medium", children: "Active" }) : /* @__PURE__ */ jsx41("span", { className: "bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded-full font-medium", children: "Inactive" }),
|
|
3573
|
+
price.recurring?.usageType === "metered" && /* @__PURE__ */ jsx41("span", { className: "bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full font-medium", children: "Metered" }),
|
|
3574
|
+
/* @__PURE__ */ jsx41("span", { className: "bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded-full font-medium uppercase", children: price.currency })
|
|
3346
3575
|
] })
|
|
3347
3576
|
] }, price.id);
|
|
3348
3577
|
}) }),
|
|
3349
|
-
showCreatePrice && /* @__PURE__ */
|
|
3578
|
+
showCreatePrice && /* @__PURE__ */ jsx41(
|
|
3350
3579
|
PriceEditor,
|
|
3351
3580
|
{
|
|
3352
3581
|
productId,
|
|
@@ -3358,7 +3587,7 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3358
3587
|
}
|
|
3359
3588
|
}
|
|
3360
3589
|
),
|
|
3361
|
-
editingPrice && /* @__PURE__ */
|
|
3590
|
+
editingPrice && /* @__PURE__ */ jsx41(
|
|
3362
3591
|
PriceEditor,
|
|
3363
3592
|
{
|
|
3364
3593
|
productId,
|
|
@@ -3372,19 +3601,19 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3372
3601
|
}
|
|
3373
3602
|
}
|
|
3374
3603
|
),
|
|
3375
|
-
/* @__PURE__ */
|
|
3376
|
-
/* @__PURE__ */
|
|
3377
|
-
/* @__PURE__ */
|
|
3378
|
-
/* @__PURE__ */
|
|
3604
|
+
/* @__PURE__ */ jsx41(AlertDialog, { open: !!priceToArchive, onOpenChange: (open) => !open && setPriceToArchive(null), children: /* @__PURE__ */ jsxs36(AlertDialogContent, { children: [
|
|
3605
|
+
/* @__PURE__ */ jsxs36(AlertDialogHeader, { children: [
|
|
3606
|
+
/* @__PURE__ */ jsx41(AlertDialogTitle, { children: "Archive Price" }),
|
|
3607
|
+
/* @__PURE__ */ jsxs36(AlertDialogDescription, { children: [
|
|
3379
3608
|
"Are you sure you want to archive the price for",
|
|
3380
3609
|
" ",
|
|
3381
3610
|
priceToArchive && `${formatCurrency(priceToArchive.unitAmount, priceToArchive.currency)} ${formatInterval2(priceToArchive)}`,
|
|
3382
3611
|
"? This will prevent new subscriptions but existing ones will continue."
|
|
3383
3612
|
] })
|
|
3384
3613
|
] }),
|
|
3385
|
-
/* @__PURE__ */
|
|
3386
|
-
/* @__PURE__ */
|
|
3387
|
-
/* @__PURE__ */
|
|
3614
|
+
/* @__PURE__ */ jsxs36(AlertDialogFooter, { children: [
|
|
3615
|
+
/* @__PURE__ */ jsx41(AlertDialogCancel, { disabled: !!archivingPriceId, children: "Cancel" }),
|
|
3616
|
+
/* @__PURE__ */ jsx41(
|
|
3388
3617
|
AlertDialogAction,
|
|
3389
3618
|
{
|
|
3390
3619
|
onClick: handleArchive,
|
|
@@ -3395,19 +3624,19 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3395
3624
|
)
|
|
3396
3625
|
] })
|
|
3397
3626
|
] }) }),
|
|
3398
|
-
/* @__PURE__ */
|
|
3399
|
-
/* @__PURE__ */
|
|
3400
|
-
/* @__PURE__ */
|
|
3401
|
-
/* @__PURE__ */
|
|
3627
|
+
/* @__PURE__ */ jsx41(AlertDialog, { open: !!priceToReactivate, onOpenChange: (open) => !open && setPriceToReactivate(null), children: /* @__PURE__ */ jsxs36(AlertDialogContent, { children: [
|
|
3628
|
+
/* @__PURE__ */ jsxs36(AlertDialogHeader, { children: [
|
|
3629
|
+
/* @__PURE__ */ jsx41(AlertDialogTitle, { children: "Reactivate Price" }),
|
|
3630
|
+
/* @__PURE__ */ jsxs36(AlertDialogDescription, { children: [
|
|
3402
3631
|
"Are you sure you want to reactivate the price for",
|
|
3403
3632
|
" ",
|
|
3404
3633
|
priceToReactivate && `${formatCurrency(priceToReactivate.unitAmount, priceToReactivate.currency)} ${formatInterval2(priceToReactivate)}`,
|
|
3405
3634
|
"? This will allow new subscriptions again."
|
|
3406
3635
|
] })
|
|
3407
3636
|
] }),
|
|
3408
|
-
/* @__PURE__ */
|
|
3409
|
-
/* @__PURE__ */
|
|
3410
|
-
/* @__PURE__ */
|
|
3637
|
+
/* @__PURE__ */ jsxs36(AlertDialogFooter, { children: [
|
|
3638
|
+
/* @__PURE__ */ jsx41(AlertDialogCancel, { disabled: !!reactivatingPriceId, children: "Cancel" }),
|
|
3639
|
+
/* @__PURE__ */ jsx41(
|
|
3411
3640
|
AlertDialogAction,
|
|
3412
3641
|
{
|
|
3413
3642
|
onClick: handleReactivate,
|
|
@@ -3424,17 +3653,17 @@ __name(PricesList, "PricesList");
|
|
|
3424
3653
|
|
|
3425
3654
|
// src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx
|
|
3426
3655
|
import { Package as Package2 } from "lucide-react";
|
|
3427
|
-
import { useEffect as useEffect12, useState as
|
|
3656
|
+
import { useEffect as useEffect12, useState as useState19 } from "react";
|
|
3428
3657
|
|
|
3429
3658
|
// src/features/billing/stripe-product/components/forms/ProductEditor.tsx
|
|
3430
3659
|
import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
|
|
3431
|
-
import { useState as
|
|
3660
|
+
import { useState as useState17 } from "react";
|
|
3432
3661
|
import { useForm as useForm3 } from "react-hook-form";
|
|
3433
3662
|
import { v4 as v43 } from "uuid";
|
|
3434
3663
|
import { z as z3 } from "zod";
|
|
3435
|
-
import { jsx as
|
|
3664
|
+
import { jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3436
3665
|
function ProductEditor({ product, open, onOpenChange, onSuccess }) {
|
|
3437
|
-
const [isSubmitting, setIsSubmitting] =
|
|
3666
|
+
const [isSubmitting, setIsSubmitting] = useState17(false);
|
|
3438
3667
|
const formSchema2 = z3.object({
|
|
3439
3668
|
name: z3.string().min(1, { message: "Product name is required" }),
|
|
3440
3669
|
description: z3.string().min(1, { message: "Description is required" }),
|
|
@@ -3474,14 +3703,14 @@ function ProductEditor({ product, open, onOpenChange, onSuccess }) {
|
|
|
3474
3703
|
setIsSubmitting(false);
|
|
3475
3704
|
}
|
|
3476
3705
|
}, "onSubmit");
|
|
3477
|
-
return /* @__PURE__ */
|
|
3478
|
-
/* @__PURE__ */
|
|
3479
|
-
/* @__PURE__ */
|
|
3480
|
-
/* @__PURE__ */
|
|
3706
|
+
return /* @__PURE__ */ jsx42(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs37(DialogContent, { className: "max-w-2xl", children: [
|
|
3707
|
+
/* @__PURE__ */ jsxs37(DialogHeader, { children: [
|
|
3708
|
+
/* @__PURE__ */ jsx42(DialogTitle, { children: product ? "Edit Product" : "Create Product" }),
|
|
3709
|
+
/* @__PURE__ */ jsx42(DialogDescription, { children: product ? `Update the details for ${product.name}` : "Create a new product to offer to your customers" })
|
|
3481
3710
|
] }),
|
|
3482
|
-
/* @__PURE__ */
|
|
3483
|
-
/* @__PURE__ */
|
|
3484
|
-
/* @__PURE__ */
|
|
3711
|
+
/* @__PURE__ */ jsx42(Form, { ...form, children: /* @__PURE__ */ jsxs37("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
|
|
3712
|
+
/* @__PURE__ */ jsx42(FormInput, { form, id: "name", name: "Product Name", placeholder: "Enter product name", isRequired: true }),
|
|
3713
|
+
/* @__PURE__ */ jsx42(
|
|
3485
3714
|
FormTextarea,
|
|
3486
3715
|
{
|
|
3487
3716
|
form,
|
|
@@ -3491,8 +3720,8 @@ function ProductEditor({ product, open, onOpenChange, onSuccess }) {
|
|
|
3491
3720
|
className: "min-h-32"
|
|
3492
3721
|
}
|
|
3493
3722
|
),
|
|
3494
|
-
/* @__PURE__ */
|
|
3495
|
-
/* @__PURE__ */
|
|
3723
|
+
/* @__PURE__ */ jsx42(FormCheckbox, { form, id: "active", name: "Active" }),
|
|
3724
|
+
/* @__PURE__ */ jsx42(CommonEditorButtons, { isEdit: !!product, form, disabled: isSubmitting, setOpen: onOpenChange })
|
|
3496
3725
|
] }) })
|
|
3497
3726
|
] }) });
|
|
3498
3727
|
}
|
|
@@ -3500,26 +3729,26 @@ __name(ProductEditor, "ProductEditor");
|
|
|
3500
3729
|
|
|
3501
3730
|
// src/features/billing/stripe-product/components/lists/ProductsList.tsx
|
|
3502
3731
|
import { Archive as Archive2, ChevronDown, ChevronUp, Edit as Edit2, Package, RefreshCw as RefreshCw2 } from "lucide-react";
|
|
3503
|
-
import { useState as
|
|
3504
|
-
import { jsx as
|
|
3732
|
+
import { useState as useState18 } from "react";
|
|
3733
|
+
import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3505
3734
|
function ProductsList({ products, onProductsChange }) {
|
|
3506
|
-
const [expandedProductId, setExpandedProductId] =
|
|
3507
|
-
const [editingProduct, setEditingProduct] =
|
|
3508
|
-
const [archivingProductId, setArchivingProductId] =
|
|
3509
|
-
const [reactivatingProductId, setReactivatingProductId] =
|
|
3510
|
-
const [productToArchive, setProductToArchive] =
|
|
3511
|
-
const [productToReactivate, setProductToReactivate] =
|
|
3735
|
+
const [expandedProductId, setExpandedProductId] = useState18(null);
|
|
3736
|
+
const [editingProduct, setEditingProduct] = useState18(null);
|
|
3737
|
+
const [archivingProductId, setArchivingProductId] = useState18(null);
|
|
3738
|
+
const [reactivatingProductId, setReactivatingProductId] = useState18(null);
|
|
3739
|
+
const [productToArchive, setProductToArchive] = useState18(null);
|
|
3740
|
+
const [productToReactivate, setProductToReactivate] = useState18(null);
|
|
3512
3741
|
const handleArchive = /* @__PURE__ */ __name(async () => {
|
|
3513
3742
|
if (!productToArchive) {
|
|
3514
3743
|
return;
|
|
3515
3744
|
}
|
|
3516
3745
|
setArchivingProductId(productToArchive.id);
|
|
3517
3746
|
try {
|
|
3518
|
-
const
|
|
3747
|
+
const _archivedProduct = await StripeProductService.archiveProduct({ id: productToArchive.id });
|
|
3519
3748
|
setProductToArchive(null);
|
|
3520
3749
|
onProductsChange();
|
|
3521
|
-
} catch (
|
|
3522
|
-
console.error("[ProductsList] Failed to archive product:",
|
|
3750
|
+
} catch (_error) {
|
|
3751
|
+
console.error("[ProductsList] Failed to archive product:", _error);
|
|
3523
3752
|
} finally {
|
|
3524
3753
|
setArchivingProductId(null);
|
|
3525
3754
|
}
|
|
@@ -3530,10 +3759,10 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3530
3759
|
}
|
|
3531
3760
|
setReactivatingProductId(productToReactivate.id);
|
|
3532
3761
|
try {
|
|
3533
|
-
const
|
|
3762
|
+
const _reactivatedProduct = await StripeProductService.reactivateProduct({ id: productToReactivate.id });
|
|
3534
3763
|
setProductToReactivate(null);
|
|
3535
3764
|
onProductsChange();
|
|
3536
|
-
} catch (
|
|
3765
|
+
} catch (_error) {
|
|
3537
3766
|
} finally {
|
|
3538
3767
|
setReactivatingProductId(null);
|
|
3539
3768
|
}
|
|
@@ -3541,29 +3770,29 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3541
3770
|
const toggleExpand = /* @__PURE__ */ __name((productId) => {
|
|
3542
3771
|
setExpandedProductId(expandedProductId === productId ? null : productId);
|
|
3543
3772
|
}, "toggleExpand");
|
|
3544
|
-
return /* @__PURE__ */
|
|
3773
|
+
return /* @__PURE__ */ jsxs38("div", { className: "flex flex-col gap-y-4", children: [
|
|
3545
3774
|
products.map((product) => {
|
|
3546
3775
|
const isExpanded = expandedProductId === product.id;
|
|
3547
3776
|
const isArchiving = archivingProductId === product.id;
|
|
3548
3777
|
const isReactivating = reactivatingProductId === product.id;
|
|
3549
|
-
return /* @__PURE__ */
|
|
3550
|
-
/* @__PURE__ */
|
|
3551
|
-
/* @__PURE__ */
|
|
3552
|
-
/* @__PURE__ */
|
|
3553
|
-
/* @__PURE__ */
|
|
3554
|
-
/* @__PURE__ */
|
|
3555
|
-
/* @__PURE__ */
|
|
3556
|
-
product.active ? /* @__PURE__ */
|
|
3778
|
+
return /* @__PURE__ */ jsxs38("div", { className: "border rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow", children: [
|
|
3779
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex items-center justify-between p-6", children: [
|
|
3780
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-x-4 flex-1", children: [
|
|
3781
|
+
/* @__PURE__ */ jsx43(Package, { className: "h-6 w-6 text-primary" }),
|
|
3782
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex-1", children: [
|
|
3783
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-x-3", children: [
|
|
3784
|
+
/* @__PURE__ */ jsx43("h3", { className: "text-lg font-semibold", children: product.name }),
|
|
3785
|
+
product.active ? /* @__PURE__ */ jsx43("span", { className: "bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full font-medium", children: "Active" }) : /* @__PURE__ */ jsx43("span", { className: "bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded-full font-medium", children: "Inactive" })
|
|
3557
3786
|
] }),
|
|
3558
|
-
product.description && /* @__PURE__ */
|
|
3787
|
+
product.description && /* @__PURE__ */ jsx43("p", { className: "text-muted-foreground text-sm mt-1", children: product.description })
|
|
3559
3788
|
] })
|
|
3560
3789
|
] }),
|
|
3561
|
-
/* @__PURE__ */
|
|
3562
|
-
/* @__PURE__ */
|
|
3563
|
-
/* @__PURE__ */
|
|
3790
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-x-2", children: [
|
|
3791
|
+
/* @__PURE__ */ jsxs38(Button, { variant: "outline", size: "sm", onClick: () => setEditingProduct(product), children: [
|
|
3792
|
+
/* @__PURE__ */ jsx43(Edit2, { className: "h-4 w-4 mr-1" }),
|
|
3564
3793
|
"Edit"
|
|
3565
3794
|
] }),
|
|
3566
|
-
product.active ? /* @__PURE__ */
|
|
3795
|
+
product.active ? /* @__PURE__ */ jsxs38(
|
|
3567
3796
|
Button,
|
|
3568
3797
|
{
|
|
3569
3798
|
variant: "outline",
|
|
@@ -3571,11 +3800,11 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3571
3800
|
onClick: () => setProductToArchive(product),
|
|
3572
3801
|
disabled: isArchiving,
|
|
3573
3802
|
children: [
|
|
3574
|
-
/* @__PURE__ */
|
|
3803
|
+
/* @__PURE__ */ jsx43(Archive2, { className: "h-4 w-4 mr-1" }),
|
|
3575
3804
|
isArchiving ? "Archiving..." : "Archive"
|
|
3576
3805
|
]
|
|
3577
3806
|
}
|
|
3578
|
-
) : /* @__PURE__ */
|
|
3807
|
+
) : /* @__PURE__ */ jsxs38(
|
|
3579
3808
|
Button,
|
|
3580
3809
|
{
|
|
3581
3810
|
variant: "outline",
|
|
@@ -3583,18 +3812,18 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3583
3812
|
onClick: () => setProductToReactivate(product),
|
|
3584
3813
|
disabled: isReactivating,
|
|
3585
3814
|
children: [
|
|
3586
|
-
/* @__PURE__ */
|
|
3815
|
+
/* @__PURE__ */ jsx43(RefreshCw2, { className: "h-4 w-4 mr-1" }),
|
|
3587
3816
|
isReactivating ? "Reactivating..." : "Reactivate"
|
|
3588
3817
|
]
|
|
3589
3818
|
}
|
|
3590
3819
|
),
|
|
3591
|
-
/* @__PURE__ */
|
|
3820
|
+
/* @__PURE__ */ jsx43(Button, { variant: "ghost", size: "sm", onClick: () => toggleExpand(product.id), children: isExpanded ? /* @__PURE__ */ jsx43(ChevronUp, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx43(ChevronDown, { className: "h-5 w-5" }) })
|
|
3592
3821
|
] })
|
|
3593
3822
|
] }),
|
|
3594
|
-
isExpanded && /* @__PURE__ */
|
|
3823
|
+
isExpanded && /* @__PURE__ */ jsx43("div", { className: "border-t bg-muted/30 p-6", children: /* @__PURE__ */ jsx43(PricesList, { productId: product.id, onPricesChange: onProductsChange }) })
|
|
3595
3824
|
] }, product.id);
|
|
3596
3825
|
}),
|
|
3597
|
-
editingProduct && /* @__PURE__ */
|
|
3826
|
+
editingProduct && /* @__PURE__ */ jsx43(
|
|
3598
3827
|
ProductEditor,
|
|
3599
3828
|
{
|
|
3600
3829
|
product: editingProduct,
|
|
@@ -3606,18 +3835,18 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3606
3835
|
}
|
|
3607
3836
|
}
|
|
3608
3837
|
),
|
|
3609
|
-
/* @__PURE__ */
|
|
3610
|
-
/* @__PURE__ */
|
|
3611
|
-
/* @__PURE__ */
|
|
3612
|
-
/* @__PURE__ */
|
|
3838
|
+
/* @__PURE__ */ jsx43(AlertDialog, { open: !!productToArchive, onOpenChange: (open) => !open && setProductToArchive(null), children: /* @__PURE__ */ jsxs38(AlertDialogContent, { children: [
|
|
3839
|
+
/* @__PURE__ */ jsxs38(AlertDialogHeader, { children: [
|
|
3840
|
+
/* @__PURE__ */ jsx43(AlertDialogTitle, { children: "Archive Product" }),
|
|
3841
|
+
/* @__PURE__ */ jsxs38(AlertDialogDescription, { children: [
|
|
3613
3842
|
'Are you sure you want to archive "',
|
|
3614
3843
|
productToArchive?.name,
|
|
3615
3844
|
'"? This will deactivate it and it will no longer be available for new subscriptions.'
|
|
3616
3845
|
] })
|
|
3617
3846
|
] }),
|
|
3618
|
-
/* @__PURE__ */
|
|
3619
|
-
/* @__PURE__ */
|
|
3620
|
-
/* @__PURE__ */
|
|
3847
|
+
/* @__PURE__ */ jsxs38(AlertDialogFooter, { children: [
|
|
3848
|
+
/* @__PURE__ */ jsx43(AlertDialogCancel, { disabled: !!archivingProductId, children: "Cancel" }),
|
|
3849
|
+
/* @__PURE__ */ jsx43(
|
|
3621
3850
|
AlertDialogAction,
|
|
3622
3851
|
{
|
|
3623
3852
|
onClick: handleArchive,
|
|
@@ -3628,18 +3857,18 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3628
3857
|
)
|
|
3629
3858
|
] })
|
|
3630
3859
|
] }) }),
|
|
3631
|
-
/* @__PURE__ */
|
|
3632
|
-
/* @__PURE__ */
|
|
3633
|
-
/* @__PURE__ */
|
|
3634
|
-
/* @__PURE__ */
|
|
3860
|
+
/* @__PURE__ */ jsx43(AlertDialog, { open: !!productToReactivate, onOpenChange: (open) => !open && setProductToReactivate(null), children: /* @__PURE__ */ jsxs38(AlertDialogContent, { children: [
|
|
3861
|
+
/* @__PURE__ */ jsxs38(AlertDialogHeader, { children: [
|
|
3862
|
+
/* @__PURE__ */ jsx43(AlertDialogTitle, { children: "Reactivate Product" }),
|
|
3863
|
+
/* @__PURE__ */ jsxs38(AlertDialogDescription, { children: [
|
|
3635
3864
|
'Are you sure you want to reactivate "',
|
|
3636
3865
|
productToReactivate?.name,
|
|
3637
3866
|
'"? This will make it available for new subscriptions again.'
|
|
3638
3867
|
] })
|
|
3639
3868
|
] }),
|
|
3640
|
-
/* @__PURE__ */
|
|
3641
|
-
/* @__PURE__ */
|
|
3642
|
-
/* @__PURE__ */
|
|
3869
|
+
/* @__PURE__ */ jsxs38(AlertDialogFooter, { children: [
|
|
3870
|
+
/* @__PURE__ */ jsx43(AlertDialogCancel, { disabled: !!reactivatingProductId, children: "Cancel" }),
|
|
3871
|
+
/* @__PURE__ */ jsx43(
|
|
3643
3872
|
AlertDialogAction,
|
|
3644
3873
|
{
|
|
3645
3874
|
onClick: handleReactivate,
|
|
@@ -3655,14 +3884,14 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3655
3884
|
__name(ProductsList, "ProductsList");
|
|
3656
3885
|
|
|
3657
3886
|
// src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx
|
|
3658
|
-
import { jsx as
|
|
3887
|
+
import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3659
3888
|
function ProductsAdminContainer() {
|
|
3660
3889
|
const { hasRole } = useCurrentUserContext();
|
|
3661
|
-
const [products, setProducts] =
|
|
3662
|
-
const [loading, setLoading] =
|
|
3663
|
-
const [showCreateProduct, setShowCreateProduct] =
|
|
3890
|
+
const [products, setProducts] = useState19([]);
|
|
3891
|
+
const [loading, setLoading] = useState19(true);
|
|
3892
|
+
const [showCreateProduct, setShowCreateProduct] = useState19(false);
|
|
3664
3893
|
if (!hasRole(getRoleId().Administrator)) {
|
|
3665
|
-
return /* @__PURE__ */
|
|
3894
|
+
return /* @__PURE__ */ jsx44("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx44("p", { className: "text-red-600 font-semibold", children: "Permission denied. Administrator access required." }) });
|
|
3666
3895
|
}
|
|
3667
3896
|
const loadProducts = /* @__PURE__ */ __name(async () => {
|
|
3668
3897
|
setLoading(true);
|
|
@@ -3679,26 +3908,26 @@ function ProductsAdminContainer() {
|
|
|
3679
3908
|
loadProducts();
|
|
3680
3909
|
}, []);
|
|
3681
3910
|
if (loading) {
|
|
3682
|
-
return /* @__PURE__ */
|
|
3911
|
+
return /* @__PURE__ */ jsx44("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx44("p", { className: "text-muted-foreground", children: "Loading products..." }) });
|
|
3683
3912
|
}
|
|
3684
|
-
return /* @__PURE__ */
|
|
3685
|
-
/* @__PURE__ */
|
|
3686
|
-
/* @__PURE__ */
|
|
3687
|
-
/* @__PURE__ */
|
|
3688
|
-
/* @__PURE__ */
|
|
3913
|
+
return /* @__PURE__ */ jsxs39("div", { className: "flex w-full flex-col gap-y-6", children: [
|
|
3914
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex items-center justify-between", children: [
|
|
3915
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-x-3", children: [
|
|
3916
|
+
/* @__PURE__ */ jsx44(Package2, { className: "h-8 w-8" }),
|
|
3917
|
+
/* @__PURE__ */ jsx44("h1", { className: "text-3xl font-bold", children: "Product & Price Management" })
|
|
3689
3918
|
] }),
|
|
3690
|
-
/* @__PURE__ */
|
|
3919
|
+
/* @__PURE__ */ jsx44(Button, { onClick: () => setShowCreateProduct(true), children: "Create Product" })
|
|
3691
3920
|
] }),
|
|
3692
|
-
products.length === 0 && /* @__PURE__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
3696
|
-
/* @__PURE__ */
|
|
3697
|
-
/* @__PURE__ */
|
|
3921
|
+
products.length === 0 && /* @__PURE__ */ jsxs39("div", { className: "bg-muted/50 flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed p-12", children: [
|
|
3922
|
+
/* @__PURE__ */ jsx44(Package2, { className: "text-muted-foreground h-16 w-16" }),
|
|
3923
|
+
/* @__PURE__ */ jsxs39("div", { className: "text-center", children: [
|
|
3924
|
+
/* @__PURE__ */ jsx44("h3", { className: "mb-2 text-xl font-semibold", children: "No products yet" }),
|
|
3925
|
+
/* @__PURE__ */ jsx44("p", { className: "text-muted-foreground mb-4", children: "Create your first product to start offering subscriptions to your customers." }),
|
|
3926
|
+
/* @__PURE__ */ jsx44(Button, { onClick: () => setShowCreateProduct(true), children: "Create Your First Product" })
|
|
3698
3927
|
] })
|
|
3699
3928
|
] }),
|
|
3700
|
-
products.length > 0 && /* @__PURE__ */
|
|
3701
|
-
showCreateProduct && /* @__PURE__ */
|
|
3929
|
+
products.length > 0 && /* @__PURE__ */ jsx44(ProductsList, { products, onProductsChange: loadProducts }),
|
|
3930
|
+
showCreateProduct && /* @__PURE__ */ jsx44(ProductEditor, { open: showCreateProduct, onOpenChange: setShowCreateProduct, onSuccess: loadProducts })
|
|
3702
3931
|
] });
|
|
3703
3932
|
}
|
|
3704
3933
|
__name(ProductsAdminContainer, "ProductsAdminContainer");
|
|
@@ -3729,6 +3958,7 @@ export {
|
|
|
3729
3958
|
ProductPricingRow,
|
|
3730
3959
|
ProductsAdminContainer,
|
|
3731
3960
|
ProductsList,
|
|
3961
|
+
PromoCodeInput,
|
|
3732
3962
|
ProrationPreview,
|
|
3733
3963
|
StripeProvider,
|
|
3734
3964
|
SubscriptionConfirmation,
|