From c453ac3a2f491c753d6fbdc3e25ba935c525bb97 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Wed, 23 Sep 2026 15:06:54 -0600 Subject: [PATCH] fix(billing): allow switching billing interval during trial Switching plan mid-trial always forced the monthly price and there was no way to move to annual. Preserve trial_end on the Stripe update so changing the interval does not reset the billing cycle and end the trial early. --- .../settings/billing/show-billing.tsx | 75 +++++++++++++------ apps/dokploy/server/api/routers/stripe.ts | 3 + apps/dokploy/server/utils/billing.ts | 7 ++ 3 files changed, 64 insertions(+), 21 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/billing/show-billing.tsx b/apps/dokploy/components/dashboard/settings/billing/show-billing.tsx index b66a23ca4..fbb85695b 100644 --- a/apps/dokploy/components/dashboard/settings/billing/show-billing.tsx +++ b/apps/dokploy/components/dashboard/settings/billing/show-billing.tsx @@ -111,14 +111,20 @@ export const ShowBilling = () => { const [trialTier, setTrialTier] = useState<"hobby" | "startup" | null>(null); const [switchingTrial, setSwitchingTrial] = useState(false); - const handleSwitchTrialPlan = async (tier: "hobby" | "startup") => { - const planName = tier === "startup" ? "Startup" : "Hobby"; + const handleSwitchTrialPlan = async ( + tier: "hobby" | "startup", + isAnnualPlan: boolean, + label?: string, + ) => { + const planName = + label ?? + `${tier === "startup" ? "Startup" : "Hobby"} ${isAnnualPlan ? "annual" : "monthly"}`; const switchPlan = async () => { await upgradeSubscription({ tier, serverQuantity: tier === "startup" ? STARTUP_SERVERS_INCLUDED : 1, - isAnnual: false, + isAnnual: isAnnualPlan, }); await new Promise((resolve) => setTimeout(resolve, 3000)); await Promise.all([ @@ -133,7 +139,7 @@ export const ShowBilling = () => { await toast .promise(switchPlan(), { loading: `Switching to ${planName}...`, - success: `Your trial is now on the ${planName} plan`, + success: `Your trial is now on ${planName}`, error: (error) => error instanceof Error ? error.message : "Error switching plan", }) @@ -336,6 +342,11 @@ export const ShowBilling = () => { {billingStatus.plan ?? "Trial"} + {billingStatus.plan && ( + + {billingStatus.isAnnual ? "Annual" : "Monthly"} + + )} {billingStatus.isOnTrial @@ -356,23 +367,45 @@ export const ShowBilling = () => {
{billingStatus.isOnTrial && useNewPricing && - billingStatus.plan && ( - + billingStatus.plan && + billingStatus.plan !== "legacy" && ( + <> + + + )}