@carlonicora/nextjs-jsonapi 1.32.1 → 1.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BlockNoteEditor-YEVSJSOI.js → BlockNoteEditor-CUXI6ZTZ.js} +14 -14
- package/dist/{BlockNoteEditor-YEVSJSOI.js.map → BlockNoteEditor-CUXI6ZTZ.js.map} +1 -1
- package/dist/{BlockNoteEditor-TFL6ZXIJ.mjs → BlockNoteEditor-UTZ7F23J.mjs} +4 -4
- package/dist/billing/index.d.mts +6 -3
- package/dist/billing/index.d.ts +6 -3
- package/dist/billing/index.js +465 -384
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +114 -33
- package/dist/billing/index.mjs.map +1 -1
- package/dist/{chunk-NPNKFWV2.js → chunk-2PHWAL6Q.js} +4 -4
- package/dist/chunk-2PHWAL6Q.js.map +1 -0
- package/dist/{chunk-SLANIL6B.mjs → chunk-53WT73E6.mjs} +56 -64
- package/dist/chunk-53WT73E6.mjs.map +1 -0
- package/dist/{chunk-YCP2OMFD.mjs → chunk-HWQBSVBT.mjs} +40 -7
- package/dist/chunk-HWQBSVBT.mjs.map +1 -0
- package/dist/{chunk-HIF7DYR3.js → chunk-RSHCU3TI.js} +553 -561
- package/dist/chunk-RSHCU3TI.js.map +1 -0
- package/dist/{chunk-KYG2PIRB.js → chunk-TZRAOUAR.js} +118 -85
- package/dist/chunk-TZRAOUAR.js.map +1 -0
- package/dist/{chunk-IXVNXOZT.mjs → chunk-XLMJPA4N.mjs} +4 -4
- package/dist/{chunk-IXVNXOZT.mjs.map → chunk-XLMJPA4N.mjs.map} +1 -1
- package/dist/client/index.d.mts +7 -6
- package/dist/client/index.d.ts +7 -6
- package/dist/client/index.js +4 -4
- package/dist/client/index.mjs +3 -3
- package/dist/components/index.d.mts +4 -3
- package/dist/components/index.d.ts +4 -3
- package/dist/components/index.js +4 -4
- package/dist/components/index.mjs +3 -3
- package/dist/{config-CHwoRDOp.d.ts → config-BbaBV_yk.d.ts} +1 -1
- package/dist/{config-DiWyJzk9.d.mts → config-BxwhHdCD.d.mts} +1 -1
- package/dist/{content.interface-BSpowEiW.d.mts → content.interface-CWV0q4lZ.d.mts} +1 -1
- package/dist/{content.interface-DFQ7mkpL.d.ts → content.interface-CgUu4771.d.ts} +1 -1
- package/dist/contexts/index.d.mts +3 -2
- package/dist/contexts/index.d.ts +3 -2
- package/dist/contexts/index.js +4 -4
- package/dist/contexts/index.mjs +3 -3
- package/dist/core/index.d.mts +17 -8
- package/dist/core/index.d.ts +17 -8
- package/dist/core/index.js +6 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +5 -1
- package/dist/feature.interface-BxFFOPNq.d.mts +19 -0
- package/dist/feature.interface-CIWxo8NP.d.ts +19 -0
- package/dist/index.d.mts +10 -9
- package/dist/index.d.ts +10 -9
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -2
- package/dist/{notification.interface-D5MbtfZK.d.mts → notification.interface-DIln2r7X.d.mts} +2 -17
- package/dist/{notification.interface-CmKmObIU.d.ts → notification.interface-XARGKJAq.d.ts} +2 -17
- package/dist/{s3.service-CoC0k0iu.d.ts → s3.service-DcqkGrKD.d.ts} +12 -3
- package/dist/{s3.service-Duh9HW2n.d.mts → s3.service-ag6M_7GO.d.mts} +12 -3
- package/dist/scripts/generate-web-module/templates/pages/detail-page.template.js +1 -1
- package/dist/scripts/generate-web-module/templates/pages/detail-page.template.js.map +1 -1
- package/dist/scripts/generate-web-module/templates/pages/list-page.template.js +1 -1
- package/dist/scripts/generate-web-module/templates/pages/list-page.template.js.map +1 -1
- package/dist/server/index.d.mts +4 -3
- package/dist/server/index.d.ts +4 -3
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +1 -1
- package/dist/{stripe-subscription.interface-BaZUngWe.d.ts → stripe-subscription.interface-Dm__xmvE.d.ts} +3 -0
- package/dist/{stripe-subscription.interface-Cm_It1fz.d.mts → stripe-subscription.interface-_VWPY2AA.d.mts} +3 -0
- package/dist/{useDataListRetriever-futhx3OP.d.mts → useDataListRetriever-BqJSFBck.d.mts} +1 -0
- package/dist/{useDataListRetriever-futhx3OP.d.ts → useDataListRetriever-BqJSFBck.d.ts} +1 -0
- package/dist/{useSocket-DUqGoPya.d.mts → useSocket-BILAdmZ0.d.mts} +1 -1
- package/dist/{useSocket-QuHa0ZmO.d.ts → useSocket-awibcC9B.d.ts} +1 -1
- package/package.json +1 -1
- package/scripts/generate-web-module/templates/pages/detail-page.template.ts +1 -1
- package/scripts/generate-web-module/templates/pages/list-page.template.ts +1 -1
- package/src/components/forms/DatePickerPopover.tsx +17 -15
- package/src/components/tables/ContentListTable.tsx +2 -2
- package/src/core/abstracts/AbstractService.ts +25 -0
- package/src/core/abstracts/ClientAbstractService.ts +10 -0
- package/src/features/billing/components/containers/BillingDashboardContainer.tsx +4 -1
- package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +1 -1
- package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +1 -1
- package/src/features/billing/stripe-price/components/forms/PriceEditor.tsx +85 -1
- package/src/features/billing/stripe-price/data/stripe-price.interface.ts +3 -0
- package/src/features/billing/stripe-price/data/stripe-price.ts +18 -0
- package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +5 -2
- package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +5 -18
- package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +1 -1
- package/src/features/billing/stripe-subscription/components/widgets/ProductPricingList.tsx +16 -12
- package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +14 -3
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepPlanSelection.tsx +14 -9
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +1 -1
- package/src/features/billing/stripe-subscription/data/stripe-subscription.service.ts +2 -2
- package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +1 -1
- package/src/features/company/components/details/TokenStatusIndicator.tsx +4 -6
- package/src/features/company/hooks/useSubscriptionStatus.ts +18 -0
- package/src/features/content/hooks/useContentTableStructure.tsx +1 -1
- package/src/features/user/contexts/CurrentUserContext.tsx +2 -1
- package/src/features/user/hooks/useUserTableStructure.tsx +1 -1
- package/src/hooks/useDataListRetriever.ts +13 -0
- package/src/login/config.ts +6 -6
- package/src/shadcnui/ui/table.tsx +20 -49
- package/dist/chunk-HIF7DYR3.js.map +0 -1
- package/dist/chunk-KYG2PIRB.js.map +0 -1
- package/dist/chunk-NPNKFWV2.js.map +0 -1
- package/dist/chunk-SLANIL6B.mjs.map +0 -1
- package/dist/chunk-YCP2OMFD.mjs.map +0 -1
- /package/dist/{BlockNoteEditor-TFL6ZXIJ.mjs.map → BlockNoteEditor-UTZ7F23J.mjs.map} +0 -0
package/dist/billing/index.mjs
CHANGED
|
@@ -47,12 +47,13 @@ import {
|
|
|
47
47
|
TabsList,
|
|
48
48
|
TabsTrigger,
|
|
49
49
|
useCurrentUserContext
|
|
50
|
-
} from "../chunk-
|
|
50
|
+
} from "../chunk-53WT73E6.mjs";
|
|
51
51
|
import {
|
|
52
52
|
getRoleId,
|
|
53
53
|
getStripePublishableKey
|
|
54
|
-
} from "../chunk-
|
|
54
|
+
} from "../chunk-XLMJPA4N.mjs";
|
|
55
55
|
import {
|
|
56
|
+
FeatureService,
|
|
56
57
|
StripeCustomerService,
|
|
57
58
|
StripeInvoiceService,
|
|
58
59
|
StripePriceService,
|
|
@@ -60,7 +61,7 @@ import {
|
|
|
60
61
|
StripeSubscriptionService,
|
|
61
62
|
StripeUsageService,
|
|
62
63
|
cn
|
|
63
|
-
} from "../chunk-
|
|
64
|
+
} from "../chunk-HWQBSVBT.mjs";
|
|
64
65
|
import "../chunk-AUXK7QSA.mjs";
|
|
65
66
|
import "../chunk-C7C7VY4F.mjs";
|
|
66
67
|
import "../chunk-U4MTVHOC.mjs";
|
|
@@ -981,7 +982,7 @@ function InvoiceDetails({ invoice, open, onOpenChange, onInvoiceChange }) {
|
|
|
981
982
|
] }),
|
|
982
983
|
/* @__PURE__ */ jsxs10("div", { children: [
|
|
983
984
|
/* @__PURE__ */ jsx12("h4", { className: "text-sm font-medium text-muted-foreground mb-2", children: "Line Items" }),
|
|
984
|
-
/* @__PURE__ */ jsx12("div", { className: "border rounded-lg overflow-
|
|
985
|
+
/* @__PURE__ */ jsx12("div", { className: "border rounded-lg overflow-clip", children: /* @__PURE__ */ jsxs10("table", { className: "w-full", children: [
|
|
985
986
|
/* @__PURE__ */ jsx12("thead", { className: "bg-muted", children: /* @__PURE__ */ jsxs10("tr", { children: [
|
|
986
987
|
/* @__PURE__ */ jsx12("th", { className: "text-left p-3 text-sm font-medium", children: "Description" }),
|
|
987
988
|
/* @__PURE__ */ jsx12("th", { className: "text-right p-3 text-sm font-medium", children: "Amount" })
|
|
@@ -1047,7 +1048,7 @@ function InvoicesList({ invoices, onInvoicesChange }) {
|
|
|
1047
1048
|
return invoice.stripeInvoiceId.slice(-8);
|
|
1048
1049
|
}, "getInvoiceNumber");
|
|
1049
1050
|
return /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
1050
|
-
/* @__PURE__ */ jsx13("div", { className: "border rounded-lg overflow-
|
|
1051
|
+
/* @__PURE__ */ jsx13("div", { className: "border rounded-lg overflow-clip", children: /* @__PURE__ */ jsxs11(Table, { children: [
|
|
1051
1052
|
/* @__PURE__ */ jsx13(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs11(TableRow, { children: [
|
|
1052
1053
|
/* @__PURE__ */ jsx13(TableHead, { children: "Invoice #" }),
|
|
1053
1054
|
/* @__PURE__ */ jsx13(TableHead, { children: "Date" }),
|
|
@@ -1153,7 +1154,6 @@ import { useForm } from "react-hook-form";
|
|
|
1153
1154
|
import { z } from "zod";
|
|
1154
1155
|
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1155
1156
|
var formSchema = z.object({
|
|
1156
|
-
cancelImmediately: z.boolean(),
|
|
1157
1157
|
reason: z.string().optional()
|
|
1158
1158
|
});
|
|
1159
1159
|
function CancelSubscriptionDialog({
|
|
@@ -1166,17 +1166,15 @@ function CancelSubscriptionDialog({
|
|
|
1166
1166
|
const form = useForm({
|
|
1167
1167
|
resolver: zodResolver(formSchema),
|
|
1168
1168
|
defaultValues: {
|
|
1169
|
-
cancelImmediately: false,
|
|
1170
1169
|
reason: ""
|
|
1171
1170
|
}
|
|
1172
1171
|
});
|
|
1173
|
-
const cancelImmediately = form.watch("cancelImmediately");
|
|
1174
1172
|
const onSubmit = /* @__PURE__ */ __name(async (values) => {
|
|
1175
1173
|
setIsSubmitting(true);
|
|
1176
1174
|
try {
|
|
1177
1175
|
await StripeSubscriptionService.cancelSubscription({
|
|
1178
1176
|
id: subscription.id,
|
|
1179
|
-
cancelImmediately:
|
|
1177
|
+
cancelImmediately: false
|
|
1180
1178
|
});
|
|
1181
1179
|
onSuccess();
|
|
1182
1180
|
onOpenChange(false);
|
|
@@ -1193,8 +1191,7 @@ function CancelSubscriptionDialog({
|
|
|
1193
1191
|
/* @__PURE__ */ jsx15(DialogDescription, { children: "Are you sure you want to cancel this subscription? This action cannot be undone." })
|
|
1194
1192
|
] }),
|
|
1195
1193
|
/* @__PURE__ */ jsx15(Form, { ...form, children: /* @__PURE__ */ jsxs13("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
|
|
1196
|
-
/* @__PURE__ */
|
|
1197
|
-
cancelImmediately ? /* @__PURE__ */ jsx15("div", { className: "bg-red-50 border border-red-200 rounded-lg p-3 text-sm text-red-800", children: "Your subscription will be canceled immediately and you will lose access right away." }) : /* @__PURE__ */ jsxs13("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-3 text-sm text-blue-800", children: [
|
|
1194
|
+
/* @__PURE__ */ jsxs13("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-3 text-sm text-blue-800", children: [
|
|
1198
1195
|
"Your subscription will remain active until ",
|
|
1199
1196
|
periodEndDate,
|
|
1200
1197
|
". You can continue using the service until then."
|
|
@@ -1423,7 +1420,7 @@ function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan
|
|
|
1423
1420
|
setSelectedSub(subscription);
|
|
1424
1421
|
}, "handleRowClick");
|
|
1425
1422
|
return /* @__PURE__ */ jsxs15(Fragment4, { children: [
|
|
1426
|
-
/* @__PURE__ */ jsx18("div", { className: "border rounded-lg overflow-
|
|
1423
|
+
/* @__PURE__ */ jsx18("div", { className: "border rounded-lg overflow-clip", children: /* @__PURE__ */ jsxs15(Table, { children: [
|
|
1427
1424
|
/* @__PURE__ */ jsx18(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs15(TableRow, { children: [
|
|
1428
1425
|
/* @__PURE__ */ jsx18(TableHead, { children: "Status" }),
|
|
1429
1426
|
/* @__PURE__ */ jsx18(TableHead, { children: "Plan" }),
|
|
@@ -1472,7 +1469,7 @@ __name(SubscriptionsList, "SubscriptionsList");
|
|
|
1472
1469
|
|
|
1473
1470
|
// src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx
|
|
1474
1471
|
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1475
|
-
function SubscriptionsContainer({ onOpenWizard }) {
|
|
1472
|
+
function SubscriptionsContainer({ onOpenWizard, hasActiveRecurringSubscription }) {
|
|
1476
1473
|
const [subscriptions, setSubscriptions] = useState10([]);
|
|
1477
1474
|
const [loading, setLoading] = useState10(true);
|
|
1478
1475
|
const loadSubscriptions = useCallback(async () => {
|
|
@@ -1501,7 +1498,7 @@ function SubscriptionsContainer({ onOpenWizard }) {
|
|
|
1501
1498
|
/* @__PURE__ */ jsx19(CreditCard3, { className: "h-8 w-8" }),
|
|
1502
1499
|
/* @__PURE__ */ jsx19("h1", { className: "text-3xl font-bold", children: "Subscriptions" })
|
|
1503
1500
|
] }),
|
|
1504
|
-
subscriptions.length > 0 && /* @__PURE__ */ jsx19(Button, { onClick: () => onOpenWizard?.(), children: "Subscribe to a Plan" })
|
|
1501
|
+
subscriptions.length > 0 && /* @__PURE__ */ jsx19(Button, { onClick: () => onOpenWizard?.(), children: hasActiveRecurringSubscription ? "Purchase Add-ons" : "Subscribe to a Plan" })
|
|
1505
1502
|
] }),
|
|
1506
1503
|
criticalSubscriptions.map((subscription) => /* @__PURE__ */ jsx19(BillingAlertBanner, { subscription }, subscription.id)),
|
|
1507
1504
|
subscriptions.length === 0 && /* @__PURE__ */ jsxs16("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
|
|
@@ -1669,7 +1666,8 @@ function ProductPricingList({
|
|
|
1669
1666
|
loadingPriceId,
|
|
1670
1667
|
loading = false,
|
|
1671
1668
|
onSelectPrice,
|
|
1672
|
-
hideRecurringPrices = false
|
|
1669
|
+
hideRecurringPrices = false,
|
|
1670
|
+
hideOneTimePrices = false
|
|
1673
1671
|
}) {
|
|
1674
1672
|
if (loading) {
|
|
1675
1673
|
return /* @__PURE__ */ jsx23(ProductPricingListSkeleton, {});
|
|
@@ -1684,13 +1682,16 @@ function ProductPricingList({
|
|
|
1684
1682
|
if (!aRecurring && bRecurring) return 1;
|
|
1685
1683
|
return 0;
|
|
1686
1684
|
});
|
|
1687
|
-
|
|
1688
|
-
...product,
|
|
1689
|
-
stripePrices: (product.stripePrices || []).filter((price) => price.priceType !== "recurring")
|
|
1690
|
-
})).filter((product) => product.stripePrices.length > 0) : sortedProducts;
|
|
1691
|
-
return /* @__PURE__ */ jsx23("div", { className: "space-y-6", children: filteredProducts.map((product) => {
|
|
1685
|
+
return /* @__PURE__ */ jsx23("div", { className: "space-y-6", children: sortedProducts.map((product) => {
|
|
1692
1686
|
const allPrices = product.stripePrices || [];
|
|
1693
|
-
|
|
1687
|
+
let pricesToFilter = allPrices;
|
|
1688
|
+
if (hideRecurringPrices) {
|
|
1689
|
+
pricesToFilter = pricesToFilter.filter((price) => price.priceType !== "recurring");
|
|
1690
|
+
}
|
|
1691
|
+
if (hideOneTimePrices) {
|
|
1692
|
+
pricesToFilter = pricesToFilter.filter((price) => price.priceType !== "one_time");
|
|
1693
|
+
}
|
|
1694
|
+
const filteredPrices = getFilteredPrices(pricesToFilter, selectedInterval);
|
|
1694
1695
|
if (filteredPrices.length === 0) {
|
|
1695
1696
|
return null;
|
|
1696
1697
|
}
|
|
@@ -1994,6 +1995,7 @@ function WizardStepPlanSelection({
|
|
|
1994
1995
|
selectedInterval,
|
|
1995
1996
|
currentPriceId,
|
|
1996
1997
|
hideRecurringPrices,
|
|
1998
|
+
hideOneTimePrices,
|
|
1997
1999
|
onSelectPrice,
|
|
1998
2000
|
onIntervalChange,
|
|
1999
2001
|
onNext,
|
|
@@ -2033,7 +2035,7 @@ function WizardStepPlanSelection({
|
|
|
2033
2035
|
onSelectPrice(price);
|
|
2034
2036
|
}, "handleSelectPrice");
|
|
2035
2037
|
return /* @__PURE__ */ jsxs24("div", { className: "space-y-6", children: [
|
|
2036
|
-
/* @__PURE__ */ jsx27("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx27(
|
|
2038
|
+
!hideRecurringPrices && /* @__PURE__ */ jsx27("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx27(
|
|
2037
2039
|
IntervalToggle,
|
|
2038
2040
|
{
|
|
2039
2041
|
value: selectedInterval,
|
|
@@ -2051,6 +2053,7 @@ function WizardStepPlanSelection({
|
|
|
2051
2053
|
selectedPriceId: selectedPrice?.id,
|
|
2052
2054
|
loading,
|
|
2053
2055
|
hideRecurringPrices,
|
|
2056
|
+
hideOneTimePrices,
|
|
2054
2057
|
onSelectPrice: handleSelectPrice
|
|
2055
2058
|
}
|
|
2056
2059
|
),
|
|
@@ -2101,7 +2104,7 @@ function WizardStepReview({
|
|
|
2101
2104
|
/* @__PURE__ */ jsx28("p", { className: "text-sm text-blue-700", children: "Your next charge will be adjusted to account for the plan change." }),
|
|
2102
2105
|
/* @__PURE__ */ jsxs25("div", { className: "flex justify-between text-sm", children: [
|
|
2103
2106
|
/* @__PURE__ */ jsx28("span", { className: "text-blue-600", children: "Amount due now:" }),
|
|
2104
|
-
/* @__PURE__ */ jsx28("span", { className: "font-medium text-blue-800", children: formatCurrency(prorationPreview.
|
|
2107
|
+
/* @__PURE__ */ jsx28("span", { className: "font-medium text-blue-800", children: formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency) })
|
|
2105
2108
|
] })
|
|
2106
2109
|
] }),
|
|
2107
2110
|
/* @__PURE__ */ jsx28("div", { className: "border rounded-lg p-4", children: /* @__PURE__ */ jsxs25("div", { className: "flex justify-between items-center", children: [
|
|
@@ -2184,8 +2187,10 @@ function SubscriptionWizard({
|
|
|
2184
2187
|
actions.reset();
|
|
2185
2188
|
}
|
|
2186
2189
|
}, [open, actions.reset]);
|
|
2187
|
-
const
|
|
2188
|
-
const
|
|
2190
|
+
const isPurchasingAddons = hasActiveRecurringSubscription && !subscription;
|
|
2191
|
+
const isChangePlanMode = !!subscription;
|
|
2192
|
+
const dialogTitle = subscription ? "Change Subscription Plan" : isPurchasingAddons ? "Purchase Add-ons" : "Subscribe to a Plan";
|
|
2193
|
+
const dialogDescription = subscription ? "Select a new plan for your subscription" : isPurchasingAddons ? "Select one-time products to purchase" : "Choose a subscription plan to get started";
|
|
2189
2194
|
return /* @__PURE__ */ jsx30(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs27(DialogContent, { className: "max-w-2xl", children: [
|
|
2190
2195
|
/* @__PURE__ */ jsxs27(DialogHeader, { children: [
|
|
2191
2196
|
/* @__PURE__ */ jsx30(DialogTitle, { children: dialogTitle }),
|
|
@@ -2198,7 +2203,8 @@ function SubscriptionWizard({
|
|
|
2198
2203
|
selectedPrice: state.selectedPrice,
|
|
2199
2204
|
selectedInterval: state.selectedInterval,
|
|
2200
2205
|
currentPriceId: subscription?.price?.id,
|
|
2201
|
-
hideRecurringPrices:
|
|
2206
|
+
hideRecurringPrices: isPurchasingAddons,
|
|
2207
|
+
hideOneTimePrices: isChangePlanMode,
|
|
2202
2208
|
onSelectPrice: actions.selectPrice,
|
|
2203
2209
|
onIntervalChange: actions.setInterval,
|
|
2204
2210
|
onNext: actions.goToReview,
|
|
@@ -2401,7 +2407,7 @@ function UsageHistoryTable({ usageRecords }) {
|
|
|
2401
2407
|
}
|
|
2402
2408
|
return /* @__PURE__ */ jsxs30("div", { className: "flex w-full flex-col gap-y-4", children: [
|
|
2403
2409
|
/* @__PURE__ */ jsx34("h2", { className: "text-xl font-semibold", children: "Usage History" }),
|
|
2404
|
-
/* @__PURE__ */ jsx34("div", { className: "overflow-
|
|
2410
|
+
/* @__PURE__ */ jsx34("div", { className: "overflow-clip rounded-lg border", children: /* @__PURE__ */ jsxs30(Table, { children: [
|
|
2405
2411
|
/* @__PURE__ */ jsx34(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs30(TableRow, { children: [
|
|
2406
2412
|
/* @__PURE__ */ jsx34(TableHead, { children: "Date & Time" }),
|
|
2407
2413
|
/* @__PURE__ */ jsx34(TableHead, { children: "Meter Event" }),
|
|
@@ -2777,7 +2783,13 @@ function BillingDashboardContainer() {
|
|
|
2777
2783
|
open: activeModal === "subscriptions",
|
|
2778
2784
|
onOpenChange: handleModalClose,
|
|
2779
2785
|
title: getModalTitle("subscriptions"),
|
|
2780
|
-
children: /* @__PURE__ */ jsx37(
|
|
2786
|
+
children: /* @__PURE__ */ jsx37(
|
|
2787
|
+
SubscriptionsContainer,
|
|
2788
|
+
{
|
|
2789
|
+
onOpenWizard: handleOpenWizard,
|
|
2790
|
+
hasActiveRecurringSubscription
|
|
2791
|
+
}
|
|
2792
|
+
)
|
|
2781
2793
|
}
|
|
2782
2794
|
),
|
|
2783
2795
|
/* @__PURE__ */ jsx37(
|
|
@@ -2865,6 +2877,18 @@ import { z as z2 } from "zod";
|
|
|
2865
2877
|
import { jsx as jsx39, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2866
2878
|
function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
2867
2879
|
const [isSubmitting, setIsSubmitting] = useState14(false);
|
|
2880
|
+
const [allFeatures, setAllFeatures] = useState14([]);
|
|
2881
|
+
useEffect10(() => {
|
|
2882
|
+
const fetchFeatures = /* @__PURE__ */ __name(async () => {
|
|
2883
|
+
try {
|
|
2884
|
+
const features = await FeatureService.findMany({});
|
|
2885
|
+
setAllFeatures(features);
|
|
2886
|
+
} catch (error) {
|
|
2887
|
+
console.error("[PriceEditor] Failed to fetch features:", error);
|
|
2888
|
+
}
|
|
2889
|
+
}, "fetchFeatures");
|
|
2890
|
+
fetchFeatures();
|
|
2891
|
+
}, []);
|
|
2868
2892
|
const formSchema2 = z2.object({
|
|
2869
2893
|
unitAmount: z2.preprocess(
|
|
2870
2894
|
(val) => typeof val === "string" ? parseFloat(val) : val,
|
|
@@ -2881,10 +2905,13 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
2881
2905
|
active: z2.boolean(),
|
|
2882
2906
|
description: z2.string().optional(),
|
|
2883
2907
|
features: z2.array(z2.string()),
|
|
2884
|
-
token: z2.string()
|
|
2908
|
+
token: z2.string(),
|
|
2909
|
+
featureIds: z2.array(z2.string())
|
|
2885
2910
|
});
|
|
2886
2911
|
const isEditMode = !!price;
|
|
2887
2912
|
const defaultUnitAmount = price?.unitAmount ? price.unitAmount / 100 : 0;
|
|
2913
|
+
const coreFeatureIds = allFeatures.filter((f) => f.isCore).map((f) => f.id);
|
|
2914
|
+
const defaultFeatureIds = [.../* @__PURE__ */ new Set([...price?.priceFeatures?.map((f) => f.id) ?? [], ...coreFeatureIds])];
|
|
2888
2915
|
const form = useForm2({
|
|
2889
2916
|
resolver: zodResolver2(formSchema2),
|
|
2890
2917
|
defaultValues: {
|
|
@@ -2897,11 +2924,16 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
2897
2924
|
active: price?.active ?? true,
|
|
2898
2925
|
description: price?.description || "",
|
|
2899
2926
|
features: price?.features || [],
|
|
2900
|
-
token: price?.token?.toString() ?? ""
|
|
2927
|
+
token: price?.token?.toString() ?? "",
|
|
2928
|
+
featureIds: defaultFeatureIds
|
|
2901
2929
|
}
|
|
2902
2930
|
});
|
|
2903
2931
|
useEffect10(() => {
|
|
2904
2932
|
if (open) {
|
|
2933
|
+
const currentCoreFeatureIds = allFeatures.filter((f) => f.isCore).map((f) => f.id);
|
|
2934
|
+
const resetFeatureIds = [
|
|
2935
|
+
.../* @__PURE__ */ new Set([...price?.priceFeatures?.map((f) => f.id) ?? [], ...currentCoreFeatureIds])
|
|
2936
|
+
];
|
|
2905
2937
|
form.reset({
|
|
2906
2938
|
unitAmount: price?.unitAmount ? price.unitAmount / 100 : 0,
|
|
2907
2939
|
currency: price?.currency || "usd",
|
|
@@ -2912,10 +2944,11 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
2912
2944
|
active: price?.active ?? true,
|
|
2913
2945
|
description: price?.description || "",
|
|
2914
2946
|
features: price?.features || [],
|
|
2915
|
-
token: price?.token?.toString() ?? ""
|
|
2947
|
+
token: price?.token?.toString() ?? "",
|
|
2948
|
+
featureIds: resetFeatureIds
|
|
2916
2949
|
});
|
|
2917
2950
|
}
|
|
2918
|
-
}, [open, price?.id]);
|
|
2951
|
+
}, [open, price?.id, allFeatures]);
|
|
2919
2952
|
const watchInterval = form.watch("interval");
|
|
2920
2953
|
const isRecurring = watchInterval !== "one_time";
|
|
2921
2954
|
const onSubmit = /* @__PURE__ */ __name(async (values) => {
|
|
@@ -2928,7 +2961,9 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
2928
2961
|
nickname: values.nickname || void 0,
|
|
2929
2962
|
description: values.description || void 0,
|
|
2930
2963
|
features: values.features.filter((f) => f.trim()) || void 0,
|
|
2931
|
-
token: values.token ? parseInt(values.token, 10) : void 0
|
|
2964
|
+
token: values.token ? parseInt(values.token, 10) : void 0,
|
|
2965
|
+
// Only include featureIds for recurring prices (one-time prices don't support platform features)
|
|
2966
|
+
...price?.priceType === "recurring" ? { featureIds: values.featureIds } : {}
|
|
2932
2967
|
});
|
|
2933
2968
|
} else {
|
|
2934
2969
|
const createInput = {
|
|
@@ -2957,6 +2992,9 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
2957
2992
|
if (values.token) {
|
|
2958
2993
|
createInput.token = parseInt(values.token, 10);
|
|
2959
2994
|
}
|
|
2995
|
+
if (isRecurring && values.featureIds.length > 0) {
|
|
2996
|
+
createInput.featureIds = values.featureIds;
|
|
2997
|
+
}
|
|
2960
2998
|
await StripePriceService.createPrice(createInput);
|
|
2961
2999
|
}
|
|
2962
3000
|
onSuccess();
|
|
@@ -3111,6 +3149,49 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
|
|
|
3111
3149
|
)
|
|
3112
3150
|
] })
|
|
3113
3151
|
] }),
|
|
3152
|
+
isRecurring && allFeatures.length > 0 && /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
|
|
3153
|
+
/* @__PURE__ */ jsx39(Label, { children: "Platform Features" }),
|
|
3154
|
+
/* @__PURE__ */ jsx39("div", { className: "border rounded-md p-4 space-y-2 max-h-48 overflow-y-auto", children: allFeatures.map((feature) => {
|
|
3155
|
+
const isCore = feature.isCore;
|
|
3156
|
+
const isChecked = form.watch("featureIds").includes(feature.id);
|
|
3157
|
+
return /* @__PURE__ */ jsxs34("div", { className: "flex items-center space-x-2", children: [
|
|
3158
|
+
/* @__PURE__ */ jsx39(
|
|
3159
|
+
"input",
|
|
3160
|
+
{
|
|
3161
|
+
type: "checkbox",
|
|
3162
|
+
id: `feature-${feature.id}`,
|
|
3163
|
+
checked: isChecked,
|
|
3164
|
+
disabled: isCore,
|
|
3165
|
+
onChange: (e) => {
|
|
3166
|
+
const currentIds = form.getValues("featureIds");
|
|
3167
|
+
if (e.target.checked) {
|
|
3168
|
+
form.setValue("featureIds", [...currentIds, feature.id]);
|
|
3169
|
+
} else {
|
|
3170
|
+
if (!isCore) {
|
|
3171
|
+
form.setValue(
|
|
3172
|
+
"featureIds",
|
|
3173
|
+
currentIds.filter((id) => id !== feature.id)
|
|
3174
|
+
);
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
},
|
|
3178
|
+
className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary disabled:opacity-50"
|
|
3179
|
+
}
|
|
3180
|
+
),
|
|
3181
|
+
/* @__PURE__ */ jsxs34(
|
|
3182
|
+
"label",
|
|
3183
|
+
{
|
|
3184
|
+
htmlFor: `feature-${feature.id}`,
|
|
3185
|
+
className: `text-sm ${isCore ? "text-muted-foreground" : ""}`,
|
|
3186
|
+
children: [
|
|
3187
|
+
feature.name,
|
|
3188
|
+
isCore && /* @__PURE__ */ jsx39("span", { className: "ml-2 text-xs text-muted-foreground", children: "(Core - Required)" })
|
|
3189
|
+
]
|
|
3190
|
+
}
|
|
3191
|
+
)
|
|
3192
|
+
] }, feature.id);
|
|
3193
|
+
}) })
|
|
3194
|
+
] }),
|
|
3114
3195
|
/* @__PURE__ */ jsx39(FormCheckbox, { form, id: "active", name: "Active" }),
|
|
3115
3196
|
/* @__PURE__ */ jsx39(CommonEditorButtons, { isEdit: isEditMode, form, disabled: isSubmitting, setOpen: onOpenChange })
|
|
3116
3197
|
] }) })
|