1
- import { useState } from 'react' ;
2
- import { auth , signInWithGoogle , signInWithEmailAndPassword } from '../../firebaseConfig' ;
3
- // import { GoogleButton } from 'react-google-button'
4
- import { UserAuth } from '../context/AuthContext' ;
1
+ // SignIn.jsx
2
+ import React , { useState } from 'react' ;
3
+ import {
4
+ auth ,
5
+ signInWithGoogle ,
6
+ signInWithEmailAndPassword ,
7
+ signInWithDiscord
8
+ } from '../../firebaseConfig' ;
9
+ import { UserAuth } from '../../context/AuthContext' ;
10
+ import { FaGoogle , FaDiscord } from 'react-icons/fa' ;
11
+ import { motion } from 'framer-motion' ;
5
12
6
13
const SignIn = ( ) => {
7
14
const [ email , setEmail ] = useState ( '' ) ;
8
15
const [ password , setPassword ] = useState ( '' ) ;
9
16
17
+ const [ isLoading , setIsLoading ] = useState ( false ) ;
18
+ const [ mode , setMode ] = useState ( 'signin' ) ; // 'signin', 'signup', 'resetPassword'
19
+
20
+
21
+ const [ touched , setTouched ] = useState ( { } ) ;
22
+ const [ errors , setErrors ] = useState ( { } ) ;
23
+
10
24
const { googleSignIn } = UserAuth ( ) ;
11
-
12
- const handleGoogleSignIn = async ( ) => {
13
- try {
14
- const { user } = await googleSignIn ( ) ;
15
- console . log ( user , "Logged in with Google" ) ;
16
- } catch ( error ) {
17
- console . log ( error ) ;
18
- }
25
+
26
+ const handleGoogleSignIn = async ( ) => {
27
+ setIsLoading ( true ) ;
28
+ try {
29
+ const { user } = await googleSignIn ( ) ;
30
+ console . log ( user , "Logged in with Google" ) ;
31
+ } catch ( error ) {
32
+ console . log ( error ) ;
33
+ } finally {
34
+ setIsLoading ( false ) ;
35
+ }
36
+ } ;
37
+
38
+ const handleEmailSignIn = async ( e ) => {
39
+ e . preventDefault ( ) ;
40
+ if ( validate ( ) ) {
41
+ setIsLoading ( true ) ;
42
+ try {
43
+ await signInWithEmailAndPassword ( auth , email , password ) ;
44
+ console . log ( 'Logged in' ) ;
45
+ } catch ( error ) {
46
+ console . error ( error ) ;
47
+ setErrors ( { ...errors , auth : 'Invalid email or password' } ) ;
48
+ } finally {
49
+ setIsLoading ( false ) ;
50
+ }
19
51
}
52
+ } ;
20
53
21
- const handleLogin = async ( ) => {
54
+ const handleDiscordSignIn = async ( ) => {
55
+ setIsLoading ( true ) ;
22
56
try {
23
- await signInWithEmailAndPassword ( auth , email , password ) ;
24
- console . log ( 'Logged in' ) ;
57
+ await signInWithDiscord ( ) ;
25
58
} catch ( error ) {
26
59
console . error ( error ) ;
60
+ } finally {
61
+ setIsLoading ( false ) ;
62
+ }
63
+ } ;
64
+
65
+ const handleResetPassword = async ( ) => {
66
+ // Implement password reset logic
67
+ } ;
68
+
69
+ const handleSignUp = async ( ) => {
70
+ // Implement sign up logic
71
+ } ;
72
+
73
+ const inputClassNames = ( field ) => {
74
+ let baseClasses = "w-full px-4 py-2 bg-white border border-slate-300 rounded-md text-md shadow-sm placeholder-slate-400 focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500 transition-colors" ;
75
+ if ( errors [ field ] && touched [ field ] ) {
76
+ baseClasses += " border-pink-500 text-pink-600 focus:border-pink-500 focus:ring-pink-500" ;
77
+ }
78
+ return baseClasses ;
79
+ } ;
80
+
81
+ const handleBlur = ( e ) => {
82
+ const { name } = e . target ;
83
+ setTouched ( { ...touched , [ name ] : true } ) ;
84
+ } ;
85
+
86
+ const validate = ( ) => {
87
+ let tempErrors = { } ;
88
+ if ( ! email || ! / \S + @ \S + \. \S + / . test ( email ) ) {
89
+ tempErrors . email = 'Valid email is required' ;
90
+ }
91
+ if ( mode !== 'resetPassword' && ( ! password || password . length < 6 ) ) {
92
+ tempErrors . password = 'Password must be at least 6 characters' ;
27
93
}
94
+ setErrors ( tempErrors ) ;
95
+ return Object . keys ( tempErrors ) . length === 0 ;
28
96
} ;
29
97
30
98
return (
31
- < div className = "login-container" >
32
- < h1 > Login</ h1 >
33
- < input
34
- type = "email"
35
- value = { email }
36
- onChange = { ( e ) => setEmail ( e . target . value ) }
37
- placeholder = "Email"
38
- />
39
- < input
40
- type = "password"
41
- value = { password }
42
- onChange = { ( e ) => setPassword ( e . target . value ) }
43
- placeholder = "Password"
44
- />
45
- < button onClick = { handleLogin } > Login</ button >
46
- < button onClick = { handleGoogleSignIn } > Login with Google</ button >
47
- < button onClick = { ( ) => alert ( 'Implement Discord login' ) } > Login with Discord</ button >
99
+ < div className = "min-h-screen flex items-center justify-center bg-gradient-to-r from-cyan-500 to-blue-500 p-4" style = { { animation : 'bounceIn 1s ease-in-out' } } >
100
+ < motion . div
101
+ initial = { { opacity : 0 , y : - 50 } }
102
+ animate = { { opacity : 1 , y : 0 } }
103
+ transition = { { duration : 0.5 } }
104
+ className = "bg-white p-8 rounded-lg shadow-xl w-full max-w-md"
105
+ >
106
+ < h2 className = "text-3xl font-bold mb-6 text-center text-gray-800" >
107
+ { mode === 'signin' ? 'Sign In' : mode === 'signup' ? 'Sign Up' : 'Reset Password' }
108
+ </ h2 >
109
+
110
+ < form onSubmit = { handleEmailSignIn } className = "space-y-4" >
111
+
112
+ < input
113
+ type = "email"
114
+ name = "email"
115
+ value = { email }
116
+ onChange = { ( e ) => setEmail ( e . target . value ) }
117
+ onBlur = { handleBlur }
118
+ placeholder = "Email"
119
+ className = { inputClassNames ( 'email' ) }
120
+ />
121
+ { errors . email && touched . email && < p className = "text-red-500 text-sm mt-1" > { errors . email } </ p > }
122
+
123
+ { mode !== 'resetPassword' && (
124
+ < >
125
+ < input
126
+ type = "password"
127
+ name = "password"
128
+ value = { password }
129
+ onChange = { ( e ) => setPassword ( e . target . value ) }
130
+ onBlur = { handleBlur }
131
+ placeholder = "Password"
132
+ className = { inputClassNames ( 'password' ) }
133
+ />
134
+ { errors . password && touched . password && < p className = "text-red-500 text-sm mt-1" > { errors . password } </ p > }
135
+ </ >
136
+ ) }
137
+
138
+ < motion . button
139
+ whileHover = { { scale : 1.05 } }
140
+ whileTap = { { scale : 0.95 } }
141
+ type = "submit"
142
+ className = "w-full bg-blue-600 text-white py-2 rounded-md hover:bg-blue-700 transition duration-300"
143
+ disabled = { isLoading }
144
+ >
145
+ { isLoading ? 'Loading...' : mode === 'signin' ? 'Sign In' : mode === 'signup' ? 'Sign Up' : 'Reset Password' }
146
+ </ motion . button >
147
+ </ form >
148
+
149
+ < div className = "mt-4 flex flex-col space-y-2" >
150
+ < motion . button
151
+ whileHover = { { scale : 1.05 } }
152
+ whileTap = { { scale : 0.95 } }
153
+ onClick = { handleGoogleSignIn }
154
+ className = "flex items-center justify-center w-full bg-white text-gray-700 py-2 px-4 rounded-md border border-gray-300 hover:bg-gray-100 transition duration-300"
155
+ disabled = { isLoading }
156
+ >
157
+ < FaGoogle className = "mr-2" /> Continue with Google
158
+ </ motion . button >
159
+ < motion . button
160
+ whileHover = { { scale : 1.05 } }
161
+ whileTap = { { scale : 0.95 } }
162
+ onClick = { handleDiscordSignIn }
163
+ className = "flex items-center justify-center w-full bg-indigo-600 text-white py-2 px-4 rounded-md hover:bg-indigo-700 transition duration-300"
164
+ disabled = { isLoading }
165
+ >
166
+ < FaDiscord className = "mr-2" /> Continue with Discord
167
+ </ motion . button >
168
+ </ div >
169
+
170
+ < div className = "mt-4 text-center" >
171
+ < a
172
+ href = "#"
173
+ onClick = { ( ) => setMode ( 'resetPassword' ) }
174
+ className = "text-sm text-blue-600 hover:underline"
175
+ >
176
+ Forgot password?
177
+ </ a >
178
+ </ div >
179
+
180
+ < div className = "mt-4 text-center" >
181
+ < span className = "text-sm text-gray-600" >
182
+ { mode === 'signin' ? "Don't have an account? " : "Already have an account? " }
183
+ </ span >
184
+ < a href = "#"
185
+ onClick = { ( ) => setMode ( mode === 'signin' ? 'signup' : 'signin' ) }
186
+ className = "text-sm text-blue-600 hover:underline"
187
+ >
188
+ { mode === 'signin' ? 'Sign up' : 'Sign in' }
189
+ </ a >
190
+ </ div >
191
+ </ motion . div >
48
192
</ div >
49
193
) ;
50
- } ;
194
+ }
51
195
52
- export default SignIn ;
196
+ export default SignIn ;
0 commit comments