Skip to content

Commit 50089be

Browse files
committed
Handle updating email address to primary
1 parent 3017d22 commit 50089be

3 files changed

Lines changed: 39 additions & 17 deletions

File tree

packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ const AuthenticatedContent = withCoreUserGuard(() => {
128128
const ConfigureSSOSteps = () => {
129129
const { user } = useUser();
130130

131-
const primaryEmailAddress = user?.primaryEmailAddress;
131+
const hasEmailAddress = Boolean(user?.emailAddresses?.length);
132132

133133
return (
134134
<ConfigureSSOWizard>
@@ -138,7 +138,7 @@ const ConfigureSSOSteps = () => {
138138
label='Verify domain'
139139
>
140140
<ConfigureSSOWizard>
141-
{!primaryEmailAddress && (
141+
{!hasEmailAddress && (
142142
<ConfigureSSOWizard.Step
143143
id='provide-email'
144144
path='provide-email'

packages/ui/src/components/ConfigureSSO/steps/ProvideEmailStep.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { handleError } from '@/utils/errorHandler';
99
import { useConfigureSSOWizard, useRegisterContinueAction } from '../wizard';
1010
import { StepLayout } from './StepLayout';
1111

12+
const isEmail = (str: string) => /^\S+@\S+\.\S+$/.test(str);
13+
1214
export const ProvideEmail = (): JSX.Element => {
1315
const { goNext } = useConfigureSSOWizard();
1416
const { user } = useUser();
@@ -18,7 +20,7 @@ export const ProvideEmail = (): JSX.Element => {
1820
const [isSubmitting, setIsSubmitting] = React.useState(false);
1921
const createEmailAddress = useReverification((value: string) => user?.createEmailAddress({ email: value }));
2022

21-
const canSubmit = !isSubmitting;
23+
const canSubmit = isEmail(email) && !isSubmitting;
2224

2325
const submit = React.useCallback(async () => {
2426
if (!canSubmit) {

packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,29 @@ import { Col, Flow, Heading, Icon, Input, localizationKeys, Text, useLocalizatio
55
import { useFieldOTP } from '@/elements/CodeControl';
66
import { useCardState } from '@/elements/contexts';
77
import { Form } from '@/elements/Form';
8+
import { DuotoneAtSymbol } from '@/icons';
89
import { handleError } from '@/utils/errorHandler';
910

1011
import { useConfigureSSOWizard, useRegisterContinueAction } from '../wizard';
1112
import { StepLayout } from './StepLayout';
12-
import { DuotoneAtSymbol } from '@/icons';
1313

14-
export const VerifyDomainStep = (): JSX.Element => {
15-
const { goNext } = useConfigureSSOWizard();
14+
export const VerifyDomainStep = (): JSX.Element | null => {
15+
const { goNext, goToStep } = useConfigureSSOWizard();
1616
const card = useCardState();
1717
const { t } = useLocalizations();
1818
const { user } = useUser();
1919

20-
const primaryEmailAddress = user?.primaryEmailAddress;
21-
const isVerified = primaryEmailAddress?.verification.status === 'verified';
20+
const emailToVerify =
21+
user?.primaryEmailAddress ?? user?.emailAddresses?.find(e => e.verification.status !== 'verified');
22+
const isVerified = emailToVerify?.verification.status === 'verified';
23+
const isAlreadyPrimary = Boolean(emailToVerify && emailToVerify.id === user?.primaryEmailAddressId);
2224

2325
const prepareEmailVerification = useReverification(() =>
24-
primaryEmailAddress?.prepareVerification({ strategy: 'email_code' }),
26+
emailToVerify?.prepareVerification({ strategy: 'email_code' }),
2527
);
26-
const attemptEmailVerification = useReverification((code: string) =>
27-
primaryEmailAddress?.attemptVerification({ code }),
28+
const attemptEmailVerification = useReverification((code: string) => emailToVerify?.attemptVerification({ code }));
29+
const setPrimaryEmailAddress = useReverification((emailAddressId: string) =>
30+
user?.update({ primaryEmailAddressId: emailAddressId }),
2831
);
2932

3033
const prepare = React.useCallback(
@@ -44,7 +47,15 @@ export const VerifyDomainStep = (): JSX.Element => {
4447
onResendCodeClicked: () => {
4548
void prepare();
4649
},
47-
onResolve: () => {
50+
onResolve: async () => {
51+
if (emailToVerify && !isAlreadyPrimary) {
52+
try {
53+
await setPrimaryEmailAddress(emailToVerify.id);
54+
} catch (err) {
55+
handleError(err as Error, [], card.setError);
56+
return;
57+
}
58+
}
4859
void goNext();
4960
},
5061
});
@@ -67,17 +78,27 @@ export const VerifyDomainStep = (): JSX.Element => {
6778
},
6879
);
6980

81+
React.useEffect(() => {
82+
if (!emailToVerify) {
83+
void goToStep('provide-email');
84+
}
85+
}, [emailToVerify, goToStep]);
86+
7087
// Send the first code on mount (only when there's something to verify),
7188
// and clear any stale card error that could be lingering from a previous step
7289
React.useEffect(() => {
73-
if (!isVerified) {
90+
if (emailToVerify && !isVerified) {
7491
void prepare();
7592
}
7693
card.setError(undefined);
7794
return () => card.setError(undefined);
7895
// eslint-disable-next-line react-hooks/exhaustive-deps
7996
}, []);
8097

98+
if (!emailToVerify) {
99+
return null;
100+
}
101+
81102
return (
82103
<Flow.Part part='verifyDomain'>
83104
<StepLayout
@@ -93,7 +114,7 @@ export const VerifyDomainStep = (): JSX.Element => {
93114
paddingBlock: t.space.$8,
94115
})}
95116
>
96-
{showVerifiedView && primaryEmailAddress ? (
117+
{showVerifiedView ? (
97118
<>
98119
<Icon
99120
icon={DuotoneAtSymbol}
@@ -118,7 +139,7 @@ export const VerifyDomainStep = (): JSX.Element => {
118139
</Col>
119140
<Input
120141
type='email'
121-
value={primaryEmailAddress.emailAddress}
142+
value={emailToVerify.emailAddress}
122143
readOnly
123144
aria-label={t(localizationKeys('configureSSO.verifyEmailDomainStep.emailCode.verified.inputLabel'))}
124145
sx={t => ({ width: '100%', maxWidth: t.sizes.$66, backgroundColor: t.colors.$neutralAlpha50 })}
@@ -137,11 +158,10 @@ export const VerifyDomainStep = (): JSX.Element => {
137158
variant='body'
138159
sx={t => ({ color: t.colors.$colorMutedForeground })}
139160
localizationKey={localizationKeys('configureSSO.verifyEmailDomainStep.emailCode.formSubtitle', {
140-
identifier: primaryEmailAddress?.emailAddress ?? '',
161+
identifier: emailToVerify.emailAddress,
141162
})}
142163
/>
143164
</Col>
144-
145165
<Form.OTPInput
146166
{...otp}
147167
resendButton={localizationKeys('configureSSO.verifyEmailDomainStep.emailCode.resendButton')}

0 commit comments

Comments
 (0)