1
+ import { Stack , Alert , TextField , Button , Typography } from "@mui/material"
2
+ import { confirmPasswordReset , sendPasswordResetEmail , verifyPasswordResetCode } from "firebase/auth" ;
3
+ import { useEffect , useState } from "react" ;
4
+ import { auth } from "../../firebase" ;
5
+ import { firebaseErrorHandling } from "../../features/utility" ;
6
+ import { useAppDispatch } from "../../app/hooks" ;
7
+ import { openSnackbarInfo } from "../../features/app/snackbarSlice" ;
8
+ import { LoadingButton } from "@mui/lab" ;
9
+ import { useSearchParams } from "react-router-dom" ;
10
+
11
+ const ForgotPassword = ( ) => {
12
+ const [ isLoading , setLoading ] = useState ( false ) ;
13
+ const [ emailInput , setEmailInput ] = useState ( '' ) ;
14
+ const [ errorText , setErrorText ] = useState ( '' ) ;
15
+
16
+ const dispatch = useAppDispatch ( ) ;
17
+
18
+ const handleSendLink = ( ) => {
19
+ setLoading ( true ) ;
20
+
21
+ sendPasswordResetEmail ( auth , emailInput )
22
+ . then ( ( ) => {
23
+ dispatch ( openSnackbarInfo ( "Recovery link sent" ) ) ;
24
+ setErrorText ( '' ) ;
25
+ setLoading ( false ) ;
26
+ } )
27
+ . catch ( ( err ) => {
28
+ setErrorText ( firebaseErrorHandling ( err ) ) ;
29
+ setLoading ( false ) ;
30
+ } ) ;
31
+ }
32
+
33
+ return (
34
+ < Stack width = "100%" height = "100%" justifyContent = "space-between" >
35
+ < Stack width = "100%" spacing = { 3 } >
36
+ < Typography > Enter your email address and we'll send you a link to get back into your account.</ Typography >
37
+ { errorText && < Alert severity = "error" > { errorText } </ Alert > }
38
+ < TextField id = "email-input" label = "Email address" onChange = { ( e ) => { setEmailInput ( e . target . value ) } } />
39
+ </ Stack >
40
+ < LoadingButton loading = { isLoading } disabled = { emailInput ? false : true } sx = { { width : '100%' , height : '45px' } } onClick = { handleSendLink } variant = "contained" > Send Link</ LoadingButton >
41
+ </ Stack >
42
+ )
43
+ }
44
+
45
+ const ResetPassword = ( ) => {
46
+ const [ isLoading , setLoading ] = useState ( false ) ;
47
+ const [ valid , setValid ] = useState ( true ) ;
48
+
49
+ const [ newPasswordInput , setNewPasswordInput ] = useState ( '' ) ;
50
+ const [ confirmPasswordInput , setConfirmPasswordInput ] = useState ( '' ) ;
51
+ const [ errorText , setErrorText ] = useState ( '' ) ;
52
+
53
+ const [ searchParams ] = useSearchParams ( ) ;
54
+ const dispatch = useAppDispatch ( ) ;
55
+
56
+ const actionCode = searchParams . get ( 'oobCode' ) ;
57
+
58
+ useEffect ( ( ) => {
59
+ if ( actionCode ) {
60
+ verifyPasswordResetCode ( auth , actionCode )
61
+ . then ( ( res ) => {
62
+ setValid ( true ) ;
63
+ setErrorText ( '' ) ;
64
+ } )
65
+ . catch ( ( err ) => {
66
+ setErrorText ( firebaseErrorHandling ( err ) ) ;
67
+ setValid ( false ) ;
68
+ setLoading ( false ) ;
69
+ } )
70
+ }
71
+ else {
72
+ setErrorText ( 'Invalid request' ) ;
73
+ setValid ( false ) ;
74
+ setLoading ( false ) ;
75
+ }
76
+ } , [ ] )
77
+
78
+ const handleResetPassword = ( ) => {
79
+ setLoading ( true ) ;
80
+
81
+ if ( actionCode ) {
82
+ confirmPasswordReset ( auth , actionCode , newPasswordInput )
83
+ . then ( ( res ) => {
84
+ dispatch ( openSnackbarInfo ( "Password saved" ) ) ;
85
+ setErrorText ( '' ) ;
86
+ setLoading ( false ) ;
87
+ } )
88
+ . catch ( ( err ) => {
89
+ setErrorText ( firebaseErrorHandling ( err ) ) ;
90
+ setLoading ( false ) ;
91
+ } )
92
+ }
93
+ }
94
+
95
+ return (
96
+ valid ?
97
+ < Stack width = "100%" height = "100%" justifyContent = "space-between" >
98
+ < Stack width = "100%" spacing = { 3 } >
99
+ { errorText && < Alert severity = "error" > { errorText } </ Alert > }
100
+ < TextField id = "newpassword-input" label = "New password" value = { newPasswordInput } type = "password" onChange = { ( e ) => { setNewPasswordInput ( e . target . value ) } } />
101
+ < TextField id = "confirmpassword-input" label = "Confirm new password" value = { confirmPasswordInput } type = "password" onChange = { ( e ) => { setConfirmPasswordInput ( e . target . value ) } } />
102
+ { confirmPasswordInput && < Alert severity = { newPasswordInput != confirmPasswordInput ? "warning" : "success" } > { newPasswordInput != confirmPasswordInput ? "Password does not match" : "Password matched" } </ Alert > }
103
+ </ Stack >
104
+ < LoadingButton loading = { isLoading } sx = { { width : '100%' , height : '45px' } } onClick = { handleResetPassword } variant = "contained" disabled = { ! newPasswordInput || newPasswordInput != confirmPasswordInput ? true : false } > Save</ LoadingButton >
105
+ </ Stack > :
106
+ < Alert severity = "error" > { errorText } </ Alert >
107
+ )
108
+ }
109
+
110
+ export { ForgotPassword , ResetPassword } ;
0 commit comments