@@ -4,7 +4,7 @@ import { FcGoogle } from 'react-icons/fc';
4
4
import { BiSolidShow } from 'react-icons/bi' ;
5
5
import { BiSolidHide } from 'react-icons/bi' ;
6
6
import { useAppDispatch , useAppSelector } from '../store/store' ;
7
- import { loginUser } from '../store/features/auth/authSlice' ;
7
+ import { loginUser , verifyOTP } from '../store/features/auth/authSlice' ;
8
8
import { toast } from 'react-toastify' ;
9
9
import { useFormik } from 'formik' ;
10
10
import * as Yup from 'yup' ;
@@ -13,6 +13,8 @@ import { PulseLoader } from 'react-spinners';
13
13
import { addProductToWishlist } from '../store/features/wishlist/wishlistSlice' ;
14
14
import authService from '../store/features/auth/authService' ;
15
15
import { joinRoom } from '../utils/socket/socket' ;
16
+ import { Box , Button , Dialog , DialogActions , DialogContent , DialogContentText , DialogTitle , TextField } from '@mui/material' ;
17
+ import { FaSpinner } from 'react-icons/fa' ;
16
18
17
19
const LoginSchema = Yup . object ( ) . shape ( {
18
20
email : Yup . string ( )
@@ -25,6 +27,8 @@ function UserLogin() {
25
27
const [ isClicked , setIsClicked ] = useState ( false ) ;
26
28
const [ isFocused , setIsFocused ] = useState ( false ) ;
27
29
const [ isVisible , setIsVisible ] = useState ( false ) ;
30
+ const [ openOTPDialog , setOpenOTPDialog ] = useState ( false ) ;
31
+ const [ otp , setOtp ] = useState ( [ '' , '' , '' , '' , '' , '' ] ) ;
28
32
const navigate = useNavigate ( ) ;
29
33
const dispatch = useAppDispatch ( ) ;
30
34
const {
@@ -35,6 +39,7 @@ function UserLogin() {
35
39
token,
36
40
error,
37
41
message,
42
+ userId
38
43
} = useAppSelector ( ( state ) => state . auth ) ;
39
44
40
45
const formik = useFormik ( {
@@ -88,6 +93,38 @@ function UserLogin() {
88
93
setIsVisible ( ( isVisible ) => ! isVisible ) ;
89
94
}
90
95
96
+ useEffect ( ( ) => {
97
+ if ( isSuccess && message === "Check your Email for OTP Confirmation" ) {
98
+ setOpenOTPDialog ( true ) ;
99
+ }
100
+ } , [ isSuccess , message ] ) ;
101
+
102
+ const handleOtpChange = ( index , value ) => {
103
+ const newOtp = [ ...otp ] ;
104
+ newOtp [ index ] = value ;
105
+ setOtp ( newOtp ) ;
106
+ if ( value && index < 5 ) {
107
+ const nextInput = document . getElementById ( `otp-${ index + 1 } ` ) ;
108
+ if ( nextInput ) nextInput . focus ( ) ;
109
+ }
110
+ } ;
111
+
112
+ const handleVerifyOTP = async ( ) => {
113
+ const otpString = otp . join ( '' ) ;
114
+ if ( otpString . length === 6 ) {
115
+ const res = await dispatch ( verifyOTP ( { userId, otp : otpString } ) ) ;
116
+ if ( res . type = 'auth/verify-otp/rejected' ) {
117
+ toast . error ( res . payload )
118
+ }
119
+ else {
120
+ setOpenOTPDialog ( false ) ;
121
+ }
122
+ setOtp ( [ '' , '' , '' , '' , '' , '' ] )
123
+ } else {
124
+ toast . error ( "Please enter a valid 6-digit OTP" ) ;
125
+ }
126
+ } ;
127
+
91
128
return (
92
129
< section className = "section__login" >
93
130
< div className = "mini-container login" >
@@ -186,6 +223,92 @@ function UserLogin() {
186
223
</ p >
187
224
</ div >
188
225
</ div >
226
+
227
+ < Dialog
228
+ open = { openOTPDialog }
229
+ onClose = { ( ) => setOpenOTPDialog ( false ) }
230
+ aria-labelledby = "alert-dialog-title"
231
+ aria-describedby = "alert-dialog-description"
232
+ PaperProps = { {
233
+ style : {
234
+ borderRadius : '12px' ,
235
+ padding : '24px' ,
236
+ maxWidth : '400px' ,
237
+ } ,
238
+ } }
239
+ >
240
+ < DialogTitle id = "alert-dialog-title" sx = { { fontSize : '2rem' , fontWeight : 'bold' , color : '#ff6d18' } } >
241
+ Verify OTP
242
+ </ DialogTitle >
243
+ < DialogContent >
244
+ < DialogContentText id = "alert-dialog-description" sx = { { fontSize : '1.2rem' , marginBottom : '20px' } } >
245
+ Please enter the 6-digit OTP sent to your email to verify your account.
246
+ </ DialogContentText >
247
+ < Box sx = { { display : 'flex' , justifyContent : 'center' , gap : '8px' , marginBottom : '20px' } } >
248
+ { otp . map ( ( digit , index ) => (
249
+ < TextField
250
+ key = { index }
251
+ id = { `otp-${ index } ` }
252
+ value = { digit }
253
+ onChange = { ( e ) => handleOtpChange ( index , e . target . value ) }
254
+ inputProps = { {
255
+ maxLength : 1 ,
256
+ style : { textAlign : 'center' , fontSize : '1.5rem' }
257
+ } }
258
+ sx = { {
259
+ width : '40px' ,
260
+ '& .MuiOutlinedInput-root' : {
261
+ '& fieldset' : {
262
+ borderColor : '#ff6d18' ,
263
+ } ,
264
+ '&:hover fieldset' : {
265
+ borderColor : '#e65b00' ,
266
+ } ,
267
+ '&.Mui-focused fieldset' : {
268
+ borderColor : '#e65b00' ,
269
+ } ,
270
+ } ,
271
+ } }
272
+ />
273
+ ) ) }
274
+ </ Box >
275
+ </ DialogContent >
276
+ < DialogActions sx = { { justifyContent : 'center' , gap : '16px' } } >
277
+ < Button
278
+ onClick = { ( ) => { setOpenOTPDialog ( false ) ; setOtp ( [ '' , '' , '' , '' , '' , '' ] ) ; } }
279
+ sx = { {
280
+ backgroundColor : '#f0f0f0' ,
281
+ color : '#333' ,
282
+ fontSize : '1.2rem' ,
283
+ padding : '8px 24px' ,
284
+ borderRadius : '8px' ,
285
+ '&:hover' : {
286
+ backgroundColor : '#e0e0e0' ,
287
+ } ,
288
+ } }
289
+ >
290
+ Cancel
291
+ </ Button >
292
+ < Button
293
+ onClick = { handleVerifyOTP }
294
+ sx = { {
295
+ backgroundColor : '#ff6d18' ,
296
+ color : '#fff' ,
297
+ fontSize : '1.2rem' ,
298
+ padding : '8px 24px' ,
299
+ borderRadius : '8px' ,
300
+ '&:hover' : {
301
+ backgroundColor : '#e65b00' ,
302
+ } ,
303
+ } }
304
+ autoFocus
305
+ >
306
+ { isLoading ? "Verifying" : "Verify" }
307
+ < PulseLoader size = { 6 } color = "#ffe2d1" loading = { isLoading } />
308
+ </ Button >
309
+ </ DialogActions >
310
+ </ Dialog >
311
+
189
312
</ section >
190
313
) ;
191
314
}
0 commit comments