@carlonicora/nextjs-jsonapi 1.37.0 → 1.38.1
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-GTWR6CPI.mjs → BlockNoteEditor-5CEV5TZT.mjs} +3 -3
- package/dist/{BlockNoteEditor-74FHJO7E.js → BlockNoteEditor-VB72JQEO.js} +13 -13
- package/dist/{BlockNoteEditor-74FHJO7E.js.map → BlockNoteEditor-VB72JQEO.js.map} +1 -1
- package/dist/billing/index.d.mts +12 -2
- package/dist/billing/index.d.ts +12 -2
- package/dist/billing/index.js +680 -452
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +588 -360
- 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-YVEK3SUS.js → chunk-BYMBRMKS.js} +454 -446
- package/dist/chunk-BYMBRMKS.js.map +1 -0
- package/dist/{chunk-P7R2DPD6.mjs → chunk-TQ5GRRTM.mjs} +125 -1
- package/dist/chunk-TQ5GRRTM.mjs.map +1 -0
- package/dist/{chunk-ZUUH4CQC.mjs → chunk-VMK2N3TQ.mjs} +13 -5
- package/dist/{chunk-ZUUH4CQC.mjs.map → chunk-VMK2N3TQ.mjs.map} +1 -1
- package/dist/client/index.js +3 -3
- package/dist/client/index.mjs +2 -2
- package/dist/components/index.js +3 -3
- package/dist/components/index.mjs +2 -2
- 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/package.json +1 -1
- package/src/billing/index.ts +1 -0
- package/src/core/index.ts +1 -0
- package/src/core/registry/ModuleRegistry.ts +1 -0
- package/src/features/auth/components/forms/Login.tsx +14 -2
- package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +5 -16
- package/src/features/billing/stripe-invoice/data/stripe-invoice.interface.ts +1 -0
- 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/lists/SubscriptionsList.tsx +20 -3
- package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +6 -0
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +131 -9
- 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/index.ts +1 -0
- package/dist/chunk-53IPQJVH.js.map +0 -1
- package/dist/chunk-P7R2DPD6.mjs.map +0 -1
- package/dist/chunk-YVEK3SUS.js.map +0 -1
- /package/dist/{BlockNoteEditor-GTWR6CPI.mjs.map → BlockNoteEditor-5CEV5TZT.mjs.map} +0 -0
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-VMK2N3TQ.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 || "";
|
|
@@ -181,14 +173,7 @@ function SubscriptionSummaryCard({
|
|
|
181
173
|
}
|
|
182
174
|
)
|
|
183
175
|
] }),
|
|
184
|
-
/* @__PURE__ */
|
|
185
|
-
formatPrice(primarySubscription.price?.unitAmount, primarySubscription.price?.currency),
|
|
186
|
-
primarySubscription.price?.recurring && /* @__PURE__ */ jsxs("span", { children: [
|
|
187
|
-
"/",
|
|
188
|
-
primarySubscription.price.recurring.interval
|
|
189
|
-
] })
|
|
190
|
-
] }),
|
|
191
|
-
/* @__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)}` }),
|
|
192
177
|
activeSubscriptions.length > 1 && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
193
178
|
"+",
|
|
194
179
|
activeSubscriptions.length - 1,
|
|
@@ -548,9 +533,9 @@ function BillingUsageSummaryCard({
|
|
|
548
533
|
__name(BillingUsageSummaryCard, "BillingUsageSummaryCard");
|
|
549
534
|
|
|
550
535
|
// src/features/billing/components/containers/BillingDashboardContainer.tsx
|
|
551
|
-
import { CreditCard as CreditCard4, Loader2 as
|
|
536
|
+
import { CreditCard as CreditCard4, Loader2 as Loader23, Wallet as Wallet2 } from "lucide-react";
|
|
552
537
|
import { useSearchParams } from "next/navigation";
|
|
553
|
-
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";
|
|
554
539
|
|
|
555
540
|
// src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx
|
|
556
541
|
import { CreditCard as CreditCard2 } from "lucide-react";
|
|
@@ -1449,11 +1434,12 @@ function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan
|
|
|
1449
1434
|
/* @__PURE__ */ jsx18(TableHead, { children: "Status" }),
|
|
1450
1435
|
/* @__PURE__ */ jsx18(TableHead, { children: "Plan" }),
|
|
1451
1436
|
/* @__PURE__ */ jsx18(TableHead, { children: "Period" }),
|
|
1452
|
-
/* @__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" })
|
|
1453
1439
|
] }) }),
|
|
1454
1440
|
/* @__PURE__ */ jsx18(TableBody, { children: subscriptions.map((subscription) => {
|
|
1455
1441
|
const price = subscription.price;
|
|
1456
|
-
const amount = price?.unitAmount ? formatCurrency(price.unitAmount, price.currency) : "
|
|
1442
|
+
const amount = price?.unitAmount ? formatCurrency(price.unitAmount, price.currency) : "0";
|
|
1457
1443
|
const period = `${formatDate3(subscription.currentPeriodStart)} - ${formatDate3(subscription.currentPeriodEnd)}`;
|
|
1458
1444
|
return /* @__PURE__ */ jsxs15(
|
|
1459
1445
|
TableRow,
|
|
@@ -1470,7 +1456,19 @@ function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan
|
|
|
1470
1456
|
) }),
|
|
1471
1457
|
/* @__PURE__ */ jsx18(TableCell, { className: "font-medium", children: formatPlanName3(price) }),
|
|
1472
1458
|
/* @__PURE__ */ jsx18(TableCell, { className: "text-muted-foreground text-sm", children: period }),
|
|
1473
|
-
/* @__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
|
+
) })
|
|
1474
1472
|
]
|
|
1475
1473
|
},
|
|
1476
1474
|
subscription.id
|
|
@@ -1837,7 +1835,11 @@ var initialState = {
|
|
|
1837
1835
|
hasPaymentMethod: false,
|
|
1838
1836
|
isProcessing: false,
|
|
1839
1837
|
error: null,
|
|
1840
|
-
prorationPreview: null
|
|
1838
|
+
prorationPreview: null,
|
|
1839
|
+
promotionCode: null,
|
|
1840
|
+
isValidatingPromoCode: false,
|
|
1841
|
+
promoCodeError: null,
|
|
1842
|
+
isTrialSubscription: false
|
|
1841
1843
|
};
|
|
1842
1844
|
function wizardReducer(state, action) {
|
|
1843
1845
|
switch (action.type) {
|
|
@@ -1855,6 +1857,14 @@ function wizardReducer(state, action) {
|
|
|
1855
1857
|
return { ...state, error: action.error };
|
|
1856
1858
|
case "SET_PRORATION_PREVIEW":
|
|
1857
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 };
|
|
1858
1868
|
case "RESET":
|
|
1859
1869
|
return initialState;
|
|
1860
1870
|
default:
|
|
@@ -1894,6 +1904,19 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1894
1904
|
dispatch({ type: "SET_PROCESSING", isProcessing: true });
|
|
1895
1905
|
try {
|
|
1896
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
|
+
}
|
|
1897
1920
|
if (subscription && state.selectedPrice.id !== subscription.price?.id) {
|
|
1898
1921
|
const preview = await StripeSubscriptionService.getProrationPreview({
|
|
1899
1922
|
subscriptionId: subscription.id,
|
|
@@ -1908,22 +1931,31 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1908
1931
|
} finally {
|
|
1909
1932
|
dispatch({ type: "SET_PROCESSING", isProcessing: false });
|
|
1910
1933
|
}
|
|
1911
|
-
}, [state.selectedPrice, subscription, checkPaymentMethod]);
|
|
1934
|
+
}, [state.selectedPrice, state.hasPaymentMethod, subscription, checkPaymentMethod]);
|
|
1912
1935
|
const confirmSubscription = useCallback2(async () => {
|
|
1913
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);
|
|
1914
1940
|
dispatch({ type: "SET_PROCESSING", isProcessing: true });
|
|
1915
1941
|
dispatch({ type: "SET_ERROR", error: null });
|
|
1916
1942
|
try {
|
|
1917
1943
|
if (subscription) {
|
|
1918
|
-
|
|
1944
|
+
const changePlanParams = {
|
|
1919
1945
|
id: subscription.id,
|
|
1920
|
-
newPriceId: state.selectedPrice.id
|
|
1921
|
-
|
|
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);
|
|
1922
1951
|
} else {
|
|
1923
|
-
|
|
1952
|
+
const createParams = {
|
|
1924
1953
|
id: v4(),
|
|
1925
|
-
priceId: state.selectedPrice.id
|
|
1926
|
-
|
|
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);
|
|
1927
1959
|
}
|
|
1928
1960
|
onSuccessRef.current();
|
|
1929
1961
|
onCloseRef.current();
|
|
@@ -1945,7 +1977,7 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1945
1977
|
} finally {
|
|
1946
1978
|
dispatch({ type: "SET_PROCESSING", isProcessing: false });
|
|
1947
1979
|
}
|
|
1948
|
-
}, [state.selectedPrice, subscription]);
|
|
1980
|
+
}, [state.selectedPrice, state.promotionCode, subscription]);
|
|
1949
1981
|
const handlePaymentMethodSuccess = useCallback2(async () => {
|
|
1950
1982
|
dispatch({ type: "SET_HAS_PAYMENT_METHOD", hasMethod: true });
|
|
1951
1983
|
dispatch({ type: "SET_STEP", step: "review" });
|
|
@@ -1953,6 +1985,34 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1953
1985
|
const reset = useCallback2(() => {
|
|
1954
1986
|
dispatch({ type: "RESET" });
|
|
1955
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
|
+
}, []);
|
|
1956
2016
|
const actions = useMemo(
|
|
1957
2017
|
() => ({
|
|
1958
2018
|
selectPrice,
|
|
@@ -1962,7 +2022,9 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1962
2022
|
confirmSubscription,
|
|
1963
2023
|
handlePaymentMethodSuccess,
|
|
1964
2024
|
checkPaymentMethod,
|
|
1965
|
-
reset
|
|
2025
|
+
reset,
|
|
2026
|
+
validatePromoCode,
|
|
2027
|
+
clearPromoCode
|
|
1966
2028
|
}),
|
|
1967
2029
|
[
|
|
1968
2030
|
selectPrice,
|
|
@@ -1972,7 +2034,9 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1972
2034
|
confirmSubscription,
|
|
1973
2035
|
handlePaymentMethodSuccess,
|
|
1974
2036
|
checkPaymentMethod,
|
|
1975
|
-
reset
|
|
2037
|
+
reset,
|
|
2038
|
+
validatePromoCode,
|
|
2039
|
+
clearPromoCode
|
|
1976
2040
|
]
|
|
1977
2041
|
);
|
|
1978
2042
|
return {
|
|
@@ -2091,7 +2155,96 @@ __name(WizardStepPlanSelection, "WizardStepPlanSelection");
|
|
|
2091
2155
|
|
|
2092
2156
|
// src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx
|
|
2093
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";
|
|
2094
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";
|
|
2095
2248
|
function WizardStepReview({
|
|
2096
2249
|
selectedPrice,
|
|
2097
2250
|
subscription,
|
|
@@ -2101,10 +2254,16 @@ function WizardStepReview({
|
|
|
2101
2254
|
isProcessing,
|
|
2102
2255
|
onBack,
|
|
2103
2256
|
onAddPaymentMethod,
|
|
2104
|
-
onConfirm
|
|
2257
|
+
onConfirm,
|
|
2258
|
+
promotionCode,
|
|
2259
|
+
isValidatingPromoCode,
|
|
2260
|
+
promoCodeError,
|
|
2261
|
+
onApplyPromoCode,
|
|
2262
|
+
onRemovePromoCode,
|
|
2263
|
+
isTrialUpgrade
|
|
2105
2264
|
}) {
|
|
2106
2265
|
if (!selectedPrice) {
|
|
2107
|
-
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." });
|
|
2108
2267
|
}
|
|
2109
2268
|
const isChangingPlan = subscription && subscription.price?.id !== selectedPrice.id;
|
|
2110
2269
|
const formatInterval2 = /* @__PURE__ */ __name((price) => {
|
|
@@ -2112,62 +2271,124 @@ function WizardStepReview({
|
|
|
2112
2271
|
const interval = price.recurring?.interval || "month";
|
|
2113
2272
|
return interval === "year" ? "yearly" : "monthly";
|
|
2114
2273
|
}, "formatInterval");
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
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 })
|
|
2122
2316
|
] }),
|
|
2123
|
-
/* @__PURE__ */
|
|
2124
|
-
/* @__PURE__ */
|
|
2125
|
-
|
|
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) })
|
|
2126
2324
|
] })
|
|
2127
2325
|
] })
|
|
2128
2326
|
] }),
|
|
2129
|
-
isChangingPlan && prorationPreview && /* @__PURE__ */
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
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
|
+
)
|
|
2136
2357
|
] }),
|
|
2137
|
-
/* @__PURE__ */
|
|
2138
|
-
/* @__PURE__ */
|
|
2139
|
-
/* @__PURE__ */
|
|
2140
|
-
/* @__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" })
|
|
2141
2362
|
] }),
|
|
2142
|
-
!hasPaymentMethod && /* @__PURE__ */
|
|
2363
|
+
!hasPaymentMethod && /* @__PURE__ */ jsx29(Button, { variant: "outline", onClick: onAddPaymentMethod, children: "Add Payment Method" })
|
|
2143
2364
|
] }) }),
|
|
2144
|
-
error && /* @__PURE__ */
|
|
2145
|
-
/* @__PURE__ */
|
|
2146
|
-
/* @__PURE__ */
|
|
2365
|
+
error && /* @__PURE__ */ jsxs26(Alert, { variant: "destructive", children: [
|
|
2366
|
+
/* @__PURE__ */ jsx29(AlertCircle, { className: "h-4 w-4" }),
|
|
2367
|
+
/* @__PURE__ */ jsx29(AlertDescription, { children: error })
|
|
2147
2368
|
] }),
|
|
2148
|
-
/* @__PURE__ */
|
|
2149
|
-
/* @__PURE__ */
|
|
2150
|
-
/* @__PURE__ */
|
|
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" })
|
|
2151
2372
|
] })
|
|
2152
2373
|
] });
|
|
2153
2374
|
}
|
|
2154
2375
|
__name(WizardStepReview, "WizardStepReview");
|
|
2155
2376
|
|
|
2156
2377
|
// src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx
|
|
2157
|
-
import { jsx as
|
|
2378
|
+
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2158
2379
|
function WizardStepPaymentMethod({ onBack, onSuccess, isProcessing }) {
|
|
2159
|
-
return /* @__PURE__ */
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
/* @__PURE__ */
|
|
2162
|
-
/* @__PURE__ */
|
|
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" })
|
|
2163
2384
|
] }),
|
|
2164
|
-
/* @__PURE__ */
|
|
2385
|
+
/* @__PURE__ */ jsx30(PaymentMethodForm, { onSuccess, onCancel: onBack, isLoading: isProcessing })
|
|
2165
2386
|
] });
|
|
2166
2387
|
}
|
|
2167
2388
|
__name(WizardStepPaymentMethod, "WizardStepPaymentMethod");
|
|
2168
2389
|
|
|
2169
2390
|
// src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx
|
|
2170
|
-
import { jsx as
|
|
2391
|
+
import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2171
2392
|
function SubscriptionWizard({
|
|
2172
2393
|
open,
|
|
2173
2394
|
onOpenChange,
|
|
@@ -2200,13 +2421,13 @@ function SubscriptionWizard({
|
|
|
2200
2421
|
const isChangePlanMode = !!subscription;
|
|
2201
2422
|
const dialogTitle = subscription ? "Change Subscription Plan" : isPurchasingAddons ? "Purchase Add-ons" : "Subscribe to a Plan";
|
|
2202
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";
|
|
2203
|
-
return /* @__PURE__ */
|
|
2204
|
-
/* @__PURE__ */
|
|
2205
|
-
/* @__PURE__ */
|
|
2206
|
-
/* @__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 })
|
|
2207
2428
|
] }),
|
|
2208
|
-
/* @__PURE__ */
|
|
2209
|
-
state.step === "plan-selection" && /* @__PURE__ */
|
|
2429
|
+
/* @__PURE__ */ jsx31(WizardProgressIndicator, { currentStep: state.step }),
|
|
2430
|
+
state.step === "plan-selection" && /* @__PURE__ */ jsx31(
|
|
2210
2431
|
WizardStepPlanSelection,
|
|
2211
2432
|
{
|
|
2212
2433
|
selectedPrice: state.selectedPrice,
|
|
@@ -2220,7 +2441,7 @@ function SubscriptionWizard({
|
|
|
2220
2441
|
isProcessing: state.isProcessing
|
|
2221
2442
|
}
|
|
2222
2443
|
),
|
|
2223
|
-
state.step === "review" && /* @__PURE__ */
|
|
2444
|
+
state.step === "review" && /* @__PURE__ */ jsx31(
|
|
2224
2445
|
WizardStepReview,
|
|
2225
2446
|
{
|
|
2226
2447
|
selectedPrice: state.selectedPrice,
|
|
@@ -2231,10 +2452,16 @@ function SubscriptionWizard({
|
|
|
2231
2452
|
isProcessing: state.isProcessing,
|
|
2232
2453
|
onBack: () => actions.goToStep("plan-selection"),
|
|
2233
2454
|
onAddPaymentMethod: () => actions.goToStep("payment-method"),
|
|
2234
|
-
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
|
|
2235
2462
|
}
|
|
2236
2463
|
),
|
|
2237
|
-
state.step === "payment-method" && /* @__PURE__ */
|
|
2464
|
+
state.step === "payment-method" && /* @__PURE__ */ jsx31(
|
|
2238
2465
|
WizardStepPaymentMethod,
|
|
2239
2466
|
{
|
|
2240
2467
|
onBack: () => actions.goToStep("review"),
|
|
@@ -2248,11 +2475,11 @@ __name(SubscriptionWizard, "SubscriptionWizard");
|
|
|
2248
2475
|
|
|
2249
2476
|
// src/features/billing/stripe-usage/components/containers/UsageContainer.tsx
|
|
2250
2477
|
import { Activity as Activity3 } from "lucide-react";
|
|
2251
|
-
import { useEffect as useEffect8, useState as
|
|
2478
|
+
import { useEffect as useEffect8, useState as useState13 } from "react";
|
|
2252
2479
|
|
|
2253
2480
|
// src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx
|
|
2254
2481
|
import { Activity as Activity2 } from "lucide-react";
|
|
2255
|
-
import { jsx as
|
|
2482
|
+
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2256
2483
|
function getProgressColor(percentage) {
|
|
2257
2484
|
if (percentage === null) return "bg-blue-500";
|
|
2258
2485
|
if (percentage >= 90) return "bg-red-500";
|
|
@@ -2280,31 +2507,31 @@ function UsageSummaryCard({ meter, summary }) {
|
|
|
2280
2507
|
const progressWidth = percentage !== null ? Math.min(percentage, 100) : 0;
|
|
2281
2508
|
const displayName = meter.displayName || meter.eventName;
|
|
2282
2509
|
const hasLimit = limit !== null && limit !== void 0;
|
|
2283
|
-
return /* @__PURE__ */
|
|
2284
|
-
/* @__PURE__ */
|
|
2285
|
-
/* @__PURE__ */
|
|
2286
|
-
/* @__PURE__ */
|
|
2287
|
-
/* @__PURE__ */
|
|
2288
|
-
/* @__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 })
|
|
2289
2516
|
] })
|
|
2290
2517
|
] }),
|
|
2291
|
-
/* @__PURE__ */
|
|
2292
|
-
/* @__PURE__ */
|
|
2293
|
-
/* @__PURE__ */
|
|
2294
|
-
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: [
|
|
2295
2522
|
"of ",
|
|
2296
2523
|
limit.toLocaleString(),
|
|
2297
2524
|
" used"
|
|
2298
2525
|
] })
|
|
2299
2526
|
] }),
|
|
2300
|
-
hasLimit ? /* @__PURE__ */
|
|
2301
|
-
/* @__PURE__ */
|
|
2302
|
-
/* @__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: [
|
|
2303
2530
|
percentage?.toFixed(1),
|
|
2304
2531
|
"% used"
|
|
2305
2532
|
] })
|
|
2306
|
-
] }) : /* @__PURE__ */
|
|
2307
|
-
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: [
|
|
2308
2535
|
"Period: ",
|
|
2309
2536
|
formatDate4(summary.start),
|
|
2310
2537
|
" - ",
|
|
@@ -2316,19 +2543,19 @@ function UsageSummaryCard({ meter, summary }) {
|
|
|
2316
2543
|
__name(UsageSummaryCard, "UsageSummaryCard");
|
|
2317
2544
|
|
|
2318
2545
|
// src/features/billing/stripe-usage/components/widgets/UsageSummaryCards.tsx
|
|
2319
|
-
import { jsx as
|
|
2546
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
2320
2547
|
function UsageSummaryCards({ meters, summaries }) {
|
|
2321
|
-
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)) });
|
|
2322
2549
|
}
|
|
2323
2550
|
__name(UsageSummaryCards, "UsageSummaryCards");
|
|
2324
2551
|
|
|
2325
2552
|
// src/features/billing/stripe-usage/components/containers/UsageContainer.tsx
|
|
2326
|
-
import { jsx as
|
|
2553
|
+
import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2327
2554
|
function UsageContainer() {
|
|
2328
|
-
const [meters, setMeters] =
|
|
2329
|
-
const [summaries, setSummaries] =
|
|
2330
|
-
const [loading, setLoading] =
|
|
2331
|
-
const [subscriptions, setSubscriptions] =
|
|
2555
|
+
const [meters, setMeters] = useState13([]);
|
|
2556
|
+
const [summaries, setSummaries] = useState13({});
|
|
2557
|
+
const [loading, setLoading] = useState13(true);
|
|
2558
|
+
const [subscriptions, setSubscriptions] = useState13([]);
|
|
2332
2559
|
useEffect8(() => {
|
|
2333
2560
|
loadUsageData();
|
|
2334
2561
|
}, []);
|
|
@@ -2373,27 +2600,27 @@ function UsageContainer() {
|
|
|
2373
2600
|
return null;
|
|
2374
2601
|
}
|
|
2375
2602
|
if (loading) {
|
|
2376
|
-
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..." }) });
|
|
2377
2604
|
}
|
|
2378
|
-
return /* @__PURE__ */
|
|
2379
|
-
/* @__PURE__ */
|
|
2380
|
-
/* @__PURE__ */
|
|
2381
|
-
/* @__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" })
|
|
2382
2609
|
] }),
|
|
2383
|
-
meters.length === 0 && /* @__PURE__ */
|
|
2384
|
-
/* @__PURE__ */
|
|
2385
|
-
/* @__PURE__ */
|
|
2386
|
-
/* @__PURE__ */
|
|
2387
|
-
/* @__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." })
|
|
2388
2615
|
] })
|
|
2389
2616
|
] }),
|
|
2390
|
-
meters.length > 0 && /* @__PURE__ */
|
|
2617
|
+
meters.length > 0 && /* @__PURE__ */ jsx34(UsageSummaryCards, { meters, summaries })
|
|
2391
2618
|
] });
|
|
2392
2619
|
}
|
|
2393
2620
|
__name(UsageContainer, "UsageContainer");
|
|
2394
2621
|
|
|
2395
2622
|
// src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx
|
|
2396
|
-
import { jsx as
|
|
2623
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2397
2624
|
function formatDateTime(date) {
|
|
2398
2625
|
if (!date) return "N/A";
|
|
2399
2626
|
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
@@ -2412,25 +2639,25 @@ function formatDateTime(date) {
|
|
|
2412
2639
|
__name(formatDateTime, "formatDateTime");
|
|
2413
2640
|
function UsageHistoryTable({ usageRecords }) {
|
|
2414
2641
|
if (usageRecords.length === 0) {
|
|
2415
|
-
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." }) });
|
|
2416
2643
|
}
|
|
2417
|
-
return /* @__PURE__ */
|
|
2418
|
-
/* @__PURE__ */
|
|
2419
|
-
/* @__PURE__ */
|
|
2420
|
-
/* @__PURE__ */
|
|
2421
|
-
/* @__PURE__ */
|
|
2422
|
-
/* @__PURE__ */
|
|
2423
|
-
/* @__PURE__ */
|
|
2424
|
-
/* @__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" })
|
|
2425
2652
|
] }) }),
|
|
2426
|
-
/* @__PURE__ */
|
|
2653
|
+
/* @__PURE__ */ jsx35(TableBody, { children: usageRecords.map((record) => {
|
|
2427
2654
|
const dateTime = formatDateTime(record.timestamp);
|
|
2428
2655
|
const quantity = record.quantity.toLocaleString();
|
|
2429
|
-
return /* @__PURE__ */
|
|
2430
|
-
/* @__PURE__ */
|
|
2431
|
-
/* @__PURE__ */
|
|
2432
|
-
/* @__PURE__ */
|
|
2433
|
-
/* @__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 })
|
|
2434
2661
|
] }, record.id);
|
|
2435
2662
|
}) })
|
|
2436
2663
|
] }) })
|
|
@@ -2439,10 +2666,10 @@ function UsageHistoryTable({ usageRecords }) {
|
|
|
2439
2666
|
__name(UsageHistoryTable, "UsageHistoryTable");
|
|
2440
2667
|
|
|
2441
2668
|
// src/features/billing/components/modals/BillingDetailModal.tsx
|
|
2442
|
-
import { jsx as
|
|
2669
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2443
2670
|
function BillingDetailModal({ open, onOpenChange, title, children, className }) {
|
|
2444
|
-
return /* @__PURE__ */
|
|
2445
|
-
/* @__PURE__ */
|
|
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 }) }),
|
|
2446
2673
|
children
|
|
2447
2674
|
] }) });
|
|
2448
2675
|
}
|
|
@@ -2450,16 +2677,16 @@ __name(BillingDetailModal, "BillingDetailModal");
|
|
|
2450
2677
|
|
|
2451
2678
|
// src/features/billing/components/widgets/BillingAlertBanner.tsx
|
|
2452
2679
|
import { AlertCircle as AlertCircle2 } from "lucide-react";
|
|
2453
|
-
import { jsx as
|
|
2680
|
+
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2454
2681
|
function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
2455
2682
|
if (subscription.status === "past_due" /* PAST_DUE */) {
|
|
2456
|
-
return /* @__PURE__ */
|
|
2457
|
-
/* @__PURE__ */
|
|
2458
|
-
/* @__PURE__ */
|
|
2459
|
-
/* @__PURE__ */
|
|
2460
|
-
/* @__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." })
|
|
2461
2688
|
] }),
|
|
2462
|
-
onUpdatePayment && /* @__PURE__ */
|
|
2689
|
+
onUpdatePayment && /* @__PURE__ */ jsx37(Button, { variant: "outline", size: "sm", onClick: onUpdatePayment, className: "border-red-300 text-red-700", children: "Update Payment Method" })
|
|
2463
2690
|
] });
|
|
2464
2691
|
}
|
|
2465
2692
|
if (subscription.status === "trialing" /* TRIALING */ && subscription.trialEnd) {
|
|
@@ -2467,11 +2694,11 @@ function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
|
2467
2694
|
const now = /* @__PURE__ */ new Date();
|
|
2468
2695
|
const daysRemaining = Math.ceil((trialEnd.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
|
|
2469
2696
|
if (daysRemaining <= 7) {
|
|
2470
|
-
return /* @__PURE__ */
|
|
2471
|
-
/* @__PURE__ */
|
|
2472
|
-
/* @__PURE__ */
|
|
2473
|
-
/* @__PURE__ */
|
|
2474
|
-
/* @__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: [
|
|
2475
2702
|
"Your trial ends in ",
|
|
2476
2703
|
daysRemaining,
|
|
2477
2704
|
" ",
|
|
@@ -2479,7 +2706,7 @@ function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
|
2479
2706
|
". Add a payment method to continue your subscription."
|
|
2480
2707
|
] })
|
|
2481
2708
|
] }),
|
|
2482
|
-
onAddPayment && /* @__PURE__ */
|
|
2709
|
+
onAddPayment && /* @__PURE__ */ jsx37(Button, { variant: "outline", size: "sm", onClick: onAddPayment, className: "border-yellow-300 text-yellow-700", children: "Add Payment Method" })
|
|
2483
2710
|
] });
|
|
2484
2711
|
}
|
|
2485
2712
|
}
|
|
@@ -2488,9 +2715,9 @@ function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
|
2488
2715
|
__name(BillingAlertBanner, "BillingAlertBanner");
|
|
2489
2716
|
|
|
2490
2717
|
// src/features/billing/components/containers/BillingDashboardContainer.tsx
|
|
2491
|
-
import { Fragment as
|
|
2718
|
+
import { Fragment as Fragment7, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2492
2719
|
function BillingDashboardContainer() {
|
|
2493
|
-
const [data, setData] =
|
|
2720
|
+
const [data, setData] = useState14({
|
|
2494
2721
|
customer: null,
|
|
2495
2722
|
subscriptions: [],
|
|
2496
2723
|
paymentMethods: [],
|
|
@@ -2498,26 +2725,26 @@ function BillingDashboardContainer() {
|
|
|
2498
2725
|
meters: [],
|
|
2499
2726
|
meterSummaries: {}
|
|
2500
2727
|
});
|
|
2501
|
-
const [loading, setLoading] =
|
|
2728
|
+
const [loading, setLoading] = useState14({
|
|
2502
2729
|
customer: true,
|
|
2503
2730
|
subscriptions: true,
|
|
2504
2731
|
paymentMethods: true,
|
|
2505
2732
|
invoices: true,
|
|
2506
2733
|
usage: true
|
|
2507
2734
|
});
|
|
2508
|
-
const [errors, setErrors] =
|
|
2735
|
+
const [errors, setErrors] = useState14({
|
|
2509
2736
|
customer: null,
|
|
2510
2737
|
subscriptions: null,
|
|
2511
2738
|
paymentMethods: null,
|
|
2512
2739
|
invoices: null,
|
|
2513
2740
|
usage: null
|
|
2514
2741
|
});
|
|
2515
|
-
const [activeModal, setActiveModal] =
|
|
2516
|
-
const [noCustomerExists, setNoCustomerExists] =
|
|
2517
|
-
const [creatingCustomer, setCreatingCustomer] =
|
|
2742
|
+
const [activeModal, setActiveModal] = useState14(null);
|
|
2743
|
+
const [noCustomerExists, setNoCustomerExists] = useState14(false);
|
|
2744
|
+
const [creatingCustomer, setCreatingCustomer] = useState14(false);
|
|
2518
2745
|
const searchParams = useSearchParams();
|
|
2519
|
-
const [showWizard, setShowWizard] =
|
|
2520
|
-
const [editingSubscription, setEditingSubscription] =
|
|
2746
|
+
const [showWizard, setShowWizard] = useState14(false);
|
|
2747
|
+
const [editingSubscription, setEditingSubscription] = useState14(null);
|
|
2521
2748
|
const hasMeteredSubscriptions = useCallback4(() => {
|
|
2522
2749
|
return data.subscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
|
|
2523
2750
|
}, [data.subscriptions]);
|
|
@@ -2698,26 +2925,26 @@ function BillingDashboardContainer() {
|
|
|
2698
2925
|
}
|
|
2699
2926
|
}, "getModalTitle");
|
|
2700
2927
|
const isInitialLoading = loading.customer && !noCustomerExists && !data.customer;
|
|
2701
|
-
return /* @__PURE__ */
|
|
2702
|
-
/* @__PURE__ */
|
|
2703
|
-
/* @__PURE__ */
|
|
2704
|
-
/* @__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" })
|
|
2705
2932
|
] }),
|
|
2706
|
-
isInitialLoading && /* @__PURE__ */
|
|
2707
|
-
noCustomerExists && !isInitialLoading && /* @__PURE__ */
|
|
2708
|
-
/* @__PURE__ */
|
|
2709
|
-
/* @__PURE__ */
|
|
2710
|
-
/* @__PURE__ */
|
|
2711
|
-
/* @__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." })
|
|
2712
2939
|
] }),
|
|
2713
|
-
/* @__PURE__ */
|
|
2714
|
-
/* @__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" }),
|
|
2715
2942
|
"Setting up..."
|
|
2716
2943
|
] }) : "Set Up Billing Account" }) }),
|
|
2717
|
-
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 }) })
|
|
2718
2945
|
] }),
|
|
2719
|
-
!noCustomerExists && !isInitialLoading && /* @__PURE__ */
|
|
2720
|
-
criticalSubscriptions.map((subscription) => /* @__PURE__ */
|
|
2946
|
+
!noCustomerExists && !isInitialLoading && /* @__PURE__ */ jsxs34(Fragment7, { children: [
|
|
2947
|
+
criticalSubscriptions.map((subscription) => /* @__PURE__ */ jsx38(
|
|
2721
2948
|
BillingAlertBanner,
|
|
2722
2949
|
{
|
|
2723
2950
|
subscription,
|
|
@@ -2726,8 +2953,8 @@ function BillingDashboardContainer() {
|
|
|
2726
2953
|
},
|
|
2727
2954
|
subscription.id
|
|
2728
2955
|
)),
|
|
2729
|
-
/* @__PURE__ */
|
|
2730
|
-
/* @__PURE__ */
|
|
2956
|
+
/* @__PURE__ */ jsxs34("div", { className: "grid gap-4 md:grid-cols-2", children: [
|
|
2957
|
+
/* @__PURE__ */ jsx38(
|
|
2731
2958
|
SubscriptionSummaryCard,
|
|
2732
2959
|
{
|
|
2733
2960
|
subscriptions: data.subscriptions,
|
|
@@ -2742,7 +2969,7 @@ function BillingDashboardContainer() {
|
|
|
2742
2969
|
}
|
|
2743
2970
|
}
|
|
2744
2971
|
),
|
|
2745
|
-
/* @__PURE__ */
|
|
2972
|
+
/* @__PURE__ */ jsx38(
|
|
2746
2973
|
PaymentMethodSummaryCard,
|
|
2747
2974
|
{
|
|
2748
2975
|
paymentMethods: data.paymentMethods,
|
|
@@ -2752,7 +2979,7 @@ function BillingDashboardContainer() {
|
|
|
2752
2979
|
onManageClick: () => setActiveModal("payment-methods")
|
|
2753
2980
|
}
|
|
2754
2981
|
),
|
|
2755
|
-
/* @__PURE__ */
|
|
2982
|
+
/* @__PURE__ */ jsx38(
|
|
2756
2983
|
CustomerInfoCard,
|
|
2757
2984
|
{
|
|
2758
2985
|
customer: data.customer,
|
|
@@ -2760,7 +2987,7 @@ function BillingDashboardContainer() {
|
|
|
2760
2987
|
error: errors.customer || void 0
|
|
2761
2988
|
}
|
|
2762
2989
|
),
|
|
2763
|
-
/* @__PURE__ */
|
|
2990
|
+
/* @__PURE__ */ jsx38(
|
|
2764
2991
|
InvoicesSummaryCard,
|
|
2765
2992
|
{
|
|
2766
2993
|
invoices: data.invoices,
|
|
@@ -2769,7 +2996,7 @@ function BillingDashboardContainer() {
|
|
|
2769
2996
|
onViewAllClick: () => setActiveModal("invoices")
|
|
2770
2997
|
}
|
|
2771
2998
|
),
|
|
2772
|
-
hasMeteredSubscriptions() && /* @__PURE__ */
|
|
2999
|
+
hasMeteredSubscriptions() && /* @__PURE__ */ jsx38(
|
|
2773
3000
|
BillingUsageSummaryCard,
|
|
2774
3001
|
{
|
|
2775
3002
|
meters: data.meters,
|
|
@@ -2780,13 +3007,13 @@ function BillingDashboardContainer() {
|
|
|
2780
3007
|
}
|
|
2781
3008
|
)
|
|
2782
3009
|
] }),
|
|
2783
|
-
/* @__PURE__ */
|
|
3010
|
+
/* @__PURE__ */ jsx38(
|
|
2784
3011
|
BillingDetailModal,
|
|
2785
3012
|
{
|
|
2786
3013
|
open: activeModal === "subscriptions",
|
|
2787
3014
|
onOpenChange: handleModalClose,
|
|
2788
3015
|
title: getModalTitle("subscriptions"),
|
|
2789
|
-
children: /* @__PURE__ */
|
|
3016
|
+
children: /* @__PURE__ */ jsx38(
|
|
2790
3017
|
SubscriptionsContainer,
|
|
2791
3018
|
{
|
|
2792
3019
|
onOpenWizard: handleOpenWizard,
|
|
@@ -2795,34 +3022,34 @@ function BillingDashboardContainer() {
|
|
|
2795
3022
|
)
|
|
2796
3023
|
}
|
|
2797
3024
|
),
|
|
2798
|
-
/* @__PURE__ */
|
|
3025
|
+
/* @__PURE__ */ jsx38(
|
|
2799
3026
|
BillingDetailModal,
|
|
2800
3027
|
{
|
|
2801
3028
|
open: activeModal === "payment-methods",
|
|
2802
3029
|
onOpenChange: handleModalClose,
|
|
2803
3030
|
title: getModalTitle("payment-methods"),
|
|
2804
|
-
children: /* @__PURE__ */
|
|
3031
|
+
children: /* @__PURE__ */ jsx38(PaymentMethodsContainer, {})
|
|
2805
3032
|
}
|
|
2806
3033
|
),
|
|
2807
|
-
/* @__PURE__ */
|
|
3034
|
+
/* @__PURE__ */ jsx38(
|
|
2808
3035
|
BillingDetailModal,
|
|
2809
3036
|
{
|
|
2810
3037
|
open: activeModal === "invoices",
|
|
2811
3038
|
onOpenChange: handleModalClose,
|
|
2812
3039
|
title: getModalTitle("invoices"),
|
|
2813
|
-
children: /* @__PURE__ */
|
|
3040
|
+
children: /* @__PURE__ */ jsx38(InvoicesContainer, {})
|
|
2814
3041
|
}
|
|
2815
3042
|
),
|
|
2816
|
-
/* @__PURE__ */
|
|
3043
|
+
/* @__PURE__ */ jsx38(
|
|
2817
3044
|
BillingDetailModal,
|
|
2818
3045
|
{
|
|
2819
3046
|
open: activeModal === "usage",
|
|
2820
3047
|
onOpenChange: handleModalClose,
|
|
2821
3048
|
title: getModalTitle("usage"),
|
|
2822
|
-
children: /* @__PURE__ */
|
|
3049
|
+
children: /* @__PURE__ */ jsx38(UsageContainer, {})
|
|
2823
3050
|
}
|
|
2824
3051
|
),
|
|
2825
|
-
/* @__PURE__ */
|
|
3052
|
+
/* @__PURE__ */ jsx38(
|
|
2826
3053
|
SubscriptionWizard,
|
|
2827
3054
|
{
|
|
2828
3055
|
open: showWizard,
|
|
@@ -2841,7 +3068,7 @@ __name(BillingDashboardContainer, "BillingDashboardContainer");
|
|
|
2841
3068
|
import { Elements } from "@stripe/react-stripe-js";
|
|
2842
3069
|
import { loadStripe } from "@stripe/stripe-js";
|
|
2843
3070
|
import { useMemo as useMemo4 } from "react";
|
|
2844
|
-
import { Fragment as
|
|
3071
|
+
import { Fragment as Fragment8, jsx as jsx39 } from "react/jsx-runtime";
|
|
2845
3072
|
var stripePromiseCache = null;
|
|
2846
3073
|
function getStripePromise(publishableKey) {
|
|
2847
3074
|
if (!publishableKey) {
|
|
@@ -2860,9 +3087,9 @@ function StripeProvider({ children }) {
|
|
|
2860
3087
|
const stripePromise = useMemo4(() => getStripePromise(publishableKey), [publishableKey]);
|
|
2861
3088
|
const options = useMemo4(() => ({}), []);
|
|
2862
3089
|
if (!publishableKey) {
|
|
2863
|
-
return /* @__PURE__ */
|
|
3090
|
+
return /* @__PURE__ */ jsx39(Fragment8, { children });
|
|
2864
3091
|
}
|
|
2865
|
-
return /* @__PURE__ */
|
|
3092
|
+
return /* @__PURE__ */ jsx39(Elements, { stripe: stripePromise, options, children });
|
|
2866
3093
|
}
|
|
2867
3094
|
__name(StripeProvider, "StripeProvider");
|
|
2868
3095
|
function isStripeConfigured() {
|
|
@@ -2873,14 +3100,14 @@ __name(isStripeConfigured, "isStripeConfigured");
|
|
|
2873
3100
|
// src/features/billing/stripe-price/components/forms/PriceEditor.tsx
|
|
2874
3101
|
import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
|
|
2875
3102
|
import { AlertCircle as AlertCircle3, PlusIcon, XIcon } from "lucide-react";
|
|
2876
|
-
import { useEffect as useEffect10, useState as
|
|
3103
|
+
import { useEffect as useEffect10, useState as useState15 } from "react";
|
|
2877
3104
|
import { useForm as useForm2 } from "react-hook-form";
|
|
2878
3105
|
import { v4 as v42 } from "uuid";
|
|
2879
3106
|
import { z as z2 } from "zod";
|
|
2880
|
-
import { jsx as
|
|
3107
|
+
import { jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2881
3108
|
function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
2882
|
-
const [isSubmitting, setIsSubmitting] =
|
|
2883
|
-
const [allFeatures, setAllFeatures] =
|
|
3109
|
+
const [isSubmitting, setIsSubmitting] = useState15(false);
|
|
3110
|
+
const [allFeatures, setAllFeatures] = useState15([]);
|
|
2884
3111
|
useEffect10(() => {
|
|
2885
3112
|
const fetchFeatures = /* @__PURE__ */ __name(async () => {
|
|
2886
3113
|
try {
|
|
@@ -3030,21 +3257,21 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3030
3257
|
{ id: "licensed", text: "Licensed (per unit)" },
|
|
3031
3258
|
{ id: "metered", text: "Metered (usage-based)" }
|
|
3032
3259
|
];
|
|
3033
|
-
return /* @__PURE__ */
|
|
3034
|
-
/* @__PURE__ */
|
|
3035
|
-
/* @__PURE__ */
|
|
3036
|
-
/* @__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" })
|
|
3037
3264
|
] }),
|
|
3038
|
-
isEditMode && /* @__PURE__ */
|
|
3039
|
-
/* @__PURE__ */
|
|
3040
|
-
/* @__PURE__ */
|
|
3041
|
-
/* @__PURE__ */
|
|
3042
|
-
/* @__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." })
|
|
3043
3270
|
] })
|
|
3044
3271
|
] }),
|
|
3045
|
-
/* @__PURE__ */
|
|
3046
|
-
/* @__PURE__ */
|
|
3047
|
-
/* @__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(
|
|
3048
3275
|
FormInput,
|
|
3049
3276
|
{
|
|
3050
3277
|
form,
|
|
@@ -3055,9 +3282,9 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3055
3282
|
isRequired: true
|
|
3056
3283
|
}
|
|
3057
3284
|
),
|
|
3058
|
-
/* @__PURE__ */
|
|
3285
|
+
/* @__PURE__ */ jsx40(FormSelect, { form, id: "currency", name: "Currency", values: currencyOptions, disabled: isEditMode })
|
|
3059
3286
|
] }),
|
|
3060
|
-
/* @__PURE__ */
|
|
3287
|
+
/* @__PURE__ */ jsx40(
|
|
3061
3288
|
FormSelect,
|
|
3062
3289
|
{
|
|
3063
3290
|
form,
|
|
@@ -3067,8 +3294,8 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3067
3294
|
disabled: isEditMode
|
|
3068
3295
|
}
|
|
3069
3296
|
),
|
|
3070
|
-
isRecurring && /* @__PURE__ */
|
|
3071
|
-
/* @__PURE__ */
|
|
3297
|
+
isRecurring && /* @__PURE__ */ jsxs35("div", { className: "grid grid-cols-2 gap-x-4", children: [
|
|
3298
|
+
/* @__PURE__ */ jsx40(
|
|
3072
3299
|
FormInput,
|
|
3073
3300
|
{
|
|
3074
3301
|
form,
|
|
@@ -3079,7 +3306,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3079
3306
|
disabled: isEditMode
|
|
3080
3307
|
}
|
|
3081
3308
|
),
|
|
3082
|
-
/* @__PURE__ */
|
|
3309
|
+
/* @__PURE__ */ jsx40(
|
|
3083
3310
|
FormSelect,
|
|
3084
3311
|
{
|
|
3085
3312
|
form,
|
|
@@ -3090,7 +3317,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3090
3317
|
}
|
|
3091
3318
|
)
|
|
3092
3319
|
] }),
|
|
3093
|
-
/* @__PURE__ */
|
|
3320
|
+
/* @__PURE__ */ jsx40(
|
|
3094
3321
|
FormInput,
|
|
3095
3322
|
{
|
|
3096
3323
|
form,
|
|
@@ -3099,7 +3326,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3099
3326
|
placeholder: "e.g., Standard Plan, Pro Tier"
|
|
3100
3327
|
}
|
|
3101
3328
|
),
|
|
3102
|
-
/* @__PURE__ */
|
|
3329
|
+
/* @__PURE__ */ jsx40(
|
|
3103
3330
|
FormTextarea,
|
|
3104
3331
|
{
|
|
3105
3332
|
form,
|
|
@@ -3109,12 +3336,12 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3109
3336
|
className: "min-h-24"
|
|
3110
3337
|
}
|
|
3111
3338
|
),
|
|
3112
|
-
/* @__PURE__ */
|
|
3113
|
-
/* @__PURE__ */
|
|
3114
|
-
/* @__PURE__ */
|
|
3115
|
-
/* @__PURE__ */
|
|
3116
|
-
form.watch("features").map((_, index) => /* @__PURE__ */
|
|
3117
|
-
/* @__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(
|
|
3118
3345
|
Input,
|
|
3119
3346
|
{
|
|
3120
3347
|
...form.register(`features.${index}`),
|
|
@@ -3122,7 +3349,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3122
3349
|
className: "flex-1"
|
|
3123
3350
|
}
|
|
3124
3351
|
),
|
|
3125
|
-
/* @__PURE__ */
|
|
3352
|
+
/* @__PURE__ */ jsx40(
|
|
3126
3353
|
Button,
|
|
3127
3354
|
{
|
|
3128
3355
|
type: "button",
|
|
@@ -3135,11 +3362,11 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3135
3362
|
currentFeatures.filter((_2, i) => i !== index)
|
|
3136
3363
|
);
|
|
3137
3364
|
},
|
|
3138
|
-
children: /* @__PURE__ */
|
|
3365
|
+
children: /* @__PURE__ */ jsx40(XIcon, { className: "h-4 w-4" })
|
|
3139
3366
|
}
|
|
3140
3367
|
)
|
|
3141
3368
|
] }, index)),
|
|
3142
|
-
/* @__PURE__ */
|
|
3369
|
+
/* @__PURE__ */ jsxs35(
|
|
3143
3370
|
Button,
|
|
3144
3371
|
{
|
|
3145
3372
|
type: "button",
|
|
@@ -3151,20 +3378,20 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3151
3378
|
},
|
|
3152
3379
|
className: "mt-2",
|
|
3153
3380
|
children: [
|
|
3154
|
-
/* @__PURE__ */
|
|
3381
|
+
/* @__PURE__ */ jsx40(PlusIcon, { className: "h-4 w-4 mr-2" }),
|
|
3155
3382
|
"Add Feature"
|
|
3156
3383
|
]
|
|
3157
3384
|
}
|
|
3158
3385
|
)
|
|
3159
3386
|
] })
|
|
3160
3387
|
] }),
|
|
3161
|
-
isRecurring && allFeatures.length > 0 && /* @__PURE__ */
|
|
3162
|
-
/* @__PURE__ */
|
|
3163
|
-
/* @__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) => {
|
|
3164
3391
|
const isCore = feature.isCore;
|
|
3165
3392
|
const isChecked = form.watch("featureIds").includes(feature.id);
|
|
3166
|
-
return /* @__PURE__ */
|
|
3167
|
-
/* @__PURE__ */
|
|
3393
|
+
return /* @__PURE__ */ jsxs35("div", { className: "flex items-center space-x-2", children: [
|
|
3394
|
+
/* @__PURE__ */ jsx40(
|
|
3168
3395
|
"input",
|
|
3169
3396
|
{
|
|
3170
3397
|
type: "checkbox",
|
|
@@ -3187,22 +3414,22 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3187
3414
|
className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary disabled:opacity-50"
|
|
3188
3415
|
}
|
|
3189
3416
|
),
|
|
3190
|
-
/* @__PURE__ */
|
|
3417
|
+
/* @__PURE__ */ jsxs35(
|
|
3191
3418
|
"label",
|
|
3192
3419
|
{
|
|
3193
3420
|
htmlFor: `feature-${feature.id}`,
|
|
3194
3421
|
className: `text-sm ${isCore ? "text-muted-foreground" : ""}`,
|
|
3195
3422
|
children: [
|
|
3196
3423
|
feature.name,
|
|
3197
|
-
isCore && /* @__PURE__ */
|
|
3424
|
+
isCore && /* @__PURE__ */ jsx40("span", { className: "ml-2 text-xs text-muted-foreground", children: "(Core - Required)" })
|
|
3198
3425
|
]
|
|
3199
3426
|
}
|
|
3200
3427
|
)
|
|
3201
3428
|
] }, feature.id);
|
|
3202
3429
|
}) })
|
|
3203
3430
|
] }),
|
|
3204
|
-
/* @__PURE__ */
|
|
3205
|
-
isRecurring && /* @__PURE__ */
|
|
3431
|
+
/* @__PURE__ */ jsx40(FormCheckbox, { form, id: "active", name: "Active" }),
|
|
3432
|
+
isRecurring && /* @__PURE__ */ jsx40(
|
|
3206
3433
|
FormCheckbox,
|
|
3207
3434
|
{
|
|
3208
3435
|
form,
|
|
@@ -3211,7 +3438,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3211
3438
|
description: "Mark this as the trial subscription plan (only one price should be marked as trial)"
|
|
3212
3439
|
}
|
|
3213
3440
|
),
|
|
3214
|
-
/* @__PURE__ */
|
|
3441
|
+
/* @__PURE__ */ jsx40(CommonEditorButtons, { isEdit: isEditMode, form, disabled: isSubmitting, setOpen: onOpenChange })
|
|
3215
3442
|
] }) })
|
|
3216
3443
|
] }) });
|
|
3217
3444
|
}
|
|
@@ -3219,17 +3446,17 @@ __name(PriceEditor, "PriceEditor");
|
|
|
3219
3446
|
|
|
3220
3447
|
// src/features/billing/stripe-price/components/lists/PricesList.tsx
|
|
3221
3448
|
import { Archive, DollarSign, Edit, RotateCcw } from "lucide-react";
|
|
3222
|
-
import { useEffect as useEffect11, useState as
|
|
3223
|
-
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";
|
|
3224
3451
|
function PricesList({ productId, onPricesChange }) {
|
|
3225
|
-
const [prices, setPrices] =
|
|
3226
|
-
const [loading, setLoading] =
|
|
3227
|
-
const [showCreatePrice, setShowCreatePrice] =
|
|
3228
|
-
const [editingPrice, setEditingPrice] =
|
|
3229
|
-
const [priceToArchive, setPriceToArchive] =
|
|
3230
|
-
const [priceToReactivate, setPriceToReactivate] =
|
|
3231
|
-
const [archivingPriceId, setArchivingPriceId] =
|
|
3232
|
-
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);
|
|
3233
3460
|
const loadPrices = /* @__PURE__ */ __name(async () => {
|
|
3234
3461
|
setLoading(true);
|
|
3235
3462
|
try {
|
|
@@ -3292,27 +3519,27 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3292
3519
|
return "";
|
|
3293
3520
|
}, "formatInterval");
|
|
3294
3521
|
if (loading) {
|
|
3295
|
-
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..." }) });
|
|
3296
3523
|
}
|
|
3297
|
-
return /* @__PURE__ */
|
|
3298
|
-
/* @__PURE__ */
|
|
3299
|
-
/* @__PURE__ */
|
|
3300
|
-
/* @__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" })
|
|
3301
3528
|
] }),
|
|
3302
|
-
prices.length === 0 && /* @__PURE__ */
|
|
3303
|
-
/* @__PURE__ */
|
|
3304
|
-
/* @__PURE__ */
|
|
3305
|
-
/* @__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" })
|
|
3306
3533
|
] }),
|
|
3307
|
-
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) => {
|
|
3308
3535
|
const isArchiving = archivingPriceId === price.id;
|
|
3309
3536
|
const isReactivating = reactivatingPriceId === price.id;
|
|
3310
|
-
return /* @__PURE__ */
|
|
3311
|
-
/* @__PURE__ */
|
|
3312
|
-
/* @__PURE__ */
|
|
3313
|
-
/* @__PURE__ */
|
|
3314
|
-
/* @__PURE__ */
|
|
3315
|
-
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(
|
|
3316
3543
|
Button,
|
|
3317
3544
|
{
|
|
3318
3545
|
variant: "ghost",
|
|
@@ -3320,9 +3547,9 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3320
3547
|
onClick: () => setPriceToArchive(price),
|
|
3321
3548
|
className: "h-8 w-8 p-0",
|
|
3322
3549
|
disabled: isArchiving,
|
|
3323
|
-
children: /* @__PURE__ */
|
|
3550
|
+
children: /* @__PURE__ */ jsx41(Archive, { className: "h-4 w-4" })
|
|
3324
3551
|
}
|
|
3325
|
-
) : /* @__PURE__ */
|
|
3552
|
+
) : /* @__PURE__ */ jsx41(
|
|
3326
3553
|
Button,
|
|
3327
3554
|
{
|
|
3328
3555
|
variant: "ghost",
|
|
@@ -3330,25 +3557,25 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3330
3557
|
onClick: () => setPriceToReactivate(price),
|
|
3331
3558
|
className: "h-8 w-8 p-0",
|
|
3332
3559
|
disabled: isReactivating,
|
|
3333
|
-
children: /* @__PURE__ */
|
|
3560
|
+
children: /* @__PURE__ */ jsx41(RotateCcw, { className: "h-4 w-4" })
|
|
3334
3561
|
}
|
|
3335
3562
|
)
|
|
3336
3563
|
] })
|
|
3337
3564
|
] }),
|
|
3338
|
-
/* @__PURE__ */
|
|
3565
|
+
/* @__PURE__ */ jsx41("div", { className: "mb-2", children: /* @__PURE__ */ jsxs36("div", { className: "text-2xl font-bold", children: [
|
|
3339
3566
|
formatCurrency(price.unitAmount, price.currency),
|
|
3340
3567
|
" ",
|
|
3341
|
-
/* @__PURE__ */
|
|
3568
|
+
/* @__PURE__ */ jsx41("span", { className: "text-muted-foreground text-sm font-normal", children: formatInterval2(price) })
|
|
3342
3569
|
] }) }),
|
|
3343
|
-
price.metadata?.nickname && /* @__PURE__ */
|
|
3344
|
-
/* @__PURE__ */
|
|
3345
|
-
price.active ? /* @__PURE__ */
|
|
3346
|
-
price.recurring?.usageType === "metered" && /* @__PURE__ */
|
|
3347
|
-
/* @__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 })
|
|
3348
3575
|
] })
|
|
3349
3576
|
] }, price.id);
|
|
3350
3577
|
}) }),
|
|
3351
|
-
showCreatePrice && /* @__PURE__ */
|
|
3578
|
+
showCreatePrice && /* @__PURE__ */ jsx41(
|
|
3352
3579
|
PriceEditor,
|
|
3353
3580
|
{
|
|
3354
3581
|
productId,
|
|
@@ -3360,7 +3587,7 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3360
3587
|
}
|
|
3361
3588
|
}
|
|
3362
3589
|
),
|
|
3363
|
-
editingPrice && /* @__PURE__ */
|
|
3590
|
+
editingPrice && /* @__PURE__ */ jsx41(
|
|
3364
3591
|
PriceEditor,
|
|
3365
3592
|
{
|
|
3366
3593
|
productId,
|
|
@@ -3374,19 +3601,19 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3374
3601
|
}
|
|
3375
3602
|
}
|
|
3376
3603
|
),
|
|
3377
|
-
/* @__PURE__ */
|
|
3378
|
-
/* @__PURE__ */
|
|
3379
|
-
/* @__PURE__ */
|
|
3380
|
-
/* @__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: [
|
|
3381
3608
|
"Are you sure you want to archive the price for",
|
|
3382
3609
|
" ",
|
|
3383
3610
|
priceToArchive && `${formatCurrency(priceToArchive.unitAmount, priceToArchive.currency)} ${formatInterval2(priceToArchive)}`,
|
|
3384
3611
|
"? This will prevent new subscriptions but existing ones will continue."
|
|
3385
3612
|
] })
|
|
3386
3613
|
] }),
|
|
3387
|
-
/* @__PURE__ */
|
|
3388
|
-
/* @__PURE__ */
|
|
3389
|
-
/* @__PURE__ */
|
|
3614
|
+
/* @__PURE__ */ jsxs36(AlertDialogFooter, { children: [
|
|
3615
|
+
/* @__PURE__ */ jsx41(AlertDialogCancel, { disabled: !!archivingPriceId, children: "Cancel" }),
|
|
3616
|
+
/* @__PURE__ */ jsx41(
|
|
3390
3617
|
AlertDialogAction,
|
|
3391
3618
|
{
|
|
3392
3619
|
onClick: handleArchive,
|
|
@@ -3397,19 +3624,19 @@ function PricesList({ productId, onPricesChange }) {
|
|
|
3397
3624
|
)
|
|
3398
3625
|
] })
|
|
3399
3626
|
] }) }),
|
|
3400
|
-
/* @__PURE__ */
|
|
3401
|
-
/* @__PURE__ */
|
|
3402
|
-
/* @__PURE__ */
|
|
3403
|
-
/* @__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: [
|
|
3404
3631
|
"Are you sure you want to reactivate the price for",
|
|
3405
3632
|
" ",
|
|
3406
3633
|
priceToReactivate && `${formatCurrency(priceToReactivate.unitAmount, priceToReactivate.currency)} ${formatInterval2(priceToReactivate)}`,
|
|
3407
3634
|
"? This will allow new subscriptions again."
|
|
3408
3635
|
] })
|
|
3409
3636
|
] }),
|
|
3410
|
-
/* @__PURE__ */
|
|
3411
|
-
/* @__PURE__ */
|
|
3412
|
-
/* @__PURE__ */
|
|
3637
|
+
/* @__PURE__ */ jsxs36(AlertDialogFooter, { children: [
|
|
3638
|
+
/* @__PURE__ */ jsx41(AlertDialogCancel, { disabled: !!reactivatingPriceId, children: "Cancel" }),
|
|
3639
|
+
/* @__PURE__ */ jsx41(
|
|
3413
3640
|
AlertDialogAction,
|
|
3414
3641
|
{
|
|
3415
3642
|
onClick: handleReactivate,
|
|
@@ -3426,17 +3653,17 @@ __name(PricesList, "PricesList");
|
|
|
3426
3653
|
|
|
3427
3654
|
// src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx
|
|
3428
3655
|
import { Package as Package2 } from "lucide-react";
|
|
3429
|
-
import { useEffect as useEffect12, useState as
|
|
3656
|
+
import { useEffect as useEffect12, useState as useState19 } from "react";
|
|
3430
3657
|
|
|
3431
3658
|
// src/features/billing/stripe-product/components/forms/ProductEditor.tsx
|
|
3432
3659
|
import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
|
|
3433
|
-
import { useState as
|
|
3660
|
+
import { useState as useState17 } from "react";
|
|
3434
3661
|
import { useForm as useForm3 } from "react-hook-form";
|
|
3435
3662
|
import { v4 as v43 } from "uuid";
|
|
3436
3663
|
import { z as z3 } from "zod";
|
|
3437
|
-
import { jsx as
|
|
3664
|
+
import { jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3438
3665
|
function ProductEditor({ product, open, onOpenChange, onSuccess }) {
|
|
3439
|
-
const [isSubmitting, setIsSubmitting] =
|
|
3666
|
+
const [isSubmitting, setIsSubmitting] = useState17(false);
|
|
3440
3667
|
const formSchema2 = z3.object({
|
|
3441
3668
|
name: z3.string().min(1, { message: "Product name is required" }),
|
|
3442
3669
|
description: z3.string().min(1, { message: "Description is required" }),
|
|
@@ -3476,14 +3703,14 @@ function ProductEditor({ product, open, onOpenChange, onSuccess }) {
|
|
|
3476
3703
|
setIsSubmitting(false);
|
|
3477
3704
|
}
|
|
3478
3705
|
}, "onSubmit");
|
|
3479
|
-
return /* @__PURE__ */
|
|
3480
|
-
/* @__PURE__ */
|
|
3481
|
-
/* @__PURE__ */
|
|
3482
|
-
/* @__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" })
|
|
3483
3710
|
] }),
|
|
3484
|
-
/* @__PURE__ */
|
|
3485
|
-
/* @__PURE__ */
|
|
3486
|
-
/* @__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(
|
|
3487
3714
|
FormTextarea,
|
|
3488
3715
|
{
|
|
3489
3716
|
form,
|
|
@@ -3493,8 +3720,8 @@ function ProductEditor({ product, open, onOpenChange, onSuccess }) {
|
|
|
3493
3720
|
className: "min-h-32"
|
|
3494
3721
|
}
|
|
3495
3722
|
),
|
|
3496
|
-
/* @__PURE__ */
|
|
3497
|
-
/* @__PURE__ */
|
|
3723
|
+
/* @__PURE__ */ jsx42(FormCheckbox, { form, id: "active", name: "Active" }),
|
|
3724
|
+
/* @__PURE__ */ jsx42(CommonEditorButtons, { isEdit: !!product, form, disabled: isSubmitting, setOpen: onOpenChange })
|
|
3498
3725
|
] }) })
|
|
3499
3726
|
] }) });
|
|
3500
3727
|
}
|
|
@@ -3502,15 +3729,15 @@ __name(ProductEditor, "ProductEditor");
|
|
|
3502
3729
|
|
|
3503
3730
|
// src/features/billing/stripe-product/components/lists/ProductsList.tsx
|
|
3504
3731
|
import { Archive as Archive2, ChevronDown, ChevronUp, Edit as Edit2, Package, RefreshCw as RefreshCw2 } from "lucide-react";
|
|
3505
|
-
import { useState as
|
|
3506
|
-
import { jsx as
|
|
3732
|
+
import { useState as useState18 } from "react";
|
|
3733
|
+
import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3507
3734
|
function ProductsList({ products, onProductsChange }) {
|
|
3508
|
-
const [expandedProductId, setExpandedProductId] =
|
|
3509
|
-
const [editingProduct, setEditingProduct] =
|
|
3510
|
-
const [archivingProductId, setArchivingProductId] =
|
|
3511
|
-
const [reactivatingProductId, setReactivatingProductId] =
|
|
3512
|
-
const [productToArchive, setProductToArchive] =
|
|
3513
|
-
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);
|
|
3514
3741
|
const handleArchive = /* @__PURE__ */ __name(async () => {
|
|
3515
3742
|
if (!productToArchive) {
|
|
3516
3743
|
return;
|
|
@@ -3543,29 +3770,29 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3543
3770
|
const toggleExpand = /* @__PURE__ */ __name((productId) => {
|
|
3544
3771
|
setExpandedProductId(expandedProductId === productId ? null : productId);
|
|
3545
3772
|
}, "toggleExpand");
|
|
3546
|
-
return /* @__PURE__ */
|
|
3773
|
+
return /* @__PURE__ */ jsxs38("div", { className: "flex flex-col gap-y-4", children: [
|
|
3547
3774
|
products.map((product) => {
|
|
3548
3775
|
const isExpanded = expandedProductId === product.id;
|
|
3549
3776
|
const isArchiving = archivingProductId === product.id;
|
|
3550
3777
|
const isReactivating = reactivatingProductId === product.id;
|
|
3551
|
-
return /* @__PURE__ */
|
|
3552
|
-
/* @__PURE__ */
|
|
3553
|
-
/* @__PURE__ */
|
|
3554
|
-
/* @__PURE__ */
|
|
3555
|
-
/* @__PURE__ */
|
|
3556
|
-
/* @__PURE__ */
|
|
3557
|
-
/* @__PURE__ */
|
|
3558
|
-
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" })
|
|
3559
3786
|
] }),
|
|
3560
|
-
product.description && /* @__PURE__ */
|
|
3787
|
+
product.description && /* @__PURE__ */ jsx43("p", { className: "text-muted-foreground text-sm mt-1", children: product.description })
|
|
3561
3788
|
] })
|
|
3562
3789
|
] }),
|
|
3563
|
-
/* @__PURE__ */
|
|
3564
|
-
/* @__PURE__ */
|
|
3565
|
-
/* @__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" }),
|
|
3566
3793
|
"Edit"
|
|
3567
3794
|
] }),
|
|
3568
|
-
product.active ? /* @__PURE__ */
|
|
3795
|
+
product.active ? /* @__PURE__ */ jsxs38(
|
|
3569
3796
|
Button,
|
|
3570
3797
|
{
|
|
3571
3798
|
variant: "outline",
|
|
@@ -3573,11 +3800,11 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3573
3800
|
onClick: () => setProductToArchive(product),
|
|
3574
3801
|
disabled: isArchiving,
|
|
3575
3802
|
children: [
|
|
3576
|
-
/* @__PURE__ */
|
|
3803
|
+
/* @__PURE__ */ jsx43(Archive2, { className: "h-4 w-4 mr-1" }),
|
|
3577
3804
|
isArchiving ? "Archiving..." : "Archive"
|
|
3578
3805
|
]
|
|
3579
3806
|
}
|
|
3580
|
-
) : /* @__PURE__ */
|
|
3807
|
+
) : /* @__PURE__ */ jsxs38(
|
|
3581
3808
|
Button,
|
|
3582
3809
|
{
|
|
3583
3810
|
variant: "outline",
|
|
@@ -3585,18 +3812,18 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3585
3812
|
onClick: () => setProductToReactivate(product),
|
|
3586
3813
|
disabled: isReactivating,
|
|
3587
3814
|
children: [
|
|
3588
|
-
/* @__PURE__ */
|
|
3815
|
+
/* @__PURE__ */ jsx43(RefreshCw2, { className: "h-4 w-4 mr-1" }),
|
|
3589
3816
|
isReactivating ? "Reactivating..." : "Reactivate"
|
|
3590
3817
|
]
|
|
3591
3818
|
}
|
|
3592
3819
|
),
|
|
3593
|
-
/* @__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" }) })
|
|
3594
3821
|
] })
|
|
3595
3822
|
] }),
|
|
3596
|
-
isExpanded && /* @__PURE__ */
|
|
3823
|
+
isExpanded && /* @__PURE__ */ jsx43("div", { className: "border-t bg-muted/30 p-6", children: /* @__PURE__ */ jsx43(PricesList, { productId: product.id, onPricesChange: onProductsChange }) })
|
|
3597
3824
|
] }, product.id);
|
|
3598
3825
|
}),
|
|
3599
|
-
editingProduct && /* @__PURE__ */
|
|
3826
|
+
editingProduct && /* @__PURE__ */ jsx43(
|
|
3600
3827
|
ProductEditor,
|
|
3601
3828
|
{
|
|
3602
3829
|
product: editingProduct,
|
|
@@ -3608,18 +3835,18 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3608
3835
|
}
|
|
3609
3836
|
}
|
|
3610
3837
|
),
|
|
3611
|
-
/* @__PURE__ */
|
|
3612
|
-
/* @__PURE__ */
|
|
3613
|
-
/* @__PURE__ */
|
|
3614
|
-
/* @__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: [
|
|
3615
3842
|
'Are you sure you want to archive "',
|
|
3616
3843
|
productToArchive?.name,
|
|
3617
3844
|
'"? This will deactivate it and it will no longer be available for new subscriptions.'
|
|
3618
3845
|
] })
|
|
3619
3846
|
] }),
|
|
3620
|
-
/* @__PURE__ */
|
|
3621
|
-
/* @__PURE__ */
|
|
3622
|
-
/* @__PURE__ */
|
|
3847
|
+
/* @__PURE__ */ jsxs38(AlertDialogFooter, { children: [
|
|
3848
|
+
/* @__PURE__ */ jsx43(AlertDialogCancel, { disabled: !!archivingProductId, children: "Cancel" }),
|
|
3849
|
+
/* @__PURE__ */ jsx43(
|
|
3623
3850
|
AlertDialogAction,
|
|
3624
3851
|
{
|
|
3625
3852
|
onClick: handleArchive,
|
|
@@ -3630,18 +3857,18 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3630
3857
|
)
|
|
3631
3858
|
] })
|
|
3632
3859
|
] }) }),
|
|
3633
|
-
/* @__PURE__ */
|
|
3634
|
-
/* @__PURE__ */
|
|
3635
|
-
/* @__PURE__ */
|
|
3636
|
-
/* @__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: [
|
|
3637
3864
|
'Are you sure you want to reactivate "',
|
|
3638
3865
|
productToReactivate?.name,
|
|
3639
3866
|
'"? This will make it available for new subscriptions again.'
|
|
3640
3867
|
] })
|
|
3641
3868
|
] }),
|
|
3642
|
-
/* @__PURE__ */
|
|
3643
|
-
/* @__PURE__ */
|
|
3644
|
-
/* @__PURE__ */
|
|
3869
|
+
/* @__PURE__ */ jsxs38(AlertDialogFooter, { children: [
|
|
3870
|
+
/* @__PURE__ */ jsx43(AlertDialogCancel, { disabled: !!reactivatingProductId, children: "Cancel" }),
|
|
3871
|
+
/* @__PURE__ */ jsx43(
|
|
3645
3872
|
AlertDialogAction,
|
|
3646
3873
|
{
|
|
3647
3874
|
onClick: handleReactivate,
|
|
@@ -3657,14 +3884,14 @@ function ProductsList({ products, onProductsChange }) {
|
|
|
3657
3884
|
__name(ProductsList, "ProductsList");
|
|
3658
3885
|
|
|
3659
3886
|
// src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx
|
|
3660
|
-
import { jsx as
|
|
3887
|
+
import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3661
3888
|
function ProductsAdminContainer() {
|
|
3662
3889
|
const { hasRole } = useCurrentUserContext();
|
|
3663
|
-
const [products, setProducts] =
|
|
3664
|
-
const [loading, setLoading] =
|
|
3665
|
-
const [showCreateProduct, setShowCreateProduct] =
|
|
3890
|
+
const [products, setProducts] = useState19([]);
|
|
3891
|
+
const [loading, setLoading] = useState19(true);
|
|
3892
|
+
const [showCreateProduct, setShowCreateProduct] = useState19(false);
|
|
3666
3893
|
if (!hasRole(getRoleId().Administrator)) {
|
|
3667
|
-
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." }) });
|
|
3668
3895
|
}
|
|
3669
3896
|
const loadProducts = /* @__PURE__ */ __name(async () => {
|
|
3670
3897
|
setLoading(true);
|
|
@@ -3681,26 +3908,26 @@ function ProductsAdminContainer() {
|
|
|
3681
3908
|
loadProducts();
|
|
3682
3909
|
}, []);
|
|
3683
3910
|
if (loading) {
|
|
3684
|
-
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..." }) });
|
|
3685
3912
|
}
|
|
3686
|
-
return /* @__PURE__ */
|
|
3687
|
-
/* @__PURE__ */
|
|
3688
|
-
/* @__PURE__ */
|
|
3689
|
-
/* @__PURE__ */
|
|
3690
|
-
/* @__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" })
|
|
3691
3918
|
] }),
|
|
3692
|
-
/* @__PURE__ */
|
|
3919
|
+
/* @__PURE__ */ jsx44(Button, { onClick: () => setShowCreateProduct(true), children: "Create Product" })
|
|
3693
3920
|
] }),
|
|
3694
|
-
products.length === 0 && /* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
3696
|
-
/* @__PURE__ */
|
|
3697
|
-
/* @__PURE__ */
|
|
3698
|
-
/* @__PURE__ */
|
|
3699
|
-
/* @__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" })
|
|
3700
3927
|
] })
|
|
3701
3928
|
] }),
|
|
3702
|
-
products.length > 0 && /* @__PURE__ */
|
|
3703
|
-
showCreateProduct && /* @__PURE__ */
|
|
3929
|
+
products.length > 0 && /* @__PURE__ */ jsx44(ProductsList, { products, onProductsChange: loadProducts }),
|
|
3930
|
+
showCreateProduct && /* @__PURE__ */ jsx44(ProductEditor, { open: showCreateProduct, onOpenChange: setShowCreateProduct, onSuccess: loadProducts })
|
|
3704
3931
|
] });
|
|
3705
3932
|
}
|
|
3706
3933
|
__name(ProductsAdminContainer, "ProductsAdminContainer");
|
|
@@ -3731,6 +3958,7 @@ export {
|
|
|
3731
3958
|
ProductPricingRow,
|
|
3732
3959
|
ProductsAdminContainer,
|
|
3733
3960
|
ProductsList,
|
|
3961
|
+
PromoCodeInput,
|
|
3734
3962
|
ProrationPreview,
|
|
3735
3963
|
StripeProvider,
|
|
3736
3964
|
SubscriptionConfirmation,
|