Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 52 additions & 22 deletions apps/builder/src/features/billing/components/ChangePlanForm.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { useTranslate } from "@tolgee/react";
import { isDefined } from "@typebot.io/lib/utils";
import { Plan } from "@typebot.io/prisma/enum";
import { useRouter } from "next/router";
import { useState } from "react";
import { TextLink } from "@/components/TextLink";
import { useUser } from "@/features/user/hooks/useUser";
import type { WorkspaceInApp } from "@/features/workspace/WorkspaceProvider";
import { isSelfHostedInstance } from "@/helpers/isSelfHostedInstance";
import { orpc, queryClient } from "@/lib/queryClient";
import { toast } from "@/lib/toast";
import type { PreCheckoutDialogProps } from "./PreCheckoutDialog";
import { PreCheckoutDialog } from "./PreCheckoutDialog";
import { ProPlanPricingCard } from "./ProPlanPricingCard";
import { StarterPlanPricingCard } from "./StarterPlanPricingCard";
import { UpgradeConfirmationDialog } from "./UpgradeConfirmationDialog";
Expand All @@ -26,11 +25,11 @@ export const ChangePlanForm = ({
excludedPlans,
}: Props) => {
const { t } = useTranslate();

const { user } = useUser();
const [preCheckoutPlan, setPreCheckoutPlan] =
useState<PreCheckoutDialogProps["selectedSubscription"]>();
const router = useRouter();
const [pendingUpgrade, setPendingUpgrade] = useState<"STARTER" | "PRO">();
const [pendingCheckoutRedirect, setPendingCheckoutRedirect] = useState<
"STARTER" | "PRO"
>();

const { data, refetch } = useQuery(
orpc.billing.getSubscription.queryOptions({
Expand All @@ -39,6 +38,33 @@ export const ChangePlanForm = ({
}),
);

const { data: pendingUpgradeData, isLoading: isLoadingPendingUpgrade } =
useQuery(
orpc.billing.getSubscriptionPreview.queryOptions({
input: {
workspaceId: workspace.id,
plan: pendingUpgrade!,
},
enabled: isDefined(pendingUpgrade),
}),
);

const { mutate: createCheckoutSession } = useMutation(
orpc.billing.createCheckoutSession.mutationOptions({
onSuccess: (data) => {
router.push(data.checkoutUrl);
},
onError: (error) => {
setPendingCheckoutRedirect(undefined);
toast({
type: "error",
title: t("errorMessage"),
description: error.message,
});
},
}),
);

const { mutateAsync: updateSubscription, status: updateSubscriptionStatus } =
useMutation(
orpc.billing.updateSubscription.mutationOptions({
Expand Down Expand Up @@ -70,8 +96,6 @@ export const ChangePlanForm = ({
);

const handlePayClick = async (plan: "STARTER" | "PRO") => {
if (!user) return;

const newSubscription = {
plan,
workspaceId: workspace.id,
Expand All @@ -87,7 +111,12 @@ export const ChangePlanForm = ({
});
}
} else {
setPreCheckoutPlan(newSubscription);
setPendingCheckoutRedirect(plan);
createCheckoutSession({
workspaceId: workspace.id,
returnUrl: window.location.href,
plan,
});
}
};

Expand Down Expand Up @@ -122,17 +151,10 @@ export const ChangePlanForm = ({

return (
<div className="flex flex-col gap-6">
{!workspace.stripeId && (
<PreCheckoutDialog
selectedSubscription={preCheckoutPlan}
existingEmail={user?.email ?? undefined}
existingCompany={user?.company ?? undefined}
onClose={() => setPreCheckoutPlan(undefined)}
/>
)}
<UpgradeConfirmationDialog
isOpen={!!pendingUpgrade}
workspaceId={workspace.id}
isOpen={isDefined(pendingUpgradeData)}
amountDue={pendingUpgradeData?.amountDue ?? 0}
currency={pendingUpgradeData?.currency ?? "eur"}
targetPlan={pendingUpgrade}
onConfirm={handleConfirmUpgrade}
onClose={() => setPendingUpgrade(undefined)}
Expand All @@ -144,7 +166,11 @@ export const ChangePlanForm = ({
<StarterPlanPricingCard
currentPlan={workspace.plan}
onPayClick={() => handlePayClick(Plan.STARTER)}
isLoading={updateSubscriptionStatus === "pending"}
isLoading={
updateSubscriptionStatus === "pending" ||
pendingCheckoutRedirect === "STARTER" ||
(isLoadingPendingUpgrade && pendingUpgrade === Plan.STARTER)
}
currency={data.subscription?.currency}
/>
)}
Expand All @@ -153,7 +179,11 @@ export const ChangePlanForm = ({
<ProPlanPricingCard
currentPlan={workspace.plan}
onPayClick={() => handlePayClick(Plan.PRO)}
isLoading={updateSubscriptionStatus === "pending"}
isLoading={
updateSubscriptionStatus === "pending" ||
pendingCheckoutRedirect === "PRO" ||
(isLoadingPendingUpgrade && pendingUpgrade === Plan.PRO)
}
currency={data.subscription?.currency}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import { useTranslate } from "@tolgee/react";
import { Plan } from "@typebot.io/prisma/enum";
import { Alert } from "@typebot.io/ui/components/Alert";
import { TriangleAlertIcon } from "@typebot.io/ui/icons/TriangleAlertIcon";
import type { Workspace } from "@typebot.io/workspaces/schemas";
Expand All @@ -23,9 +22,7 @@ export const CurrentSubscriptionSummary = ({ workspace }: Props) => {
}),
);

const isSubscribed =
(workspace.plan === Plan.STARTER || workspace.plan === Plan.PRO) &&
workspace.stripeId;
const hasStripeCustomer = workspace.stripeId;

return (
<div className="flex flex-col gap-4">
Expand All @@ -51,7 +48,7 @@ export const CurrentSubscriptionSummary = ({ workspace }: Props) => {
</Alert.Description>
</Alert.Root>
)}
{isSubscribed && (
{hasStripeCustomer && (
<BillingPortalButton
workspaceId={workspace.id}
variant={
Expand Down
171 changes: 0 additions & 171 deletions apps/builder/src/features/billing/components/PreCheckoutDialog.tsx

This file was deleted.

Loading