Context : Plan choice [on pricing page on website](https://twenty.com/pricing) should redirect you the right plan on app /plan-required page (after sign in), thanks to query parameters and BillingCheckoutSessionState sync. With email verification, an other session starts at CTA click in verification email. Initial BillingCheckoutSessionState is lost and user can't submit to the plan he choose. Solution : Pass a nextPath query parameter in email verification link To test : - Modify .env to add IS_BILLING_ENABLED (+ reset db + sync billing) + IS_EMAIL_VERIFICATION_REQUIRED - Start test from this page http://app.localhost:3001/welcome?billingCheckoutSession={%22plan%22:%22ENTERPRISE%22,%22interval%22:%22Year%22,%22requirePaymentMethod%22:true} - After verification, check you arrive on /plan-required page with Enterprise plan on a yearly interval (default is Pro/monthly). closes https://github.com/twentyhq/twenty/issues/12288
134 lines
4.0 KiB
TypeScript
134 lines
4.0 KiB
TypeScript
import { verifyEmailNextPathState } from '@/app/states/verifyEmailNextPathState';
|
|
import { useIsLogged } from '@/auth/hooks/useIsLogged';
|
|
import { useDefaultHomePagePath } from '@/navigation/hooks/useDefaultHomePagePath';
|
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
|
import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
|
|
import { AppPath } from '@/types/AppPath';
|
|
import { SettingsPath } from '@/types/SettingsPath';
|
|
import { useIsWorkspaceActivationStatusEqualsTo } from '@/workspace/hooks/useIsWorkspaceActivationStatusEqualsTo';
|
|
import { useLocation, useParams } from 'react-router-dom';
|
|
import { useRecoilValue } from 'recoil';
|
|
import { isDefined } from 'twenty-shared/utils';
|
|
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
|
import { OnboardingStatus } from '~/generated/graphql';
|
|
import { isMatchingLocation } from '~/utils/isMatchingLocation';
|
|
|
|
export const usePageChangeEffectNavigateLocation = () => {
|
|
const isLoggedIn = useIsLogged();
|
|
const onboardingStatus = useOnboardingStatus();
|
|
const isWorkspaceSuspended = useIsWorkspaceActivationStatusEqualsTo(
|
|
WorkspaceActivationStatus.SUSPENDED,
|
|
);
|
|
const { defaultHomePagePath } = useDefaultHomePagePath();
|
|
const location = useLocation();
|
|
|
|
const someMatchingLocationOf = (appPaths: AppPath[]): boolean =>
|
|
appPaths.some((appPath) => isMatchingLocation(location, appPath));
|
|
const onGoingUserCreationPaths = [
|
|
AppPath.Invite,
|
|
AppPath.SignInUp,
|
|
AppPath.VerifyEmail,
|
|
AppPath.Verify,
|
|
];
|
|
const onboardingPaths = [
|
|
AppPath.CreateWorkspace,
|
|
AppPath.CreateProfile,
|
|
AppPath.SyncEmails,
|
|
AppPath.InviteTeam,
|
|
AppPath.PlanRequired,
|
|
AppPath.PlanRequiredSuccess,
|
|
];
|
|
|
|
const objectNamePlural = useParams().objectNamePlural ?? '';
|
|
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
|
const objectMetadataItem = objectMetadataItems.find(
|
|
(objectMetadataItem) => objectMetadataItem.namePlural === objectNamePlural,
|
|
);
|
|
const verifyEmailNextPath = useRecoilValue(verifyEmailNextPathState);
|
|
|
|
if (
|
|
!isLoggedIn &&
|
|
!someMatchingLocationOf([
|
|
...onGoingUserCreationPaths,
|
|
AppPath.ResetPassword,
|
|
])
|
|
) {
|
|
return AppPath.SignInUp;
|
|
}
|
|
|
|
if (
|
|
onboardingStatus === OnboardingStatus.PLAN_REQUIRED &&
|
|
!someMatchingLocationOf([AppPath.PlanRequired, AppPath.PlanRequiredSuccess])
|
|
) {
|
|
if (
|
|
isMatchingLocation(location, AppPath.VerifyEmail) &&
|
|
isDefined(verifyEmailNextPath)
|
|
) {
|
|
return verifyEmailNextPath;
|
|
}
|
|
return AppPath.PlanRequired;
|
|
}
|
|
|
|
if (
|
|
isWorkspaceSuspended &&
|
|
!isMatchingLocation(location, AppPath.SettingsCatchAll)
|
|
) {
|
|
return `${AppPath.SettingsCatchAll.replace('/*', '')}/${
|
|
SettingsPath.Billing
|
|
}`;
|
|
}
|
|
|
|
if (
|
|
onboardingStatus === OnboardingStatus.WORKSPACE_ACTIVATION &&
|
|
!someMatchingLocationOf([
|
|
AppPath.CreateWorkspace,
|
|
AppPath.PlanRequiredSuccess,
|
|
])
|
|
) {
|
|
return AppPath.CreateWorkspace;
|
|
}
|
|
|
|
if (
|
|
onboardingStatus === OnboardingStatus.PROFILE_CREATION &&
|
|
!isMatchingLocation(location, AppPath.CreateProfile)
|
|
) {
|
|
return AppPath.CreateProfile;
|
|
}
|
|
|
|
if (
|
|
onboardingStatus === OnboardingStatus.SYNC_EMAIL &&
|
|
!isMatchingLocation(location, AppPath.SyncEmails)
|
|
) {
|
|
return AppPath.SyncEmails;
|
|
}
|
|
|
|
if (
|
|
onboardingStatus === OnboardingStatus.INVITE_TEAM &&
|
|
!isMatchingLocation(location, AppPath.InviteTeam)
|
|
) {
|
|
return AppPath.InviteTeam;
|
|
}
|
|
|
|
if (
|
|
onboardingStatus === OnboardingStatus.COMPLETED &&
|
|
someMatchingLocationOf([...onboardingPaths, ...onGoingUserCreationPaths]) &&
|
|
!isMatchingLocation(location, AppPath.ResetPassword) &&
|
|
isLoggedIn
|
|
) {
|
|
return defaultHomePagePath;
|
|
}
|
|
|
|
if (isMatchingLocation(location, AppPath.Index) && isLoggedIn) {
|
|
return defaultHomePagePath;
|
|
}
|
|
|
|
if (
|
|
isMatchingLocation(location, AppPath.RecordIndexPage) &&
|
|
!isDefined(objectMetadataItem)
|
|
) {
|
|
return AppPath.NotFound;
|
|
}
|
|
|
|
return;
|
|
};
|