@zuplo/zudoku-plugin-monetization 0.0.25 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8 -5
- package/dist/index.mjs +334 -152
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import * as zudoku from "zudoku";
|
|
2
|
+
import "react";
|
|
2
3
|
|
|
3
|
-
//#region src/
|
|
4
|
-
|
|
4
|
+
//#region src/MonetizationContext.d.ts
|
|
5
|
+
interface MonetizationConfig {
|
|
5
6
|
pricing?: {
|
|
6
7
|
subtitle?: string;
|
|
7
8
|
title?: string;
|
|
8
|
-
units?: Record<string, string>;
|
|
9
9
|
showYearlyPrice?: boolean;
|
|
10
|
+
units?: Record<string, string>;
|
|
10
11
|
};
|
|
11
|
-
}
|
|
12
|
-
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/ZuploMonetizationPlugin.d.ts
|
|
15
|
+
declare const zuploMonetizationPlugin: (options?: MonetizationConfig | undefined) => zudoku.ZudokuPlugin;
|
|
13
16
|
//#endregion
|
|
14
17
|
export { zuploMonetizationPlugin };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn, createPlugin, joinUrl, throwIfProblemJson } from "zudoku";
|
|
2
|
-
import { AlertTriangleIcon, ArrowDownIcon, ArrowLeftRightIcon, ArrowUpIcon, CalendarIcon, CheckCheckIcon, CheckIcon,
|
|
2
|
+
import { AlertTriangleIcon, ArrowDownIcon, ArrowLeftRightIcon, ArrowUpIcon, CalendarIcon, CheckCheckIcon, CheckIcon, CircleSlashIcon, ClockIcon, CreditCardIcon, Grid2x2XIcon, InfoIcon, Loader2Icon, LockIcon, MoreVerticalIcon, RefreshCcw, RefreshCwIcon, Settings, ShieldIcon, StarsIcon, Trash2Icon, XIcon } from "zudoku/icons";
|
|
3
3
|
import { Button, ClientOnly, Head, Heading, Link, Slot } from "zudoku/components";
|
|
4
4
|
import { useAuth, useZudoku } from "zudoku/hooks";
|
|
5
5
|
import { QueryClient, QueryClientProvider, useMutation, useQuery, useQueryClient, useSuspenseQuery } from "zudoku/react-query";
|
|
@@ -8,9 +8,9 @@ import { Alert, AlertAction, AlertDescription, AlertTitle } from "zudoku/ui/Aler
|
|
|
8
8
|
import { Card, CardContent, CardHeader, CardTitle } from "zudoku/ui/Card";
|
|
9
9
|
import { Separator } from "zudoku/ui/Separator";
|
|
10
10
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { createContext, use, useEffect, useMemo, useState } from "react";
|
|
11
12
|
import { parse } from "tinyduration";
|
|
12
13
|
import { Button as Button$1 } from "zudoku/ui/Button";
|
|
13
|
-
import { useEffect, useMemo, useState } from "react";
|
|
14
14
|
import { DismissibleAlert, DismissibleAlertAction } from "zudoku/ui/DismissibleAlert";
|
|
15
15
|
import { ActionButton } from "zudoku/ui/ActionButton";
|
|
16
16
|
import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle } from "zudoku/ui/Item";
|
|
@@ -19,7 +19,6 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigge
|
|
|
19
19
|
import { Frame, FrameFooter, FramePanel } from "zudoku/ui/Frame";
|
|
20
20
|
import { Secret } from "zudoku/ui/Secret";
|
|
21
21
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "zudoku/ui/AlertDialog";
|
|
22
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from "zudoku/ui/Tooltip";
|
|
23
22
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "zudoku/ui/Dialog";
|
|
24
23
|
import { Input } from "zudoku/ui/Input";
|
|
25
24
|
import { Progress } from "zudoku/ui/Progress";
|
|
@@ -80,15 +79,9 @@ const useDeploymentName = () => {
|
|
|
80
79
|
};
|
|
81
80
|
|
|
82
81
|
//#endregion
|
|
83
|
-
//#region src/
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
const auth = useAuth();
|
|
87
|
-
return useSuspenseQuery({
|
|
88
|
-
queryKey: [`/v3/zudoku-metering/${useDeploymentName()}/pricing-page`],
|
|
89
|
-
meta: { context: auth.isAuthenticated ? zudoku : void 0 }
|
|
90
|
-
});
|
|
91
|
-
};
|
|
82
|
+
//#region src/MonetizationContext.tsx
|
|
83
|
+
const MonetizationContext = createContext({});
|
|
84
|
+
const useMonetizationConfig = () => use(MonetizationContext);
|
|
92
85
|
|
|
93
86
|
//#endregion
|
|
94
87
|
//#region src/utils/formatDuration.ts
|
|
@@ -124,6 +117,24 @@ const formatDurationInterval = (iso) => {
|
|
|
124
117
|
return iso;
|
|
125
118
|
}
|
|
126
119
|
};
|
|
120
|
+
/**
|
|
121
|
+
* Returns an adjective form suitable for possessive context
|
|
122
|
+
* e.g. "your monthly quota", "your weekly limit".
|
|
123
|
+
* Falls back to "billing period" for multi-unit cadences
|
|
124
|
+
* where "every 3 months" would be grammatically awkward.
|
|
125
|
+
*/
|
|
126
|
+
const formatDurationAdjective = (iso) => {
|
|
127
|
+
try {
|
|
128
|
+
const d = parse(iso);
|
|
129
|
+
if (d.years === 1) return "yearly";
|
|
130
|
+
if (d.months === 1) return "monthly";
|
|
131
|
+
if (d.weeks === 1) return "weekly";
|
|
132
|
+
if (d.days === 1) return "daily";
|
|
133
|
+
return "billing period";
|
|
134
|
+
} catch {
|
|
135
|
+
return "billing period";
|
|
136
|
+
}
|
|
137
|
+
};
|
|
127
138
|
|
|
128
139
|
//#endregion
|
|
129
140
|
//#region src/utils/formatPrice.ts
|
|
@@ -137,7 +148,8 @@ const formatPrice = (amount, currency) => new Intl.NumberFormat("en-US", {
|
|
|
137
148
|
|
|
138
149
|
//#endregion
|
|
139
150
|
//#region src/utils/categorizeRateCards.ts
|
|
140
|
-
const categorizeRateCards = (rateCards,
|
|
151
|
+
const categorizeRateCards = (rateCards, options) => {
|
|
152
|
+
const { currency, units, planBillingCadence } = options ?? {};
|
|
141
153
|
const quotas = [];
|
|
142
154
|
const features = [];
|
|
143
155
|
for (const rc of rateCards) {
|
|
@@ -157,7 +169,7 @@ const categorizeRateCards = (rateCards, currency, units) => {
|
|
|
157
169
|
key: rc.featureKey ?? rc.key,
|
|
158
170
|
name: rc.name,
|
|
159
171
|
limit: et.issueAfterReset,
|
|
160
|
-
period:
|
|
172
|
+
period: rc.billingCadence ? formatDuration(rc.billingCadence) : planBillingCadence ? formatDuration(planBillingCadence) : "month",
|
|
161
173
|
overagePrice
|
|
162
174
|
});
|
|
163
175
|
} else if (et.type === "boolean") features.push({
|
|
@@ -267,26 +279,45 @@ const queryClient = new QueryClient({ defaultOptions: {
|
|
|
267
279
|
}
|
|
268
280
|
}
|
|
269
281
|
} });
|
|
270
|
-
const ZuploMonetizationWrapper = () => {
|
|
271
|
-
|
|
272
|
-
|
|
282
|
+
const ZuploMonetizationWrapper = ({ options = {} }) => /* @__PURE__ */ jsx(QueryClientProvider, {
|
|
283
|
+
client: queryClient,
|
|
284
|
+
children: /* @__PURE__ */ jsx(MonetizationContext, {
|
|
285
|
+
value: options,
|
|
273
286
|
children: /* @__PURE__ */ jsx(ClientOnly, { children: /* @__PURE__ */ jsx(Outlet, {}) })
|
|
274
|
-
})
|
|
275
|
-
};
|
|
287
|
+
})
|
|
288
|
+
});
|
|
276
289
|
|
|
277
290
|
//#endregion
|
|
278
291
|
//#region src/pages/CheckoutConfirmPage.tsx
|
|
292
|
+
const getPlanFromPurchaseDetails = (response) => {
|
|
293
|
+
return "plan" in response ? response.plan : response;
|
|
294
|
+
};
|
|
295
|
+
const getTaxAmountFromPurchaseDetails = (response) => {
|
|
296
|
+
const taxAmount = response?.tax?.amount;
|
|
297
|
+
const numericAmount = typeof taxAmount === "number" ? taxAmount : Number.parseFloat(taxAmount ?? "");
|
|
298
|
+
if (!Number.isFinite(numericAmount)) return;
|
|
299
|
+
return numericAmount;
|
|
300
|
+
};
|
|
279
301
|
const CheckoutConfirmPage = () => {
|
|
280
302
|
const [search] = useSearchParams();
|
|
281
303
|
const planId = search.get("planId");
|
|
282
304
|
const zudoku = useZudoku();
|
|
283
305
|
const deploymentName = useDeploymentName();
|
|
284
306
|
const navigate = useNavigate();
|
|
285
|
-
const {
|
|
286
|
-
const selectedPlan = plans?.items?.find((plan) => plan.id === planId);
|
|
307
|
+
const { pricing } = useMonetizationConfig();
|
|
287
308
|
if (!planId) throw new Error("Parameter `planId` missing");
|
|
309
|
+
const purchaseDetails = useSuspenseQuery({
|
|
310
|
+
queryKey: [`/v3/zudoku-metering/${deploymentName}/plans/${planId}/purchase-details`],
|
|
311
|
+
meta: { context: zudoku }
|
|
312
|
+
});
|
|
313
|
+
const selectedPlan = getPlanFromPurchaseDetails(purchaseDetails.data);
|
|
314
|
+
const taxAmount = getTaxAmountFromPurchaseDetails(purchaseDetails.data);
|
|
288
315
|
const rateCards = selectedPlan?.phases.at(-1)?.rateCards;
|
|
289
|
-
const { quotas, features } = categorizeRateCards(rateCards ?? [],
|
|
316
|
+
const { quotas, features } = categorizeRateCards(rateCards ?? [], {
|
|
317
|
+
currency: selectedPlan?.currency,
|
|
318
|
+
units: pricing?.units,
|
|
319
|
+
planBillingCadence: selectedPlan?.billingCadence
|
|
320
|
+
});
|
|
290
321
|
const price = selectedPlan ? getPriceFromPlan(selectedPlan) : null;
|
|
291
322
|
const billingCycle = selectedPlan?.billingCadence ? formatDuration(selectedPlan.billingCadence) : null;
|
|
292
323
|
const createSubscriptionMutation = useMutation({
|
|
@@ -356,13 +387,24 @@ const CheckoutConfirmPage = () => {
|
|
|
356
387
|
}),
|
|
357
388
|
price && price.monthly > 0 && /* @__PURE__ */ jsxs("div", {
|
|
358
389
|
className: "text-right",
|
|
359
|
-
children: [
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
390
|
+
children: [
|
|
391
|
+
/* @__PURE__ */ jsx("div", {
|
|
392
|
+
className: "text-2xl font-bold",
|
|
393
|
+
children: formatPrice(price.monthly, selectedPlan?.currency)
|
|
394
|
+
}),
|
|
395
|
+
billingCycle && /* @__PURE__ */ jsxs("div", {
|
|
396
|
+
className: "text-sm text-muted-foreground font-normal",
|
|
397
|
+
children: ["Billed ", formatBillingCycle(billingCycle)]
|
|
398
|
+
}),
|
|
399
|
+
taxAmount != null && /* @__PURE__ */ jsxs("div", {
|
|
400
|
+
className: "text-xs text-muted-foreground font-normal mt-1",
|
|
401
|
+
children: [
|
|
402
|
+
"+ ",
|
|
403
|
+
formatPrice(taxAmount, selectedPlan?.currency),
|
|
404
|
+
" VAT"
|
|
405
|
+
]
|
|
406
|
+
})
|
|
407
|
+
]
|
|
366
408
|
}),
|
|
367
409
|
price && price.monthly === 0 && /* @__PURE__ */ jsx("div", {
|
|
368
410
|
className: "text-2xl text-muted-foreground font-bold",
|
|
@@ -392,7 +434,7 @@ const CheckoutConfirmPage = () => {
|
|
|
392
434
|
children: [/* @__PURE__ */ jsx(Button, {
|
|
393
435
|
className: "w-full",
|
|
394
436
|
onClick: () => createSubscriptionMutation.mutate(),
|
|
395
|
-
disabled: createSubscriptionMutation.isPending,
|
|
437
|
+
disabled: createSubscriptionMutation.isPending || !selectedPlan,
|
|
396
438
|
children: createSubscriptionMutation.isPending ? "Processing Payment..." : "Confirm & Subscribe"
|
|
397
439
|
}), /* @__PURE__ */ jsx(Button, {
|
|
398
440
|
variant: "ghost",
|
|
@@ -576,13 +618,27 @@ const ManagePaymentPage = () => {
|
|
|
576
618
|
});
|
|
577
619
|
};
|
|
578
620
|
|
|
621
|
+
//#endregion
|
|
622
|
+
//#region src/hooks/usePlans.ts
|
|
623
|
+
const usePlans = () => {
|
|
624
|
+
const zudoku = useZudoku();
|
|
625
|
+
const auth = useAuth();
|
|
626
|
+
return useSuspenseQuery({
|
|
627
|
+
queryKey: [`/v3/zudoku-metering/${useDeploymentName()}/pricing-page`],
|
|
628
|
+
meta: { context: auth.isAuthenticated ? zudoku : void 0 }
|
|
629
|
+
});
|
|
630
|
+
};
|
|
631
|
+
|
|
579
632
|
//#endregion
|
|
580
633
|
//#region src/pages/pricing/PricingCard.tsx
|
|
581
|
-
const PhaseSection = ({ phase, currency, showName,
|
|
582
|
-
const {
|
|
583
|
-
const
|
|
584
|
-
|
|
585
|
-
|
|
634
|
+
const PhaseSection = ({ phase, currency, showName, billingCadence }) => {
|
|
635
|
+
const { pricing } = useMonetizationConfig();
|
|
636
|
+
const { quotas, features } = categorizeRateCards(phase.rateCards, {
|
|
637
|
+
currency,
|
|
638
|
+
units: pricing?.units,
|
|
639
|
+
planBillingCadence: billingCadence
|
|
640
|
+
});
|
|
641
|
+
if (quotas.length === 0 && features.length === 0) return null;
|
|
586
642
|
return /* @__PURE__ */ jsxs("div", {
|
|
587
643
|
className: "space-y-2",
|
|
588
644
|
children: [
|
|
@@ -597,17 +653,19 @@ const PhaseSection = ({ phase, currency, showName, excludeKeys, units }) => {
|
|
|
597
653
|
]
|
|
598
654
|
})]
|
|
599
655
|
}),
|
|
600
|
-
|
|
601
|
-
|
|
656
|
+
quotas.map((quota) => /* @__PURE__ */ jsx(QuotaItem, { quota }, quota.key)),
|
|
657
|
+
features.map((feature) => /* @__PURE__ */ jsx(FeatureItem, { feature }, feature.key))
|
|
602
658
|
]
|
|
603
659
|
});
|
|
604
660
|
};
|
|
605
|
-
const PricingCard = ({ plan, isPopular = false, isSubscribed = false
|
|
661
|
+
const PricingCard = ({ plan, isPopular = false, isSubscribed = false }) => {
|
|
662
|
+
const { pricing } = useMonetizationConfig();
|
|
606
663
|
if (plan.phases.length === 0) return null;
|
|
607
664
|
const price = getPriceFromPlan(plan);
|
|
608
665
|
const isFree = price.monthly === 0;
|
|
609
666
|
const isCustom = plan.metadata?.isCustom === true;
|
|
610
667
|
const hasMultiplePhases = plan.phases.length > 1;
|
|
668
|
+
const billingInterval = formatDuration(plan.billingCadence);
|
|
611
669
|
return /* @__PURE__ */ jsxs("div", {
|
|
612
670
|
className: cn("relative rounded-lg border p-6 flex flex-col", isPopular && "border-primary border-2"),
|
|
613
671
|
children: [
|
|
@@ -636,10 +694,10 @@ const PricingCard = ({ plan, isPopular = false, isSubscribed = false, showYearly
|
|
|
636
694
|
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
637
695
|
className: "text-3xl font-bold text-card-foreground",
|
|
638
696
|
children: isFree ? "Free" : formatPrice(price.monthly, plan.currency)
|
|
639
|
-
}), !isFree && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */
|
|
697
|
+
}), !isFree && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
|
|
640
698
|
className: "text-muted-foreground text-sm",
|
|
641
|
-
children: "/
|
|
642
|
-
}), showYearlyPrice && /* @__PURE__ */ jsxs("div", {
|
|
699
|
+
children: ["/", billingInterval]
|
|
700
|
+
}), pricing?.showYearlyPrice !== false && price.yearly > 0 && /* @__PURE__ */ jsxs("div", {
|
|
643
701
|
className: "w-full text-sm text-muted-foreground mt-1",
|
|
644
702
|
children: [formatPrice(price.yearly, plan.currency), "/year"]
|
|
645
703
|
})] })] })
|
|
@@ -652,16 +710,12 @@ const PricingCard = ({ plan, isPopular = false, isSubscribed = false, showYearly
|
|
|
652
710
|
}),
|
|
653
711
|
/* @__PURE__ */ jsx("div", {
|
|
654
712
|
className: "space-y-4 mb-6 grow",
|
|
655
|
-
children: plan.phases.map((phase
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
excludeKeys: laterKeys,
|
|
662
|
-
units
|
|
663
|
-
}, phase.key);
|
|
664
|
-
})
|
|
713
|
+
children: plan.phases.map((phase) => /* @__PURE__ */ jsx(PhaseSection, {
|
|
714
|
+
phase,
|
|
715
|
+
currency: plan.currency,
|
|
716
|
+
showName: hasMultiplePhases,
|
|
717
|
+
billingCadence: plan.billingCadence
|
|
718
|
+
}, phase.key))
|
|
665
719
|
}),
|
|
666
720
|
isSubscribed ? /* @__PURE__ */ jsx(Button, {
|
|
667
721
|
variant: isPopular ? "default" : "secondary",
|
|
@@ -684,7 +738,8 @@ const PricingCard = ({ plan, isPopular = false, isSubscribed = false, showYearly
|
|
|
684
738
|
|
|
685
739
|
//#endregion
|
|
686
740
|
//#region src/pages/PricingPage.tsx
|
|
687
|
-
const PricingPage = (
|
|
741
|
+
const PricingPage = () => {
|
|
742
|
+
const { pricing } = useMonetizationConfig();
|
|
688
743
|
const zudoku = useZudoku();
|
|
689
744
|
const deploymentName = useDeploymentName();
|
|
690
745
|
const auth = useAuth();
|
|
@@ -697,28 +752,26 @@ const PricingPage = ({ subtitle = "See our pricing options and choose the one th
|
|
|
697
752
|
return /* @__PURE__ */ jsxs("div", {
|
|
698
753
|
className: "w-full px-4 pt-(--padding-content-top) pb-(--padding-content-bottom)",
|
|
699
754
|
children: [
|
|
700
|
-
/* @__PURE__ */ jsxs(Head, { children: [/* @__PURE__ */ jsx("title", { children: title }), /* @__PURE__ */ jsx("meta", {
|
|
755
|
+
/* @__PURE__ */ jsxs(Head, { children: [/* @__PURE__ */ jsx("title", { children: pricing?.title ?? "Pricing" }), /* @__PURE__ */ jsx("meta", {
|
|
701
756
|
name: "description",
|
|
702
|
-
content: subtitle
|
|
757
|
+
content: pricing?.subtitle ?? "See our pricing options and choose the one that best suits your needs."
|
|
703
758
|
})] }),
|
|
704
759
|
/* @__PURE__ */ jsxs("div", {
|
|
705
760
|
className: "text-center space-y-4 mb-12",
|
|
706
761
|
children: [/* @__PURE__ */ jsx(Heading, {
|
|
707
762
|
level: 1,
|
|
708
763
|
"data-testid": "title",
|
|
709
|
-
children: title
|
|
764
|
+
children: pricing?.title ?? "Pricing"
|
|
710
765
|
}), /* @__PURE__ */ jsx("p", {
|
|
711
766
|
className: "text-muted-foreground",
|
|
712
767
|
"data-testid": "subtitle",
|
|
713
|
-
children: subtitle
|
|
768
|
+
children: pricing?.subtitle ?? "See our pricing options and choose the one that best suits your needs."
|
|
714
769
|
})]
|
|
715
770
|
}),
|
|
716
771
|
/* @__PURE__ */ jsx("div", {
|
|
717
772
|
className: "w-full grid grid-cols-1 sm:grid-cols-[repeat(auto-fit,minmax(300px,max-content))] justify-center gap-6",
|
|
718
773
|
children: pricingTable.items.map((plan) => /* @__PURE__ */ jsx(PricingCard, {
|
|
719
774
|
plan,
|
|
720
|
-
units,
|
|
721
|
-
showYearlyPrice,
|
|
722
775
|
isPopular: plan.metadata?.zuplo_most_popular === "true",
|
|
723
776
|
isSubscribed: subscriptions.items.some((subscription) => ["active", "canceled"].includes(subscription.status))
|
|
724
777
|
}, plan.id))
|
|
@@ -738,11 +791,16 @@ const SubscriptionChangeConfirmPage = () => {
|
|
|
738
791
|
const deploymentName = useDeploymentName();
|
|
739
792
|
const navigate = useNavigate();
|
|
740
793
|
const { data: plans } = usePlans();
|
|
794
|
+
const { pricing } = useMonetizationConfig();
|
|
741
795
|
const selectedPlan = plans?.items?.find((plan) => plan.id === planId);
|
|
742
796
|
if (!planId) throw new Error("Parameter `planId` missing");
|
|
743
797
|
if (!subscriptionId) throw new Error("Parameter `subscriptionId` missing");
|
|
744
798
|
const rateCards = selectedPlan?.phases.at(-1)?.rateCards;
|
|
745
|
-
const { quotas, features } = categorizeRateCards(rateCards ?? [],
|
|
799
|
+
const { quotas, features } = categorizeRateCards(rateCards ?? [], {
|
|
800
|
+
currency: selectedPlan?.currency,
|
|
801
|
+
units: pricing?.units,
|
|
802
|
+
planBillingCadence: selectedPlan?.billingCadence
|
|
803
|
+
});
|
|
746
804
|
const price = selectedPlan ? getPriceFromPlan(selectedPlan) : null;
|
|
747
805
|
const billingCycle = selectedPlan?.billingCadence ? formatDuration(selectedPlan.billingCadence) : null;
|
|
748
806
|
const changeMutation = useMutation({
|
|
@@ -1216,15 +1274,24 @@ const CancelSubscriptionDialog = ({ open, onOpenChange, planName, subscriptionId
|
|
|
1216
1274
|
children: [
|
|
1217
1275
|
/* @__PURE__ */ jsx(CalendarIcon, { className: "size-4" }),
|
|
1218
1276
|
/* @__PURE__ */ jsx(AlertTitle, { children: "Your plan will be canceled at the end of your billing cycle." }),
|
|
1219
|
-
/* @__PURE__ */ jsxs(AlertDescription, { children: [
|
|
1277
|
+
/* @__PURE__ */ jsxs(AlertDescription, { children: [
|
|
1278
|
+
"You'll retain access until ",
|
|
1279
|
+
formatDate$1(billingPeriodEnd),
|
|
1280
|
+
". After your billing period ends, this plan will not renew and you would need to subscribe again to continue."
|
|
1281
|
+
] })
|
|
1220
1282
|
]
|
|
1221
1283
|
}),
|
|
1222
1284
|
/* @__PURE__ */ jsxs(Alert, {
|
|
1223
|
-
variant: "
|
|
1285
|
+
variant: "info",
|
|
1224
1286
|
children: [
|
|
1225
|
-
/* @__PURE__ */ jsx(
|
|
1226
|
-
/* @__PURE__ */ jsx(AlertTitle, { children: "
|
|
1227
|
-
/* @__PURE__ */
|
|
1287
|
+
/* @__PURE__ */ jsx(InfoIcon, { className: "size-4" }),
|
|
1288
|
+
/* @__PURE__ */ jsx(AlertTitle, { children: "You can still resume before then" }),
|
|
1289
|
+
/* @__PURE__ */ jsxs(AlertDescription, { children: [
|
|
1290
|
+
"If you change your mind you have until",
|
|
1291
|
+
" ",
|
|
1292
|
+
formatDate$1(billingPeriodEnd),
|
|
1293
|
+
" to remove this cancellation from Manage subscription."
|
|
1294
|
+
] })
|
|
1228
1295
|
]
|
|
1229
1296
|
}),
|
|
1230
1297
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -1277,17 +1344,107 @@ const CancelSubscriptionDialog = ({ open, onOpenChange, planName, subscriptionId
|
|
|
1277
1344
|
});
|
|
1278
1345
|
};
|
|
1279
1346
|
|
|
1347
|
+
//#endregion
|
|
1348
|
+
//#region src/pages/subscriptions/RestoreSubscriptionDialog.tsx
|
|
1349
|
+
const RestoreSubscriptionDialog = ({ open, onOpenChange, planName, subscriptionId, billingPeriodEnd }) => {
|
|
1350
|
+
const deploymentName = useDeploymentName();
|
|
1351
|
+
const context = useZudoku();
|
|
1352
|
+
const queryClient = useQueryClient();
|
|
1353
|
+
const restoreSubscriptionMutation = useMutation({
|
|
1354
|
+
mutationKey: [`/v3/zudoku-metering/${deploymentName}/subscriptions/${subscriptionId}/restore`],
|
|
1355
|
+
meta: {
|
|
1356
|
+
context,
|
|
1357
|
+
request: { method: "POST" }
|
|
1358
|
+
},
|
|
1359
|
+
onSuccess: async () => {
|
|
1360
|
+
await queryClient.invalidateQueries();
|
|
1361
|
+
onOpenChange(false);
|
|
1362
|
+
}
|
|
1363
|
+
});
|
|
1364
|
+
useEffect(() => {
|
|
1365
|
+
if (open) restoreSubscriptionMutation.reset();
|
|
1366
|
+
}, [open, restoreSubscriptionMutation]);
|
|
1367
|
+
const handleOpenChange = (nextOpen) => {
|
|
1368
|
+
if (!nextOpen) restoreSubscriptionMutation.reset();
|
|
1369
|
+
onOpenChange(nextOpen);
|
|
1370
|
+
};
|
|
1371
|
+
return /* @__PURE__ */ jsx(Dialog, {
|
|
1372
|
+
open,
|
|
1373
|
+
onOpenChange: handleOpenChange,
|
|
1374
|
+
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
1375
|
+
className: "sm:max-w-md",
|
|
1376
|
+
children: [
|
|
1377
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Resume subscription" }), /* @__PURE__ */ jsxs(DialogDescription, { children: [
|
|
1378
|
+
"You scheduled ",
|
|
1379
|
+
/* @__PURE__ */ jsx("span", {
|
|
1380
|
+
className: "font-medium",
|
|
1381
|
+
children: planName
|
|
1382
|
+
}),
|
|
1383
|
+
" to end. You can still change your mind before the current billing period ends."
|
|
1384
|
+
] })] }),
|
|
1385
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1386
|
+
className: "space-y-4 mt-4",
|
|
1387
|
+
children: [/* @__PURE__ */ jsxs(Alert, {
|
|
1388
|
+
variant: "info",
|
|
1389
|
+
children: [
|
|
1390
|
+
/* @__PURE__ */ jsx(CalendarIcon, { className: "size-4" }),
|
|
1391
|
+
/* @__PURE__ */ jsx(AlertTitle, { children: "What happens if you resume" }),
|
|
1392
|
+
/* @__PURE__ */ jsxs(AlertDescription, {
|
|
1393
|
+
className: "space-y-2",
|
|
1394
|
+
children: [/* @__PURE__ */ jsxs("p", { children: [
|
|
1395
|
+
"Your access stays in place until ",
|
|
1396
|
+
formatDate$1(billingPeriodEnd),
|
|
1397
|
+
" ",
|
|
1398
|
+
"either way."
|
|
1399
|
+
] }), /* @__PURE__ */ jsx("p", { children: "Confirming will remove the pending cancellation. Your subscription will remain active and continue to renew on your normal billing schedule, and charges will apply as usual." })]
|
|
1400
|
+
})
|
|
1401
|
+
]
|
|
1402
|
+
}), restoreSubscriptionMutation.isError && /* @__PURE__ */ jsxs(Alert, {
|
|
1403
|
+
variant: "destructive",
|
|
1404
|
+
children: [
|
|
1405
|
+
/* @__PURE__ */ jsx(CircleSlashIcon, { className: "size-4" }),
|
|
1406
|
+
/* @__PURE__ */ jsx(AlertTitle, { children: "Could not resume subscription" }),
|
|
1407
|
+
/* @__PURE__ */ jsx(AlertDescription, { children: restoreSubscriptionMutation.error.message })
|
|
1408
|
+
]
|
|
1409
|
+
})]
|
|
1410
|
+
}),
|
|
1411
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1412
|
+
className: "flex flex-col gap-2",
|
|
1413
|
+
children: [/* @__PURE__ */ jsx(ActionButton, {
|
|
1414
|
+
disabled: restoreSubscriptionMutation.isPending,
|
|
1415
|
+
isPending: restoreSubscriptionMutation.isPending || restoreSubscriptionMutation.isSuccess,
|
|
1416
|
+
onClick: () => restoreSubscriptionMutation.mutate(),
|
|
1417
|
+
children: "Resume subscription"
|
|
1418
|
+
}), /* @__PURE__ */ jsx(Button$1, {
|
|
1419
|
+
variant: "ghost",
|
|
1420
|
+
onClick: () => handleOpenChange(false),
|
|
1421
|
+
children: "Keep cancellation"
|
|
1422
|
+
})]
|
|
1423
|
+
})
|
|
1424
|
+
]
|
|
1425
|
+
})
|
|
1426
|
+
});
|
|
1427
|
+
};
|
|
1428
|
+
|
|
1280
1429
|
//#endregion
|
|
1281
1430
|
//#region src/pages/subscriptions/SwitchPlanModal.tsx
|
|
1282
|
-
const comparePlans = (currentPlan, targetPlan, currentIndex, targetIndex) => {
|
|
1431
|
+
const comparePlans = (currentPlan, targetPlan, currentIndex, targetIndex, units) => {
|
|
1283
1432
|
const isUpgrade = targetIndex > currentIndex;
|
|
1284
1433
|
const currentPhase = currentPlan?.phases.at(-1);
|
|
1285
1434
|
const targetPhase = targetPlan.phases.at(-1);
|
|
1286
|
-
const { quotas: currentQuotas, features: currentFeatures } = currentPhase ? categorizeRateCards(currentPhase.rateCards,
|
|
1435
|
+
const { quotas: currentQuotas, features: currentFeatures } = currentPhase ? categorizeRateCards(currentPhase.rateCards, {
|
|
1436
|
+
currency: currentPlan?.currency,
|
|
1437
|
+
units,
|
|
1438
|
+
planBillingCadence: currentPlan?.billingCadence
|
|
1439
|
+
}) : {
|
|
1287
1440
|
quotas: [],
|
|
1288
1441
|
features: []
|
|
1289
1442
|
};
|
|
1290
|
-
const { quotas: targetQuotas, features: targetFeatures } = targetPhase ? categorizeRateCards(targetPhase.rateCards,
|
|
1443
|
+
const { quotas: targetQuotas, features: targetFeatures } = targetPhase ? categorizeRateCards(targetPhase.rateCards, {
|
|
1444
|
+
currency: targetPlan.currency,
|
|
1445
|
+
units,
|
|
1446
|
+
planBillingCadence: targetPlan.billingCadence
|
|
1447
|
+
}) : {
|
|
1291
1448
|
quotas: [],
|
|
1292
1449
|
features: []
|
|
1293
1450
|
};
|
|
@@ -1394,7 +1551,11 @@ const PlanComparisonItem = ({ comparison, subscriptionId, mode, onRequestChange
|
|
|
1394
1551
|
children: "Free"
|
|
1395
1552
|
}) : /* @__PURE__ */ jsxs("span", {
|
|
1396
1553
|
className: "text-primary font-medium text-lg",
|
|
1397
|
-
children: [
|
|
1554
|
+
children: [
|
|
1555
|
+
formatPrice(displayPrice, comparison.plan.currency),
|
|
1556
|
+
"/",
|
|
1557
|
+
formatDuration(comparison.plan.billingCadence)
|
|
1558
|
+
]
|
|
1398
1559
|
})]
|
|
1399
1560
|
}), isCustom ? /* @__PURE__ */ jsx(Button$1, {
|
|
1400
1561
|
variant: "default",
|
|
@@ -1558,6 +1719,7 @@ const SwitchPlanModal = ({ subscription, children }) => {
|
|
|
1558
1719
|
const [open, setOpen] = useState(false);
|
|
1559
1720
|
const { data: plansData } = usePlans();
|
|
1560
1721
|
const [switchTo, setSwitchTo] = useState(null);
|
|
1722
|
+
const { pricing } = useMonetizationConfig();
|
|
1561
1723
|
const currentPlan = plansData?.items.find((p) => p.id === subscription.plan.id);
|
|
1562
1724
|
const { upgrades, downgrades, privatePlans } = useMemo(() => {
|
|
1563
1725
|
if (!plansData?.items || !currentPlan) return {
|
|
@@ -1568,14 +1730,18 @@ const SwitchPlanModal = ({ subscription, children }) => {
|
|
|
1568
1730
|
const isPrivatePlan = (plan) => plan.metadata?.zuplo_private_plan === "true";
|
|
1569
1731
|
const currentIndex = plansData.items.findIndex((p) => p.id === currentPlan.id);
|
|
1570
1732
|
const allComparisons = plansData.items.filter((p) => p.id !== currentPlan.id).map((plan) => {
|
|
1571
|
-
return comparePlans(currentPlan, plan, currentIndex, plansData.items.indexOf(plan));
|
|
1733
|
+
return comparePlans(currentPlan, plan, currentIndex, plansData.items.indexOf(plan), pricing?.units);
|
|
1572
1734
|
});
|
|
1573
1735
|
return {
|
|
1574
1736
|
upgrades: allComparisons.filter((c) => c.isUpgrade && !isPrivatePlan(c.plan)),
|
|
1575
1737
|
downgrades: allComparisons.filter((c) => !c.isUpgrade && !isPrivatePlan(c.plan)),
|
|
1576
1738
|
privatePlans: allComparisons.filter((c) => isPrivatePlan(c.plan))
|
|
1577
1739
|
};
|
|
1578
|
-
}, [
|
|
1740
|
+
}, [
|
|
1741
|
+
plansData?.items,
|
|
1742
|
+
currentPlan,
|
|
1743
|
+
pricing?.units
|
|
1744
|
+
]);
|
|
1579
1745
|
return /* @__PURE__ */ jsxs(Fragment, { children: [switchTo !== null && /* @__PURE__ */ jsx(ConfirmSwitchAlert, {
|
|
1580
1746
|
switchTo,
|
|
1581
1747
|
onRequestClose: () => setSwitchTo(null)
|
|
@@ -1680,81 +1846,92 @@ const SwitchPlanModal = ({ subscription, children }) => {
|
|
|
1680
1846
|
//#region src/pages/subscriptions/ManageSubscription.tsx
|
|
1681
1847
|
const ManageSubscription = ({ subscription, planName }) => {
|
|
1682
1848
|
const [cancelDialogOpen, setCancelDialogOpen] = useState(false);
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
})
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1849
|
+
const [restoreDialogOpen, setRestoreDialogOpen] = useState(false);
|
|
1850
|
+
const billingPeriodEnd = subscription.alignment.currentAlignedBillingPeriod.to;
|
|
1851
|
+
const canResumeCanceledSubscription = subscription.status === "canceled" && new Date(billingPeriodEnd) > /* @__PURE__ */ new Date();
|
|
1852
|
+
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
1853
|
+
/* @__PURE__ */ jsx(CancelSubscriptionDialog, {
|
|
1854
|
+
open: cancelDialogOpen,
|
|
1855
|
+
onOpenChange: setCancelDialogOpen,
|
|
1856
|
+
planName,
|
|
1857
|
+
subscriptionId: subscription.id,
|
|
1858
|
+
billingPeriodEnd
|
|
1859
|
+
}),
|
|
1860
|
+
/* @__PURE__ */ jsx(RestoreSubscriptionDialog, {
|
|
1861
|
+
open: restoreDialogOpen,
|
|
1862
|
+
onOpenChange: setRestoreDialogOpen,
|
|
1863
|
+
planName,
|
|
1864
|
+
subscriptionId: subscription.id,
|
|
1865
|
+
billingPeriodEnd
|
|
1866
|
+
}),
|
|
1867
|
+
/* @__PURE__ */ jsx(CardContent, {
|
|
1868
|
+
className: "p-6",
|
|
1869
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1870
|
+
className: "flex gap-4",
|
|
1871
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1872
|
+
className: "flex items-center justify-center w-12 h-12 rounded-full bg-primary/10 shrink-0",
|
|
1873
|
+
children: /* @__PURE__ */ jsx(Settings, { className: "w-6 h-6 text-primary" })
|
|
1874
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1875
|
+
className: "flex-1",
|
|
1876
|
+
id: "manage",
|
|
1877
|
+
children: [
|
|
1878
|
+
/* @__PURE__ */ jsx("h2", {
|
|
1879
|
+
className: "text-lg font-semibold text-foreground mb-1",
|
|
1880
|
+
children: "Manage Subscription"
|
|
1881
|
+
}),
|
|
1882
|
+
/* @__PURE__ */ jsx("p", {
|
|
1883
|
+
className: "text-sm text-muted-foreground mb-4",
|
|
1884
|
+
children: "Switch to a different plan or cancel your current subscription."
|
|
1885
|
+
}),
|
|
1886
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1887
|
+
className: "flex flex-wrap gap-3",
|
|
1888
|
+
children: [
|
|
1889
|
+
subscription.status === "canceled" && /* @__PURE__ */ jsx(Button$1, {
|
|
1890
|
+
variant: "outline",
|
|
1891
|
+
size: "sm",
|
|
1724
1892
|
asChild: true,
|
|
1725
|
-
children: /* @__PURE__ */
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
children:
|
|
1742
|
-
|
|
1743
|
-
|
|
1893
|
+
children: /* @__PURE__ */ jsxs(Link, {
|
|
1894
|
+
to: "/pricing",
|
|
1895
|
+
children: [/* @__PURE__ */ jsx(RefreshCcw, { className: "w-4 h-4 mr-2" }), "New subscription"]
|
|
1896
|
+
})
|
|
1897
|
+
}),
|
|
1898
|
+
subscription.status === "active" && /* @__PURE__ */ jsx(SwitchPlanModal, { subscription }),
|
|
1899
|
+
subscription.status === "active" && /* @__PURE__ */ jsx(Button$1, {
|
|
1900
|
+
variant: "outline",
|
|
1901
|
+
size: "sm",
|
|
1902
|
+
onClick: () => setCancelDialogOpen(true),
|
|
1903
|
+
children: "Cancel subscription"
|
|
1904
|
+
}),
|
|
1905
|
+
canResumeCanceledSubscription && /* @__PURE__ */ jsx(Button$1, {
|
|
1906
|
+
variant: "outline",
|
|
1907
|
+
size: "sm",
|
|
1908
|
+
onClick: () => setRestoreDialogOpen(true),
|
|
1909
|
+
children: "Resume subscription"
|
|
1910
|
+
}),
|
|
1911
|
+
/* @__PURE__ */ jsx(Button$1, {
|
|
1912
|
+
asChild: true,
|
|
1913
|
+
size: "sm",
|
|
1914
|
+
variant: "secondary",
|
|
1915
|
+
children: /* @__PURE__ */ jsx(Link, {
|
|
1916
|
+
to: "/manage-payment",
|
|
1917
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1918
|
+
className: "flex items-center gap-2",
|
|
1919
|
+
children: [/* @__PURE__ */ jsx(CreditCardIcon, {}), "Manage payment details"]
|
|
1920
|
+
})
|
|
1744
1921
|
})
|
|
1745
1922
|
})
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
]
|
|
1755
|
-
})
|
|
1923
|
+
]
|
|
1924
|
+
}),
|
|
1925
|
+
/* @__PURE__ */ jsx(Separator, { className: "my-4" }),
|
|
1926
|
+
/* @__PURE__ */ jsx("span", {
|
|
1927
|
+
className: "text-sm text-muted-foreground",
|
|
1928
|
+
children: "Your payment is securely managed by Stripe."
|
|
1929
|
+
})
|
|
1930
|
+
]
|
|
1931
|
+
})]
|
|
1932
|
+
})
|
|
1756
1933
|
})
|
|
1757
|
-
|
|
1934
|
+
] });
|
|
1758
1935
|
};
|
|
1759
1936
|
|
|
1760
1937
|
//#endregion
|
|
@@ -1763,6 +1940,8 @@ const isMeteredEntitlement = (entitlement) => {
|
|
|
1763
1940
|
return "balance" in entitlement;
|
|
1764
1941
|
};
|
|
1765
1942
|
const UsageItem = ({ meter, item, subscription }) => {
|
|
1943
|
+
const cadence = item?.billingCadence ?? subscription?.billingCadence;
|
|
1944
|
+
const billingPeriod = cadence ? formatDurationAdjective(cadence) : "monthly";
|
|
1766
1945
|
const isSoftLimit = item?.included?.entitlement?.isSoftLimit ?? true;
|
|
1767
1946
|
const rate = (item?.price?.tiers?.find((t) => !t.upToAmount) ?? item?.price?.tiers?.at(-1))?.unitPrice?.amount;
|
|
1768
1947
|
const hasOverage = meter.overage > 0;
|
|
@@ -1777,7 +1956,11 @@ const UsageItem = ({ meter, item, subscription }) => {
|
|
|
1777
1956
|
className: "mb-4",
|
|
1778
1957
|
children: [
|
|
1779
1958
|
/* @__PURE__ */ jsx(AlertTriangleIcon, { className: "size-4 text-red-600 shrink-0" }),
|
|
1780
|
-
/* @__PURE__ */
|
|
1959
|
+
/* @__PURE__ */ jsxs(AlertTitle, { children: [
|
|
1960
|
+
"You've exceeded your ",
|
|
1961
|
+
billingPeriod,
|
|
1962
|
+
" quota"
|
|
1963
|
+
] }),
|
|
1781
1964
|
/* @__PURE__ */ jsxs(AlertDescription, { children: [
|
|
1782
1965
|
"Additional usage is being charged at the overage rate",
|
|
1783
1966
|
rate ? ` ($${Number(rate).toFixed(2)}/call)` : "",
|
|
@@ -1798,7 +1981,11 @@ const UsageItem = ({ meter, item, subscription }) => {
|
|
|
1798
1981
|
className: "mb-4",
|
|
1799
1982
|
children: [
|
|
1800
1983
|
/* @__PURE__ */ jsx(AlertTriangleIcon, { className: "size-4 text-red-600 shrink-0" }),
|
|
1801
|
-
/* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsxs(AlertTitle, { children: [
|
|
1985
|
+
"You've reached your ",
|
|
1986
|
+
billingPeriod,
|
|
1987
|
+
" limit"
|
|
1988
|
+
] }),
|
|
1802
1989
|
/* @__PURE__ */ jsx(AlertDescription, { children: "Requests beyond your quota are blocked. Upgrade to a higher plan for more usage." }),
|
|
1803
1990
|
subscription && /* @__PURE__ */ jsx(AlertAction, { children: /* @__PURE__ */ jsx(SwitchPlanModal, {
|
|
1804
1991
|
subscription,
|
|
@@ -1848,7 +2035,7 @@ const UsageItem = ({ meter, item, subscription }) => {
|
|
|
1848
2035
|
}),
|
|
1849
2036
|
/* @__PURE__ */ jsxs("p", {
|
|
1850
2037
|
className: "text-xs text-muted-foreground",
|
|
1851
|
-
children: [meter.balance.toLocaleString(), " remaining this
|
|
2038
|
+
children: [meter.balance.toLocaleString(), " remaining this billing period"]
|
|
1852
2039
|
})
|
|
1853
2040
|
]
|
|
1854
2041
|
})]
|
|
@@ -2071,7 +2258,7 @@ const SubscriptionsPage = () => {
|
|
|
2071
2258
|
//#endregion
|
|
2072
2259
|
//#region src/ZuploMonetizationPlugin.tsx
|
|
2073
2260
|
const PRICING_PATH = "/pricing";
|
|
2074
|
-
const zuploMonetizationPlugin = createPlugin((options) => ({
|
|
2261
|
+
const zuploMonetizationPlugin = createPlugin((options = {}) => ({
|
|
2075
2262
|
transformConfig: ({ config, merge }) => merge({
|
|
2076
2263
|
apiKeys: { enabled: false },
|
|
2077
2264
|
header: { navigation: [...config.header?.navigation ?? [], {
|
|
@@ -2107,7 +2294,7 @@ const zuploMonetizationPlugin = createPlugin((options) => ({
|
|
|
2107
2294
|
}],
|
|
2108
2295
|
getRoutes: () => {
|
|
2109
2296
|
return [{
|
|
2110
|
-
|
|
2297
|
+
element: /* @__PURE__ */ jsx(ZuploMonetizationWrapper, { options }),
|
|
2111
2298
|
handle: { layout: "none" },
|
|
2112
2299
|
children: [
|
|
2113
2300
|
{
|
|
@@ -2129,12 +2316,7 @@ const zuploMonetizationPlugin = createPlugin((options) => ({
|
|
|
2129
2316
|
{
|
|
2130
2317
|
path: PRICING_PATH,
|
|
2131
2318
|
handle: { layout: "default" },
|
|
2132
|
-
element: /* @__PURE__ */ jsx(PricingPage, {
|
|
2133
|
-
subtitle: options?.pricing?.subtitle,
|
|
2134
|
-
title: options?.pricing?.title,
|
|
2135
|
-
units: options?.pricing?.units,
|
|
2136
|
-
showYearlyPrice: options?.pricing?.showYearlyPrice
|
|
2137
|
-
})
|
|
2319
|
+
element: /* @__PURE__ */ jsx(PricingPage, {})
|
|
2138
2320
|
},
|
|
2139
2321
|
{
|
|
2140
2322
|
handle: { layout: "default" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zuplo/zudoku-plugin-monetization",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.27",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/zuplo/zudoku",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"react": "19.2.4",
|
|
32
32
|
"react-dom": "19.2.4",
|
|
33
33
|
"tsdown": "0.20.3",
|
|
34
|
-
"zudoku": "0.
|
|
34
|
+
"zudoku": "0.72.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": ">=19.2.0",
|