@@ -22,8 +22,9 @@ export default function AuthModal({
2222 const [ showConfirmPassword , setShowConfirmPassword ] = useState ( false ) ;
2323 const [ error , setError ] = useState ( "" ) ;
2424 const [ loading , setLoading ] = useState ( false ) ;
25+ const [ googleLoading , setGoogleLoading ] = useState ( false ) ;
2526
26- const { login, signup } = useAuth ( ) ;
27+ const { login, signup, signInWithGoogle } = useAuth ( ) ;
2728
2829 const resetForm = ( ) => {
2930 setEmail ( "" ) ;
@@ -40,6 +41,20 @@ export default function AuthModal({
4041 onClose ( ) ;
4142 } ;
4243
44+ const handleGoogleSignIn = async ( ) => {
45+ setError ( "" ) ;
46+ setGoogleLoading ( true ) ;
47+
48+ try {
49+ await signInWithGoogle ( ) ;
50+ handleClose ( ) ;
51+ } catch ( err : any ) {
52+ setError ( err . message || "Google sign-in failed" ) ;
53+ } finally {
54+ setGoogleLoading ( false ) ;
55+ }
56+ } ;
57+
4358 const handleSubmit = async ( e : React . FormEvent ) => {
4459 e . preventDefault ( ) ;
4560 setError ( "" ) ;
@@ -87,132 +102,172 @@ export default function AuthModal({
87102 </ button >
88103 </ div >
89104
90- < form onSubmit = { handleSubmit } className = "p-6 space-y-4" >
105+ < div className = "p-6 space-y-4" >
91106 { error && (
92107 < div className = "flex items-center space-x-2 p-3 bg-red-900/20 border border-red-500/30 rounded-lg" >
93108 < AlertCircle className = "h-4 w-4 text-red-400" />
94109 < span className = "text-red-400 text-sm" > { error } </ span >
95110 </ div >
96111 ) }
97112
98- { mode === "signup" && (
113+ < button
114+ onClick = { handleGoogleSignIn }
115+ disabled = { googleLoading || loading }
116+ className = "w-full flex items-center justify-center space-x-3 py-3 px-4 bg-white hover:bg-gray-100 disabled:bg-gray-300 disabled:cursor-not-allowed text-gray-700 font-medium rounded-lg transition-colors border"
117+ >
118+ { googleLoading ? (
119+ < div className = "w-5 h-5 border-2 border-gray-400 border-t-transparent rounded-full animate-spin" > </ div >
120+ ) : (
121+ < svg className = "w-5 h-5" viewBox = "0 0 24 24" >
122+ < path
123+ fill = "#4285F4"
124+ d = "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
125+ />
126+ < path
127+ fill = "#34A853"
128+ d = "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
129+ />
130+ < path
131+ fill = "#FBBC05"
132+ d = "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
133+ />
134+ < path
135+ fill = "#EA4335"
136+ d = "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
137+ />
138+ </ svg >
139+ ) }
140+ < span >
141+ { googleLoading ? "Signing in..." : `Continue with Google` }
142+ </ span >
143+ </ button >
144+
145+ < div className = "flex items-center my-4" >
146+ < div className = "flex-1 h-px bg-gray-600" > </ div >
147+ < span className = "px-3 text-gray-400 text-sm" > or</ span >
148+ < div className = "flex-1 h-px bg-gray-600" > </ div >
149+ </ div >
150+
151+ < form onSubmit = { handleSubmit } className = "space-y-4" >
152+ { mode === "signup" && (
153+ < div >
154+ < label className = "block text-sm font-medium text-gray-300 mb-2" >
155+ Full Name
156+ </ label >
157+ < div className = "relative" >
158+ < User className = "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
159+ < input
160+ type = "text"
161+ value = { displayName }
162+ onChange = { ( e ) => setDisplayName ( e . target . value ) }
163+ className = "w-full pl-10 pr-4 py-3 bg-gray-700 border border-gray-600 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent"
164+ placeholder = "Enter your full name"
165+ required = { mode === "signup" }
166+ />
167+ </ div >
168+ </ div >
169+ ) }
170+
99171 < div >
100172 < label className = "block text-sm font-medium text-gray-300 mb-2" >
101- Full Name
173+ Email Address
102174 </ label >
103175 < div className = "relative" >
104- < User className = "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
176+ < Mail className = "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
105177 < input
106- type = "text "
107- value = { displayName }
108- onChange = { ( e ) => setDisplayName ( e . target . value ) }
178+ type = "email "
179+ value = { email }
180+ onChange = { ( e ) => setEmail ( e . target . value ) }
109181 className = "w-full pl-10 pr-4 py-3 bg-gray-700 border border-gray-600 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent"
110- placeholder = "Enter your full name "
111- required = { mode === "signup" }
182+ placeholder = "Enter your email "
183+ required
112184 />
113185 </ div >
114186 </ div >
115- ) }
116187
117- < div >
118- < label className = "block text-sm font-medium text-gray-300 mb-2" >
119- Email Address
120- </ label >
121- < div className = "relative" >
122- < Mail className = "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
123- < input
124- type = "email"
125- value = { email }
126- onChange = { ( e ) => setEmail ( e . target . value ) }
127- className = "w-full pl-10 pr-4 py-3 bg-gray-700 border border-gray-600 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent"
128- placeholder = "Enter your email"
129- required
130- />
131- </ div >
132- </ div >
133-
134- < div >
135- < label className = "block text-sm font-medium text-gray-300 mb-2" >
136- Password
137- </ label >
138- < div className = "relative" >
139- < Lock className = "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
140- < input
141- type = { showPassword ? "text" : "password" }
142- value = { password }
143- onChange = { ( e ) => setPassword ( e . target . value ) }
144- className = "w-full pl-10 pr-10 py-3 bg-gray-700 border border-gray-600 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent"
145- placeholder = "Enter your password"
146- required
147- />
148- < button
149- type = "button"
150- onClick = { ( ) => setShowPassword ( ! showPassword ) }
151- className = "absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-300"
152- >
153- { showPassword ? (
154- < EyeOff className = "h-4 w-4" />
155- ) : (
156- < Eye className = "h-4 w-4" />
157- ) }
158- </ button >
159- </ div >
160- </ div >
161-
162- { mode === "signup" && (
163188 < div >
164189 < label className = "block text-sm font-medium text-gray-300 mb-2" >
165- Confirm Password
190+ Password
166191 </ label >
167192 < div className = "relative" >
168193 < Lock className = "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
169194 < input
170- type = { showConfirmPassword ? "text" : "password" }
171- value = { confirmPassword }
172- onChange = { ( e ) => setConfirmPassword ( e . target . value ) }
195+ type = { showPassword ? "text" : "password" }
196+ value = { password }
197+ onChange = { ( e ) => setPassword ( e . target . value ) }
173198 className = "w-full pl-10 pr-10 py-3 bg-gray-700 border border-gray-600 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent"
174- placeholder = "Confirm your password"
175- required = { mode === "signup" }
199+ placeholder = "Enter your password"
200+ required
176201 />
177202 < button
178203 type = "button"
179- onClick = { ( ) => setShowConfirmPassword ( ! showConfirmPassword ) }
204+ onClick = { ( ) => setShowPassword ( ! showPassword ) }
180205 className = "absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-300"
181206 >
182- { showConfirmPassword ? (
207+ { showPassword ? (
183208 < EyeOff className = "h-4 w-4" />
184209 ) : (
185210 < Eye className = "h-4 w-4" />
186211 ) }
187212 </ button >
188213 </ div >
189214 </ div >
190- ) }
191215
192- < button
193- type = "submit"
194- disabled = { loading }
195- className = "w-full py-3 bg-gradient-to-r from-cyan-500 to-blue-500 hover:from-cyan-600 hover:to-blue-600 disabled:from-gray-600 disabled:to-gray-600 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-all duration-200"
196- >
197- { loading
198- ? "Processing..."
199- : mode === "login"
200- ? "Sign In"
201- : "Create Account" }
202- </ button >
216+ { mode === "signup" && (
217+ < div >
218+ < label className = "block text-sm font-medium text-gray-300 mb-2" >
219+ Confirm Password
220+ </ label >
221+ < div className = "relative" >
222+ < Lock className = "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
223+ < input
224+ type = { showConfirmPassword ? "text" : "password" }
225+ value = { confirmPassword }
226+ onChange = { ( e ) => setConfirmPassword ( e . target . value ) }
227+ className = "w-full pl-10 pr-10 py-3 bg-gray-700 border border-gray-600 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent"
228+ placeholder = "Confirm your password"
229+ required = { mode === "signup" }
230+ />
231+ < button
232+ type = "button"
233+ onClick = { ( ) => setShowConfirmPassword ( ! showConfirmPassword ) }
234+ className = "absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-300"
235+ >
236+ { showConfirmPassword ? (
237+ < EyeOff className = "h-4 w-4" />
238+ ) : (
239+ < Eye className = "h-4 w-4" />
240+ ) }
241+ </ button >
242+ </ div >
243+ </ div >
244+ ) }
203245
204- < div className = "text-center" >
205246 < button
206- type = "button "
207- onClick = { switchMode }
208- className = "text- cyan-400 hover:text -cyan-300 text-sm font-medium"
247+ type = "submit "
248+ disabled = { loading || googleLoading }
249+ className = "w-full py-3 bg-gradient-to-r from- cyan-500 to-blue-500 hover:from -cyan-600 hover:to-blue-600 disabled:from-gray-600 disabled:to-gray-600 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-all duration-200 "
209250 >
210- { mode === "login"
211- ? "Don't have an account? Sign up"
212- : "Already have an account? Sign in" }
251+ { loading
252+ ? "Processing..."
253+ : mode === "login"
254+ ? "Sign In"
255+ : "Create Account" }
213256 </ button >
214- </ div >
215- </ form >
257+
258+ < div className = "text-center" >
259+ < button
260+ type = "button"
261+ onClick = { switchMode }
262+ className = "text-cyan-400 hover:text-cyan-300 text-sm font-medium"
263+ >
264+ { mode === "login"
265+ ? "Don't have an account? Sign up"
266+ : "Already have an account? Sign in" }
267+ </ button >
268+ </ div >
269+ </ form >
270+ </ div >
216271 </ div >
217272 </ div >
218273 ) ;
0 commit comments