@@ -14,6 +14,7 @@ import { OrView } from '../../shared/components/OrView'
1414import { ScreenWrapper } from '../../shared/components/ScreenWrapper'
1515import { SignUpFooter } from '../../shared/components/SignUpFooter'
1616import { Text } from '../../shared/components/Text'
17+ import { isValidEmailAddress } from '../../shared/utils/common'
1718import { useAuth } from '../hooks/useAuth'
1819
1920// Helper to check if error is due to user closing OAuth window
@@ -41,6 +42,7 @@ export function SignUp() {
4142 const { goToStep, setEmail, setOtpSession, config, enabledMethods } =
4243 useAuth ( )
4344 const [ agreedToTerms , setAgreedToTerms ] = useState ( false )
45+ const [ highlightAgreement , setHighlightAgreement ] = useState ( false )
4446 const [ emailInput , setEmailInput ] = useState ( '' )
4547 const shouldUseOtp = config ?. emailAuthMethod === 'otp'
4648 const { mutateAsync : sendOtp , isPending : isSendOtpPending } = useSendOTP ( )
@@ -102,19 +104,30 @@ export function SignUp() {
102104 const canContinue = ! requiresAgreement || agreedToTerms
103105
104106 const handleRegisterPasskey = ( ) => {
105- if ( anyPending || ! canContinue ) return
107+ if ( anyPending ) return
108+ if ( ! canContinue ) {
109+ setHighlightAgreement ( true )
110+ return
111+ }
106112 setError ( null )
107113 registerPasskey ( )
108114 }
109115
110116 const handleLoginPasskey = ( ) => {
111- if ( anyPending || ! canContinue ) return
117+ if ( anyPending ) return
118+ if ( ! canContinue ) {
119+ setHighlightAgreement ( true )
120+ return
121+ }
112122 setError ( null )
113123 loginPasskey ( )
114124 }
115125
116126 const handleGoogleAuth = async ( ) => {
117- if ( ! canContinue ) return
127+ if ( ! canContinue ) {
128+ setHighlightAgreement ( true )
129+ return
130+ }
118131 setError ( null )
119132 try {
120133 await authenticateOAuth ( { provider : 'google' } )
@@ -130,43 +143,35 @@ export function SignUp() {
130143 goToStep ( 'wallet-selection' )
131144 }
132145
133- const handleSendOtp = async ( ) => {
134- if ( ! emailInput || anyPending || ! canContinue ) return
135- setError ( null )
136- try {
137- const { otpId, otpEncryptionTargetBundle } = await sendOtp ( {
138- email : emailInput ,
139- } )
140- setEmail ( emailInput )
141- setOtpSession ( { otpId, otpEncryptionTargetBundle } )
142- goToStep ( 'otp-input' )
143- } catch ( err ) {
144- setError (
145- err instanceof Error ? err . message : 'Failed to send verification code' ,
146- )
146+ const handleEmailSubmit = async ( forceMethod ?: 'otp' | 'magicLink' ) => {
147+ if ( ! emailInput || anyPending ) return
148+ if ( ! isValidEmailAddress ( emailInput ) ) return
149+ if ( ! canContinue ) {
150+ setHighlightAgreement ( true )
151+ return
147152 }
148- }
149153
150- const handleSendMagicLink = async ( ) => {
151- if ( ! emailInput || anyPending || ! canContinue ) return
154+ const useOtp =
155+ forceMethod !== undefined ? forceMethod === 'otp' : shouldUseOtp
156+
152157 setError ( null )
153158 try {
154- const { otpId, otpEncryptionTargetBundle } = await sendMagicLink ( {
155- email : emailInput ,
156- redirectURL : config ?. magicLinkBaseUrl ?? '' ,
157- } )
159+ const { otpId, otpEncryptionTargetBundle } = useOtp
160+ ? await sendOtp ( { email : emailInput } )
161+ : await sendMagicLink ( {
162+ email : emailInput ,
163+ redirectURL : config ?. magicLinkBaseUrl ?? '' ,
164+ } )
158165 setEmail ( emailInput )
159166 setOtpSession ( { otpId, otpEncryptionTargetBundle } )
160- goToStep ( 'email-verification' )
167+ goToStep ( useOtp ? 'otp-input' : 'email-verification' )
161168 } catch ( err ) {
162169 setError (
163170 err instanceof Error ? err . message : 'Failed to send verification code' ,
164171 )
165172 }
166173 }
167174
168- const handleEmailSubmit = shouldUseOtp ? handleSendOtp : handleSendMagicLink
169-
170175 if ( error ) {
171176 return (
172177 < div className = "flex items-center justify-center min-h-screen" >
@@ -239,24 +244,28 @@ export function SignUp() {
239244 autoComplete = "email"
240245 disabled = { anyPending }
241246 variant = "listItemStyle"
247+ className = "rounded-3xl"
242248 onKeyDown = { ( e ) => {
243249 if (
244250 e . key === 'Enter' &&
245251 emailInput &&
246252 ! anyPending &&
247- canContinue &&
248253 ! showBothEmailButtons
249254 ) {
250255 handleEmailSubmit ( )
251256 }
252257 } }
253258 >
254259 { ! showBothEmailButtons &&
255- ( emailInput && ! anyPending && canContinue ? (
260+ ( emailInput && ! anyPending ? (
256261 < button
257262 type = "button"
258- className = "w-13 h-13 rounded-2xl bg-greyScale/[3%] flex items-center justify-center hover:bg-greyScale/[5%] transition-colors cursor-pointer"
259- onClick = { handleEmailSubmit }
263+ className = { `w-13 h-13 rounded-2xl bg-greyScale/[3%] flex items-center justify-center transition-colors ${
264+ isValidEmailAddress ( emailInput ) && canContinue
265+ ? 'cursor-pointer hover:bg-greyScale/[5%]'
266+ : 'cursor-not-allowed opacity-50'
267+ } `}
268+ onClick = { ( ) => handleEmailSubmit ( ) }
260269 >
261270 < Icon
262271 name = "chevronRight"
@@ -276,16 +285,24 @@ export function SignUp() {
276285 text = "Continue with email magic link"
277286 iconName = "email"
278287 trailIcon
279- disabled = { ! emailInput || anyPending || ! canContinue }
280- onClick = { handleSendMagicLink }
288+ disabled = {
289+ ! emailInput ||
290+ anyPending ||
291+ ! isValidEmailAddress ( emailInput )
292+ }
293+ onClick = { ( ) => handleEmailSubmit ( 'magicLink' ) }
281294 />
282295 < Button
283296 action = "secondaryNeutral"
284297 text = "Continue with email OTP code"
285298 iconName = "email"
286299 trailIcon
287- disabled = { ! emailInput || anyPending || ! canContinue }
288- onClick = { handleSendOtp }
300+ disabled = {
301+ ! emailInput ||
302+ anyPending ||
303+ ! isValidEmailAddress ( emailInput )
304+ }
305+ onClick = { ( ) => handleEmailSubmit ( 'otp' ) }
289306 />
290307 </ >
291308 ) }
@@ -310,7 +327,11 @@ export function SignUp() {
310327 termsAndConditionsUrl = { config ?. termsAndConditionsUrl }
311328 privacyPolicyUrl = { config ?. privacyPolicyUrl }
312329 agreedToTerms = { agreedToTerms }
313- setAgreedToTerms = { setAgreedToTerms }
330+ setAgreedToTerms = { ( agreed ) => {
331+ setAgreedToTerms ( agreed )
332+ if ( agreed ) setHighlightAgreement ( false )
333+ } }
334+ highlight = { highlightAgreement }
314335 />
315336 </ div >
316337 ) }
0 commit comments