import { useState } from 'react'; import { useRecoilValue, useSetRecoilState } from 'recoil'; import { Button, H2Title, IconCalendarEvent, IconCircleX, IconCreditCard, Info, Section, } from 'twenty-ui'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage'; import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { AppPath } from '@/types/AppPath'; import { SettingsPath } from '@/types/SettingsPath'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus'; import { OnboardingStatus, SubscriptionInterval, SubscriptionStatus, useBillingPortalSessionQuery, useUpdateBillingSubscriptionMutation, } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; type SwitchInfo = { newInterval: SubscriptionInterval; to: string; from: string; impact: string; }; const MONTHLY_SWITCH_INFO: SwitchInfo = { newInterval: SubscriptionInterval.Year, to: 'to yearly', from: 'from monthly to yearly', impact: 'You will be charged immediately for the full year.', }; const YEARLY_SWITCH_INFO: SwitchInfo = { newInterval: SubscriptionInterval.Month, to: 'to monthly', from: 'from yearly to monthly', impact: 'Your credit balance will be used to pay the monthly bills.', }; const SWITCH_INFOS = { year: YEARLY_SWITCH_INFO, month: MONTHLY_SWITCH_INFO, }; export const SettingsBilling = () => { const { enqueueSnackBar } = useSnackBar(); const onboardingStatus = useOnboardingStatus(); const subscriptionStatus = useSubscriptionStatus(); const currentWorkspace = useRecoilValue(currentWorkspaceState); const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); const switchingInfo = currentWorkspace?.currentBillingSubscription?.interval === SubscriptionInterval.Year ? SWITCH_INFOS.year : SWITCH_INFOS.month; const [isSwitchingIntervalModalOpen, setIsSwitchingIntervalModalOpen] = useState(false); const [updateBillingSubscription] = useUpdateBillingSubscriptionMutation(); const { data, loading } = useBillingPortalSessionQuery({ variables: { returnUrlPath: '/settings/billing', }, }); const billingPortalButtonDisabled = loading || !isDefined(data) || !isDefined(data.billingPortalSession.url); const switchIntervalButtonDisabled = onboardingStatus !== OnboardingStatus.Completed; const cancelPlanButtonDisabled = billingPortalButtonDisabled || onboardingStatus !== OnboardingStatus.Completed; const displayPaymentFailInfo = subscriptionStatus === SubscriptionStatus.PastDue || subscriptionStatus === SubscriptionStatus.Unpaid; const displaySubscriptionCanceledInfo = subscriptionStatus === SubscriptionStatus.Canceled; const displaySubscribeInfo = onboardingStatus === OnboardingStatus.Completed && !isDefined(subscriptionStatus); const openBillingPortal = () => { if (isDefined(data) && isDefined(data.billingPortalSession.url)) { window.location.replace(data.billingPortalSession.url); } }; const openSwitchingIntervalModal = () => { setIsSwitchingIntervalModalOpen(true); }; const switchInterval = async () => { try { await updateBillingSubscription(); if (isDefined(currentWorkspace?.currentBillingSubscription)) { const newCurrentWorkspace = { ...currentWorkspace, currentBillingSubscription: { ...currentWorkspace?.currentBillingSubscription, interval: switchingInfo.newInterval, }, }; setCurrentWorkspace(newCurrentWorkspace); } enqueueSnackBar(`Subscription has been switched ${switchingInfo.to}`, { variant: SnackBarVariant.Success, }); } catch (error: any) { enqueueSnackBar( `Error while switching subscription ${switchingInfo.to}.`, { variant: SnackBarVariant.Error, }, ); } }; return ( {displayPaymentFailInfo && ( )} {displaySubscriptionCanceledInfo && ( )} {displaySubscribeInfo ? ( ) : ( <>
)}
{`Are you sure that you want to change your billing interval? ${switchingInfo.impact}`} } onConfirmClick={switchInterval} deleteButtonText={`Change ${switchingInfo.to}`} confirmButtonAccent={'blue'} />
); };