// Langfuse Cloud only import { useState } from "react"; import Link from "next/link"; import { useRouter } from "next/router"; import { nanoid } from "nanoid"; import { Button } from "@/src/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogBody, } from "@/src/components/ui/dialog"; import { toast } from "sonner"; // planLabels used inside StripeSwitchPlanButton import { stripeProducts, isUpgrade, } from "@/src/ee/features/billing/utils/stripeCatalogue"; import { ActionButton } from "@/src/components/ActionButton"; import { usePostHogClientCapture } from "@/src/features/posthog-analytics/usePostHogClientCapture"; import { useBillingInformation } from "@/src/ee/features/billing/components/useBillingInformation"; import { api } from "@/src/utils/api"; import { StripeCancellationButton } from "./StripeCancellationButton"; import { StripeSwitchPlanButton } from "./StripeSwitchPlanButton"; import { StripeKeepPlanButton } from "./StripeKeepPlanButton"; export const BillingSwitchPlanDialog = ({ disabled = false, }: { disabled?: boolean; }) => { const [processingPlanId, setProcessingPlanId] = useState(null); const [_opId, setOpId] = useState(null); const router = useRouter(); const { organization, cancellation, scheduledPlanSwitch, isLegacySubscription, hasValidPaymentMethod, } = useBillingInformation(); const capture = usePostHogClientCapture(); const mutCreateCheckoutSession = api.cloudBilling.createStripeCheckoutSession.useMutation({ onSuccess: (url) => { router.push(url); setProcessingPlanId(null); setOpId(null); }, onError: () => { setProcessingPlanId(null); setOpId(null); toast.error("Failed to start checkout session"); }, }); return ( { if (open) { capture("project_settings:pricing_dialog_opened"); } }} >
Plans Comparison of plans ↗
{stripeProducts .filter((product) => Boolean(product.checkout)) .map((product) => { const currentProductId = organization?.cloudConfig?.stripe?.activeProductId; const isThisUpgrade = currentProductId ? isUpgrade(currentProductId, product.stripeProductId) : true; const isCurrentPlan = currentProductId === product.stripeProductId; return (
{/* Labels above plan title */}
{isCurrentPlan && Current Plan} {scheduledPlanSwitch && scheduledPlanSwitch.newPlanId === product.stripeProductId && ( Starts next period )} {scheduledPlanSwitch && organization?.cloudConfig?.stripe?.activeProductId === product.stripeProductId && ( (Until next period) )} {!scheduledPlanSwitch && cancellation?.isCancelled && organization?.cloudConfig?.stripe?.activeProductId === product.stripeProductId && ( (Until next period) )}

{product.checkout?.title}

{product.checkout?.price}
+ {product.checkout?.usagePrice},{" "} usage calculator ↗
{product.checkout?.description}
Main features:
    {product.checkout?.mainFeatures.map( (feature, index) => (
  • {feature}
  • ), )}
Learn more about plan → {/* The default behavior the user is on a paid plan.*/} {organization?.cloudConfig?.stripe?.activeProductId ? ( // Change plan view
{isCurrentPlan && ( <> {/* Reactivate button when cancellation is scheduled on current plan */} {cancellation?.isCancelled && ( )} {!cancellation?.isCancelled && scheduledPlanSwitch && ( )} {!cancellation?.isCancelled && !scheduledPlanSwitch && ( )} )} {/* A downgrade is scheduled and this is the new plan */} {!isCurrentPlan && scheduledPlanSwitch && scheduledPlanSwitch.newPlanId === product.stripeProductId && ( )} {/* A downgrade is scheduled and this is not the new plan and not the current plan*/} {!isCurrentPlan && scheduledPlanSwitch && scheduledPlanSwitch.newPlanId !== product.stripeProductId && (hasValidPaymentMethod ? ( ) : ( ))} {/* The default behavior when it is not the current plan and no schedule exists*/} {!isCurrentPlan && !scheduledPlanSwitch && (hasValidPaymentMethod ? ( ) : ( ))}
) : ( // The default behavior when the user is not on a paid plan.
{ if (organization) { setProcessingPlanId(product.stripeProductId); // idempotency key for mutation operations with the stripe api let opId = _opId; if (!opId) { opId = nanoid(); setOpId(opId); } mutCreateCheckoutSession.mutate({ orgId: organization.id, stripeProductId: product.stripeProductId, opId: opId, }); } }} disabled={ organization?.cloudConfig?.stripe ?.activeProductId === product.stripeProductId } className="w-full" loading={processingPlanId === product.stripeProductId} > {product.checkout?.cta ? "Select" : "Select plan"} {/* Optional checkout CTA button for non-paid plan users */} {product.checkout?.cta && ( {product.checkout.cta.label} )}
)}
); })}
); };