1
- import React , { useCallback , useLayoutEffect , useState } from 'react' ;
1
+ import React , { useCallback , useLayoutEffect } from 'react'
2
2
3
3
import { isAppError } from '../../../helpers/errors'
4
4
5
- import { email } from '../../../core/validation' ;
6
- import { Heading , Intro , Info , Link , Alternative } from '../../../components/miscComponent' ;
5
+ import {
6
+ Alternative ,
7
+ Heading ,
8
+ Info ,
9
+ Intro ,
10
+ Link ,
11
+ } from '../../../components/miscComponent'
12
+ import { email } from '../../../core/validation'
7
13
8
- import { createForm , FormContext } from '../../../components/form/formComponent' ;
9
- import phoneNumberField , { type PhoneNumberOptions } from '../../../components/form/fields/phoneNumberField' ;
10
- import { simpleField } from '../../../components/form/fields/simpleField' ;
11
- import ReCaptcha , { importGoogleRecaptchaScript } from '../../../components/reCaptcha' ;
14
+ import phoneNumberField , {
15
+ type PhoneNumberOptions ,
16
+ } from '../../../components/form/fields/phoneNumberField'
17
+ import { simpleField } from '../../../components/form/fields/simpleField'
18
+ import { createForm , FormContext } from '../../../components/form/formComponent'
19
+ import ReCaptcha , {
20
+ importGoogleRecaptchaScript ,
21
+ } from '../../../components/reCaptcha'
12
22
23
+ import { InitialScreen } from '../../../../constants.ts'
24
+ import { DefaultButton } from '../../../components/form/buttonComponent.tsx'
25
+ import passwordField from '../../../components/form/fields/passwordField.tsx'
26
+ import simplePasswordField from '../../../components/form/fields/simplePasswordField'
27
+ import { useConfig } from '../../../contexts/config.tsx'
13
28
import { useI18n } from '../../../contexts/i18n'
14
- import { useRouting } from '../../../contexts/routing' ;
15
- import { useReachfive } from '../../../contexts/reachfive' ;
16
- import { selectLogin } from '../authWidget.tsx' ;
17
- import { InitialScreen } from '../../../../constants.ts' ;
18
- import passwordField from '../../../components/form/fields/passwordField.tsx' ;
19
- import simplePasswordField from '../../../components/form/fields/simplePasswordField' ;
20
- import { DefaultButton } from '../../../components/form/buttonComponent.tsx' ;
21
- import { Validator } from '../../../core/validation.ts' ;
22
- import { useConfig } from '../../../contexts/config.tsx' ;
29
+ import { useReachfive } from '../../../contexts/reachfive'
30
+ import { useRouting } from '../../../contexts/routing'
31
+ import { Validator } from '../../../core/validation.ts'
32
+ import { selectLogin } from '../authWidget.tsx'
23
33
24
- import type { OnError , OnSuccess } from '../../../types' ;
34
+ import type { OnError , OnSuccess } from '../../../types'
25
35
26
36
type EmailIdentifier = { email : string }
27
37
type PhoneNumberIdentifier = { phoneNumber : string }
@@ -42,27 +52,33 @@ const ForgotPasswordEmailForm = createForm<ForgotPasswordEmailFormData>({
42
52
} ) ,
43
53
]
44
54
} ,
45
- submitLabel : 'forgotPassword.submitLabel'
46
- } ) ;
55
+ submitLabel : 'forgotPassword.submitLabel' ,
56
+ } )
47
57
48
- const ForgotPasswordPhoneNumberForm = createForm < ForgotPasswordPhoneNumberFormData , { phoneNumberOptions ?: PhoneNumberOptions } > ( {
58
+ const ForgotPasswordPhoneNumberForm = createForm <
59
+ ForgotPasswordPhoneNumberFormData ,
60
+ { phoneNumberOptions ?: PhoneNumberOptions }
61
+ > ( {
49
62
prefix : 'r5-forgot-password-' ,
50
63
fields ( { config, phoneNumberOptions } ) {
51
64
return [
52
- phoneNumberField ( {
53
- key : 'phoneNumber' ,
54
- label : 'phoneNumber' ,
55
- required : true ,
56
- withCountryCallingCode : false ,
57
- ...phoneNumberOptions ,
58
- } , config )
65
+ phoneNumberField (
66
+ {
67
+ key : 'phoneNumber' ,
68
+ label : 'phoneNumber' ,
69
+ required : true ,
70
+ withCountryCallingCode : false ,
71
+ ...phoneNumberOptions ,
72
+ } ,
73
+ config
74
+ ) ,
59
75
]
60
76
} ,
61
- submitLabel : 'forgotPassword.submitLabel.code'
62
- } ) ;
77
+ submitLabel : 'forgotPassword.submitLabel.code' ,
78
+ } )
63
79
64
80
export type VerificationCodeFormData = {
65
- password : string ,
81
+ password : string
66
82
passwordConfirmation : string
67
83
verificationCode : string
68
84
}
@@ -75,34 +91,44 @@ interface VerificationCodeFormProps {
75
91
canShowPassword ?: boolean
76
92
}
77
93
78
- const VerificationCodeForm = createForm < VerificationCodeFormData , VerificationCodeFormProps > ( {
94
+ const VerificationCodeForm = createForm <
95
+ VerificationCodeFormData ,
96
+ VerificationCodeFormProps
97
+ > ( {
79
98
prefix : 'r5-verification-code-' ,
80
99
fields ( { canShowPassword = false , config } ) {
81
100
return [
82
101
simpleField ( {
83
102
key : 'verification_code' ,
84
103
label : 'verificationCode' ,
85
- type : 'text'
104
+ type : 'text' ,
86
105
} ) ,
87
- passwordField ( {
88
- label : 'newPassword' ,
89
- autoComplete : 'new-password' ,
90
- canShowPassword
91
- } , config ) ,
106
+ passwordField (
107
+ {
108
+ label : 'newPassword' ,
109
+ autoComplete : 'new-password' ,
110
+ canShowPassword,
111
+ } ,
112
+ config
113
+ ) ,
92
114
simplePasswordField ( {
93
115
key : 'password_confirmation' ,
94
116
label : 'passwordConfirmation' ,
95
117
autoComplete : 'new-password' ,
96
- validator : new Validator < string , FormContext < VerificationCodeFormData > > ( {
118
+ validator : new Validator <
119
+ string ,
120
+ FormContext < VerificationCodeFormData >
121
+ > ( {
97
122
rule : ( value , ctx ) => value === ctx . fields . password ,
98
- hint : 'passwordMatch'
99
- } )
100
- } )
123
+ hint : 'passwordMatch' ,
124
+ } ) ,
125
+ } ) ,
101
126
]
102
- }
127
+ } ,
103
128
} )
104
129
105
- const skipError = ( error : unknown ) => isAppError ( error ) ? error . error === 'resource_not_found' : false ;
130
+ const skipError = ( error : unknown ) =>
131
+ isAppError ( error ) ? error . error === 'resource_not_found' : false
106
132
107
133
export interface ForgotPasswordViewProps {
108
134
/**
@@ -155,12 +181,12 @@ export interface ForgotPasswordViewProps {
155
181
* The URL sent in the email to which the user is redirected.
156
182
* This URL must be whitelisted in the `Allowed Callback URLs` field of your ReachFive client settings.
157
183
*/
158
- redirectUrl ?: string ,
184
+ redirectUrl ?: string
159
185
/**
160
186
* Returned in the `redirectUrl` as a query parameter, this parameter is used to redirect users to a specific URL after a password reset.
161
187
* Important: This parameter should only be used with Hosted Pages.
162
188
*/
163
- returnToAfterPasswordReset ?: string ,
189
+ returnToAfterPasswordReset ?: string
164
190
/**
165
191
* Callback function called when the request has succeed.
166
192
*/
@@ -193,13 +219,19 @@ export const ForgotPasswordView = ({
193
219
const callback = useCallback (
194
220
( data : ForgotPasswordEmailFormData ) => {
195
221
return ReCaptcha . handle (
196
- { ...data , redirectUrl, returnToAfterPasswordReset} ,
222
+ { ...data , redirectUrl, returnToAfterPasswordReset } ,
197
223
{ recaptcha_enabled, recaptcha_site_key } ,
198
224
coreClient . requestPasswordReset ,
199
- " forgot_password"
225
+ ' forgot_password'
200
226
)
201
227
} ,
202
- [ coreClient , recaptcha_enabled , recaptcha_site_key , redirectUrl , returnToAfterPasswordReset ]
228
+ [
229
+ coreClient ,
230
+ recaptcha_enabled ,
231
+ recaptcha_site_key ,
232
+ redirectUrl ,
233
+ returnToAfterPasswordReset ,
234
+ ]
203
235
)
204
236
205
237
useLayoutEffect ( ( ) => {
@@ -222,12 +254,20 @@ export const ForgotPasswordView = ({
222
254
/>
223
255
{ allowPhoneNumberResetPassword && config . sms && (
224
256
< Alternative >
225
- < DefaultButton onClick = { ( ) => goTo ( 'forgot-password-phone-number' ) } > { i18n ( 'forgotPassword.usePhoneNumberButton' ) } </ DefaultButton >
257
+ < DefaultButton
258
+ onClick = { ( ) => goTo ( 'forgot-password-phone-number' ) }
259
+ >
260
+ { i18n ( 'forgotPassword.usePhoneNumberButton' ) }
261
+ </ DefaultButton >
226
262
</ Alternative >
227
263
) }
228
264
{ allowLogin && (
229
265
< Alternative >
230
- < Link target = { selectLogin ( initialScreen , allowWebAuthnLogin ) } > { i18n ( 'forgotPassword.backToLoginLink' ) } </ Link >
266
+ < Link
267
+ target = { selectLogin ( initialScreen , allowWebAuthnLogin ) }
268
+ >
269
+ { i18n ( 'forgotPassword.backToLoginLink' ) }
270
+ </ Link >
231
271
</ Alternative >
232
272
) }
233
273
</ div >
@@ -251,22 +291,27 @@ export const ForgotPasswordPhoneNumberView = ({
251
291
const { goTo } = useRouting ( )
252
292
const i18n = useI18n ( )
253
293
254
- const [ phoneNumber , setPhoneNumber ] = useState < string > ( '' )
255
-
256
294
const callback = useCallback (
257
295
( data : ForgotPasswordPhoneNumberFormData ) => {
258
- setPhoneNumber ( data . phoneNumber )
259
296
return ReCaptcha . handle (
260
- { ...data , redirectUrl, returnToAfterPasswordReset} ,
297
+ { ...data , redirectUrl, returnToAfterPasswordReset } ,
261
298
{ recaptcha_enabled, recaptcha_site_key } ,
262
299
coreClient . requestPasswordReset ,
263
- " forgot_password"
264
- )
300
+ ' forgot_password'
301
+ ) . then ( ( ) => data )
265
302
} ,
266
- [ coreClient , recaptcha_enabled , recaptcha_site_key , redirectUrl , returnToAfterPasswordReset ]
303
+ [
304
+ coreClient ,
305
+ recaptcha_enabled ,
306
+ recaptcha_site_key ,
307
+ redirectUrl ,
308
+ returnToAfterPasswordReset ,
309
+ ]
267
310
)
268
311
269
- const onSuccess = ( ) => goTo < PhoneNumberIdentifier > ( 'forgot-password-code' , { phoneNumber } )
312
+ const onSuccess = ( { phoneNumber } : PhoneNumberIdentifier ) => {
313
+ goTo < PhoneNumberIdentifier > ( 'forgot-password-code' , { phoneNumber } )
314
+ }
270
315
271
316
useLayoutEffect ( ( ) => {
272
317
importGoogleRecaptchaScript ( recaptcha_site_key )
@@ -285,11 +330,17 @@ export const ForgotPasswordPhoneNumberView = ({
285
330
phoneNumberOptions = { phoneNumberOptions }
286
331
/>
287
332
< Alternative >
288
- < DefaultButton onClick = { ( ) => goTo ( 'forgot-password' ) } > { i18n ( 'forgotPassword.useEmailButton' ) } </ DefaultButton >
333
+ < DefaultButton onClick = { ( ) => goTo ( 'forgot-password' ) } >
334
+ { i18n ( 'forgotPassword.useEmailButton' ) }
335
+ </ DefaultButton >
289
336
</ Alternative >
290
337
{ allowLogin && (
291
338
< Alternative >
292
- < Link target = { selectLogin ( initialScreen , allowWebAuthnLogin ) } > { i18n ( 'forgotPassword.backToLoginLink' ) } </ Link >
339
+ < Link
340
+ target = { selectLogin ( initialScreen , allowWebAuthnLogin ) }
341
+ >
342
+ { i18n ( 'forgotPassword.backToLoginLink' ) }
343
+ </ Link >
293
344
</ Alternative >
294
345
) }
295
346
</ div >
@@ -306,13 +357,14 @@ export const ForgotPasswordCodeView = ({
306
357
onSuccess = ( ( ) => { } ) as OnSuccess ,
307
358
} : ForgotPasswordViewProps ) => {
308
359
const coreClient = useReachfive ( )
309
- const { goTo, params } = useRouting ( )
310
360
const i18n = useI18n ( )
361
+ const { goTo, params } = useRouting ( )
362
+ const { phoneNumber } = params as PhoneNumberIdentifier
311
363
312
364
const callback = useCallback (
313
365
( { passwordConfirmation : _ , ...data } : VerificationCodeFormData ) => {
314
366
return coreClient . updatePassword ( {
315
- ... ( params as PhoneNumberIdentifier ) ,
367
+ phoneNumber ,
316
368
...data ,
317
369
} )
318
370
} ,
@@ -335,7 +387,11 @@ export const ForgotPasswordCodeView = ({
335
387
/>
336
388
{ allowLogin && (
337
389
< Alternative >
338
- < Link target = { selectLogin ( initialScreen , allowWebAuthnLogin ) } > { i18n ( 'back' ) } </ Link >
390
+ < Link
391
+ target = { selectLogin ( initialScreen , allowWebAuthnLogin ) }
392
+ >
393
+ { i18n ( 'back' ) }
394
+ </ Link >
339
395
</ Alternative >
340
396
) }
341
397
</ div >
@@ -345,7 +401,7 @@ export const ForgotPasswordCodeView = ({
345
401
export const ForgotPasswordSuccessView = ( {
346
402
allowLogin = true ,
347
403
initialScreen,
348
- allowWebAuthnLogin = false
404
+ allowWebAuthnLogin = false ,
349
405
} : ForgotPasswordViewProps ) => {
350
406
const i18n = useI18n ( )
351
407
return (
@@ -354,7 +410,11 @@ export const ForgotPasswordSuccessView = ({
354
410
< Info > { i18n ( 'forgotPassword.successMessage' ) } </ Info >
355
411
{ allowLogin && (
356
412
< Alternative >
357
- < Link target = { selectLogin ( initialScreen , allowWebAuthnLogin ) } > { i18n ( 'back' ) } </ Link >
413
+ < Link
414
+ target = { selectLogin ( initialScreen , allowWebAuthnLogin ) }
415
+ >
416
+ { i18n ( 'back' ) }
417
+ </ Link >
358
418
</ Alternative >
359
419
) }
360
420
</ div >
0 commit comments