@@ -12,7 +12,7 @@ import { Tooltip } from '@/ui/elements/Tooltip';
1212import { handleError } from '@/ui/utils/errorHandler' ;
1313
1414import { DevOnly } from '../../common/DevOnly' ;
15- import { useCheckoutContext , usePaymentMethods } from '../../contexts' ;
15+ import { useCheckoutContext , useEnvironment , usePaymentMethods } from '../../contexts' ;
1616import { Box , Button , Col , descriptors , Flex , Form , localizationKeys , Spinner , Text } from '../../customizables' ;
1717import { ChevronUpDown , InformationCircle } from '../../icons' ;
1818import * as AddPaymentMethod from '../PaymentMethods/AddPaymentMethod' ;
@@ -180,10 +180,13 @@ const useCheckoutMutations = () => {
180180 useTestCard : true ,
181181 } ) ;
182182
183+ const subscribeWithoutPaymentMethod = ( ) => confirmCheckout ( { } ) ;
184+
183185 return {
184186 payWithExistingPaymentMethod,
185187 addPaymentMethodAndPay,
186188 payWithTestCard,
189+ subscribeWithoutPaymentMethod,
187190 } ;
188191} ;
189192
@@ -214,12 +217,19 @@ const CheckoutFormElementsInternal = () => {
214217 const { checkout } = useCheckout ( ) ;
215218 const { id, totals, isImmediatePlanChange, freeTrialEndsAt } = checkout ;
216219 const { data : paymentMethods } = usePaymentMethods ( ) ;
220+ const environment = useEnvironment ( ) ;
217221
218222 const [ paymentMethodSource , setPaymentMethodSource ] = useState < PaymentMethodSource > ( ( ) =>
219223 paymentMethods . length > 0 || __BUILD_DISABLE_RHC__ ? 'existing' : 'new' ,
220224 ) ;
221225
222- const showPaymentMethods = isImmediatePlanChange && ( totals . totalDueNow . amount > 0 || ! ! freeTrialEndsAt ) ;
226+ // Check if payment methods should be shown based on:
227+ // 1. Immediate plan change (not a downgrade)
228+ // 2. Either there's an amount due now OR it's a free trial that requires payment method
229+ const showPaymentMethods =
230+ isImmediatePlanChange &&
231+ ( totals . totalDueNow . amount > 0 ||
232+ ( ! ! freeTrialEndsAt && environment . commerceSettings . billing . freeTrialRequiresPaymentMethod ) ) ;
223233
224234 if ( ! id ) {
225235 return null ;
@@ -254,14 +264,19 @@ const CheckoutFormElementsInternal = () => {
254264 </ >
255265 ) }
256266
257- { paymentMethodSource === 'existing' && (
267+ { showPaymentMethods && paymentMethodSource === 'existing' && (
258268 < ExistingPaymentMethodForm
259269 paymentMethods = { paymentMethods }
260270 totalDueNow = { totals . totalDueNow }
261271 />
262272 ) }
263273
264- { __BUILD_DISABLE_RHC__ ? null : paymentMethodSource === 'new' && < AddPaymentMethodForCheckout /> }
274+ { __BUILD_DISABLE_RHC__
275+ ? null
276+ : showPaymentMethods && paymentMethodSource === 'new' && < AddPaymentMethodForCheckout /> }
277+
278+ { /* Show standalone subscribe button when payment methods are not needed */ }
279+ { ! showPaymentMethods && isImmediatePlanChange && < StandaloneSubscribeButton /> }
265280 </ Col >
266281 ) ;
267282} ;
@@ -374,6 +389,7 @@ const ExistingPaymentMethodForm = withCardStateProvider(
374389 const submitLabel = useSubmitLabel ( ) ;
375390 const { checkout } = useCheckout ( ) ;
376391 const { paymentMethod, isImmediatePlanChange, freeTrialEndsAt } = checkout ;
392+ const environment = useEnvironment ( ) ;
377393
378394 const { payWithExistingPaymentMethod } = useCheckoutMutations ( ) ;
379395 const card = useCardState ( ) ;
@@ -395,7 +411,10 @@ const ExistingPaymentMethodForm = withCardStateProvider(
395411 } ) ;
396412 } , [ paymentMethods ] ) ;
397413
398- const showPaymentMethods = isImmediatePlanChange && ( totalDueNow . amount > 0 || ! ! freeTrialEndsAt ) ;
414+ const showPaymentMethods =
415+ isImmediatePlanChange &&
416+ ( totalDueNow . amount > 0 ||
417+ ( ! ! freeTrialEndsAt && environment . commerceSettings . billing . freeTrialRequiresPaymentMethod ) ) ;
399418
400419 return (
401420 < Form
@@ -462,3 +481,21 @@ const ExistingPaymentMethodForm = withCardStateProvider(
462481 ) ;
463482 } ,
464483) ;
484+
485+ const StandaloneSubscribeButton = withCardStateProvider ( ( ) => {
486+ const { subscribeWithoutPaymentMethod } = useCheckoutMutations ( ) ;
487+ const submitLabel = useSubmitLabel ( ) ;
488+ const card = useCardState ( ) ;
489+
490+ return (
491+ < Button
492+ elementDescriptor = { descriptors . formButtonPrimary }
493+ onClick = { subscribeWithoutPaymentMethod }
494+ sx = { {
495+ width : '100%' ,
496+ } }
497+ isLoading = { card . isLoading }
498+ localizationKey = { submitLabel }
499+ />
500+ ) ;
501+ } ) ;
0 commit comments