Fixing Singup sequence FLASHING💥 (#11371)
After investiagting the different options ([see related issue](https://github.com/twentyhq/core-team-issues/issues/660#issuecomment-2766030972)) I decided to add a "Verify Component" and a to build a custom Layout for this route. Reason I cannot use the default one is to have all preloaded once the user changes website and lands on the verify route. Reason I did not modify the DefaultLayout to match our need is that is would require many changes in order to avoid preloading states for our specific usecase. Fixes https://github.com/twentyhq/core-team-issues/issues/660 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
100
packages/twenty-front/src/pages/auth/SignInUpLoading.tsx
Normal file
100
packages/twenty-front/src/pages/auth/SignInUpLoading.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import { workspacePublicDataState } from '@/auth/states/workspacePublicDataState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { Logo } from '@/auth/components/Logo';
|
||||
import { Title } from '@/auth/components/Title';
|
||||
import { DEFAULT_WORKSPACE_NAME } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceName';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useWorkspaceFromInviteHash } from '@/auth/sign-in-up/hooks/useWorkspaceFromInviteHash';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { motion } from 'framer-motion';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Loader } from 'twenty-ui/feedback';
|
||||
import { MainButton } from 'twenty-ui/input';
|
||||
import { PublicWorkspaceDataOutput } from '~/generated/graphql';
|
||||
|
||||
const StyledContentContainer = styled(motion.div)`
|
||||
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
||||
margin-top: ${({ theme }) => theme.spacing(4)};
|
||||
`;
|
||||
|
||||
const StyledForm = styled.form`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
margin-top: ${({ theme }) => theme.spacing(10)};
|
||||
`;
|
||||
|
||||
const StandardContent = ({
|
||||
workspacePublicData,
|
||||
signInUpForm,
|
||||
title,
|
||||
}: {
|
||||
workspacePublicData: PublicWorkspaceDataOutput | null;
|
||||
signInUpForm: JSX.Element | null;
|
||||
title: string;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Logo secondaryLogo={workspacePublicData?.logo} />
|
||||
<Title animate={false}>{title}</Title>
|
||||
{signInUpForm}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const SignInUpLoading = () => {
|
||||
const { t } = useLingui();
|
||||
const workspacePublicData = useRecoilValue(workspacePublicDataState);
|
||||
|
||||
const { workspaceInviteHash, workspace: workspaceFromInviteHash } =
|
||||
useWorkspaceFromInviteHash();
|
||||
|
||||
const title = useMemo(() => {
|
||||
if (isDefined(workspaceInviteHash)) {
|
||||
return `Join ${workspaceFromInviteHash?.displayName ?? ''} team`;
|
||||
}
|
||||
const workspaceName = !isDefined(workspacePublicData?.displayName)
|
||||
? DEFAULT_WORKSPACE_NAME
|
||||
: !isNonEmptyString(workspacePublicData?.displayName)
|
||||
? t`Your Workspace`
|
||||
: workspacePublicData?.displayName;
|
||||
|
||||
return t`Welcome to ${workspaceName}`;
|
||||
}, [
|
||||
workspaceFromInviteHash?.displayName,
|
||||
workspaceInviteHash,
|
||||
workspacePublicData?.displayName,
|
||||
t,
|
||||
]);
|
||||
|
||||
return (
|
||||
<StandardContent
|
||||
workspacePublicData={workspacePublicData}
|
||||
signInUpForm={
|
||||
<>
|
||||
<p style={{ color: 'red', backgroundColor: 'blue' }}>
|
||||
SignInUpLoading
|
||||
</p>
|
||||
<StyledContentContainer>
|
||||
<StyledForm>
|
||||
<MainButton
|
||||
disabled={true}
|
||||
title={t`Continue`}
|
||||
type="submit"
|
||||
variant={'primary'}
|
||||
Icon={() => <Loader />}
|
||||
fullWidth
|
||||
/>
|
||||
</StyledForm>
|
||||
</StyledContentContainer>
|
||||
</>
|
||||
}
|
||||
title={title}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -11,16 +11,16 @@ import { billingState } from '@/client-config/states/billingState';
|
||||
import styled from '@emotion/styled';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Loader } from 'twenty-ui/feedback';
|
||||
import { CardPicker, MainButton } from 'twenty-ui/input';
|
||||
import { ActionLink, CAL_LINK } from 'twenty-ui/navigation';
|
||||
import {
|
||||
BillingPlanKey,
|
||||
BillingPriceLicensedDto,
|
||||
SubscriptionInterval,
|
||||
useBillingBaseProductPricesQuery,
|
||||
} from '~/generated/graphql';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { ActionLink, CAL_LINK } from 'twenty-ui/navigation';
|
||||
import { CardPicker, MainButton } from 'twenty-ui/input';
|
||||
import { Loader } from 'twenty-ui/feedback';
|
||||
|
||||
const StyledSubscriptionContainer = styled.div<{
|
||||
withLongerMarginBottom: boolean;
|
||||
@ -80,6 +80,10 @@ const StyledLinkGroup = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledChooseYourPlanPlaceholder = styled.div`
|
||||
height: 566px;
|
||||
`;
|
||||
|
||||
export const ChooseYourPlan = () => {
|
||||
const billing = useRecoilValue(billingState);
|
||||
const { t } = useLingui();
|
||||
@ -182,82 +186,87 @@ export const ChooseYourPlan = () => {
|
||||
)?.baseProduct.name;
|
||||
|
||||
return (
|
||||
isDefined(baseProductPrice) &&
|
||||
isDefined(billing) && (
|
||||
<>
|
||||
<Title noMarginTop>
|
||||
{hasWithoutCreditCardTrialPeriod
|
||||
? t`Choose your Trial`
|
||||
: t`Get your subscription`}
|
||||
</Title>
|
||||
{hasWithoutCreditCardTrialPeriod ? (
|
||||
<SubTitle>
|
||||
<Trans>Cancel anytime</Trans>
|
||||
</SubTitle>
|
||||
) : (
|
||||
withCreditCardTrialPeriod && (
|
||||
<>
|
||||
{isDefined(baseProductPrice) && isDefined(billing) ? (
|
||||
<>
|
||||
<Title noMarginTop>
|
||||
{hasWithoutCreditCardTrialPeriod
|
||||
? t`Choose your Trial`
|
||||
: t`Get your subscription`}
|
||||
</Title>
|
||||
{hasWithoutCreditCardTrialPeriod ? (
|
||||
<SubTitle>
|
||||
{t`Enjoy a ${withCreditCardTrialPeriodDuration}-days free trial`}
|
||||
<Trans>Cancel anytime</Trans>
|
||||
</SubTitle>
|
||||
)
|
||||
)}
|
||||
<StyledSubscriptionContainer
|
||||
withLongerMarginBottom={!hasWithoutCreditCardTrialPeriod}
|
||||
>
|
||||
<StyledSubscriptionPriceContainer>
|
||||
<SubscriptionPrice
|
||||
type={baseProductPrice.recurringInterval}
|
||||
price={baseProductPrice.unitAmount / 100}
|
||||
/>
|
||||
</StyledSubscriptionPriceContainer>
|
||||
<StyledBenefitsContainer>
|
||||
{benefits.map((benefit) => (
|
||||
<SubscriptionBenefit key={benefit}>{benefit}</SubscriptionBenefit>
|
||||
))}
|
||||
</StyledBenefitsContainer>
|
||||
</StyledSubscriptionContainer>
|
||||
{hasWithoutCreditCardTrialPeriod && (
|
||||
<StyledChooseTrialContainer>
|
||||
{billing.trialPeriods.map((trialPeriod) => (
|
||||
<CardPicker
|
||||
checked={
|
||||
billingCheckoutSession.requirePaymentMethod ===
|
||||
trialPeriod.isCreditCardRequired
|
||||
}
|
||||
handleChange={handleTrialPeriodChange(
|
||||
trialPeriod.isCreditCardRequired,
|
||||
)}
|
||||
key={trialPeriod.duration}
|
||||
>
|
||||
<TrialCard
|
||||
duration={trialPeriod.duration}
|
||||
withCreditCard={trialPeriod.isCreditCardRequired}
|
||||
/>
|
||||
</CardPicker>
|
||||
))}
|
||||
</StyledChooseTrialContainer>
|
||||
)}
|
||||
<MainButton
|
||||
title={t`Continue`}
|
||||
onClick={handleCheckoutSession}
|
||||
width={200}
|
||||
Icon={() => isSubmitting && <Loader />}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
<StyledLinkGroup>
|
||||
<ActionLink onClick={signOut}>
|
||||
<Trans>Log out</Trans>
|
||||
</ActionLink>
|
||||
<span />
|
||||
<ActionLink onClick={handleSwitchPlan(alternatePlan)}>
|
||||
<Trans>Switch to {alternatePlanName}</Trans>
|
||||
</ActionLink>
|
||||
<span />
|
||||
<ActionLink href={CAL_LINK} target="_blank" rel="noreferrer">
|
||||
<Trans>Book a Call</Trans>
|
||||
</ActionLink>
|
||||
</StyledLinkGroup>
|
||||
</>
|
||||
)
|
||||
) : (
|
||||
withCreditCardTrialPeriod && (
|
||||
<SubTitle>
|
||||
{t`Enjoy a ${withCreditCardTrialPeriodDuration}-days free trial`}
|
||||
</SubTitle>
|
||||
)
|
||||
)}
|
||||
<StyledSubscriptionContainer
|
||||
withLongerMarginBottom={!hasWithoutCreditCardTrialPeriod}
|
||||
>
|
||||
<StyledSubscriptionPriceContainer>
|
||||
<SubscriptionPrice
|
||||
type={baseProductPrice.recurringInterval}
|
||||
price={baseProductPrice.unitAmount / 100}
|
||||
/>
|
||||
</StyledSubscriptionPriceContainer>
|
||||
<StyledBenefitsContainer>
|
||||
{benefits.map((benefit) => (
|
||||
<SubscriptionBenefit key={benefit}>
|
||||
{benefit}
|
||||
</SubscriptionBenefit>
|
||||
))}
|
||||
</StyledBenefitsContainer>
|
||||
</StyledSubscriptionContainer>
|
||||
{hasWithoutCreditCardTrialPeriod && (
|
||||
<StyledChooseTrialContainer>
|
||||
{billing.trialPeriods.map((trialPeriod) => (
|
||||
<CardPicker
|
||||
checked={
|
||||
billingCheckoutSession.requirePaymentMethod ===
|
||||
trialPeriod.isCreditCardRequired
|
||||
}
|
||||
handleChange={handleTrialPeriodChange(
|
||||
trialPeriod.isCreditCardRequired,
|
||||
)}
|
||||
key={trialPeriod.duration}
|
||||
>
|
||||
<TrialCard
|
||||
duration={trialPeriod.duration}
|
||||
withCreditCard={trialPeriod.isCreditCardRequired}
|
||||
/>
|
||||
</CardPicker>
|
||||
))}
|
||||
</StyledChooseTrialContainer>
|
||||
)}
|
||||
<MainButton
|
||||
title={t`Continue`}
|
||||
onClick={handleCheckoutSession}
|
||||
width={200}
|
||||
Icon={() => isSubmitting && <Loader />}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
<StyledLinkGroup>
|
||||
<ActionLink onClick={signOut}>
|
||||
<Trans>Log out</Trans>
|
||||
</ActionLink>
|
||||
<span />
|
||||
<ActionLink onClick={handleSwitchPlan(alternatePlan)}>
|
||||
<Trans>Switch to {alternatePlanName}</Trans>
|
||||
</ActionLink>
|
||||
<span />
|
||||
<ActionLink href={CAL_LINK} target="_blank" rel="noreferrer">
|
||||
<Trans>Book a Call</Trans>
|
||||
</ActionLink>
|
||||
</StyledLinkGroup>
|
||||
</>
|
||||
) : (
|
||||
<StyledChooseYourPlanPlaceholder />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user