11import React , { useState } from "react" ;
2- import { useNavigate } from "react-router-dom" ;
3- import { toast } from "react-hot-toast " ;
4- import axios from "axios" ;
5- import { useAuth } from "../context/AuthContext" ;
2+ import { FaRegEye , FaRegEyeSlash } from "react-icons/fa" ;
3+ import { useNavigate } from "react-router-dom " ;
4+ import { ClipLoader } from "react-spinners" ;
5+ import { loginUser } from "../services/authService" ;
66
7- export default function Login ( ) {
7+ const Login = ( ) => {
88 const [ email , setEmail ] = useState ( "" ) ;
99 const [ password , setPassword ] = useState ( "" ) ;
10- const [ loading , setLoading ] = useState ( false ) ;
11-
12- const { login } = useAuth ( ) ;
13- const navigate = useNavigate ( ) ;
10+ const [ showPassword , setShowPassword ] = useState ( false ) ;
11+ const [ err , setErr ] = useState ( "" ) ;
12+ const [ loading , setLoading ] = useState ( false ) ;
13+ const navigate = useNavigate ( ) ;
1414
1515 const handleLogin = async ( e ) => {
1616 e . preventDefault ( ) ;
17+ setErr ( "" ) ;
1718 setLoading ( true ) ;
18- const loadingToast = toast . loading ( "Logging in..." ) ;
19-
2019 try {
21-
22- const { data } = await axios . post (
23- "/api/v1/user/login" ,
24- { email, password } ,
25- {
26- headers : { "Content-Type" : "application/json" } ,
27- withCredentials : true ,
28- }
29- ) ;
30-
31-
32- toast . dismiss ( loadingToast ) ;
33-
34- if ( data . success ) {
35- toast . success ( data . message || "Logged in successfully!" ) ;
36- login ( data . user ) ;
37- navigate ( "/dashboard" ) ;
38- } else {
39-
40- toast . error ( data . message || "Login failed. Please try again." ) ;
41- }
42-
20+ const result = await loginUser ( { email, password } ) ;
21+ console . log ( result . data ) ;
22+ setLoading ( false ) ;
23+ navigate ( "/" ) ; // Redirect on success
4324 } catch ( error ) {
44-
45- console . error ( "Login error:" , error ) ;
46- toast . dismiss ( loadingToast ) ; // Dismiss loading toast
47-
48-
49- const errorMessage =
50- error . response ?. data ?. message || "Login failed. Please check your credentials." ;
51- toast . error ( errorMessage ) ;
52-
53- } finally {
54- setLoading ( false ) ;
25+ setErr ( error ?. response ?. data ?. message || error . message || "Login failed." ) ;
26+ setLoading ( false ) ;
5527 }
5628 } ;
5729
5830 return (
59- < div className = "page login" >
60- < h1 > Login</ h1 >
61- < form onSubmit = { handleLogin } >
62- < input
63- type = "email"
64- placeholder = "Email"
65- value = { email }
66- onChange = { ( e ) => setEmail ( e . target . value ) }
67- required
68- />
69- < input
70- type = "password"
71- placeholder = "Password"
72- value = { password }
73- onChange = { ( e ) => setPassword ( e . target . value ) }
74- required
75- />
76-
77- < button type = "submit" disabled = { loading } >
78- { loading ? "Logging in..." : "Login" }
79- </ button >
80- </ form >
31+ < div className = "min-h-screen flex items-center justify-center bg-gray-900 p-6" >
32+ < div className = "bg-gray-800 rounded-2xl shadow-2xl w-full max-w-md p-10 border border-gray-700" >
33+ < h1 className = "text-4xl font-extrabold mb-4 text-cyan-400 text-center" > MailMERN</ h1 >
34+ < p className = "text-gray-400 mb-8 text-center" > Sign in to your account</ p >
35+
36+ < form onSubmit = { handleLogin } className = "space-y-6" >
37+ < div >
38+ < label htmlFor = "email" className = "block mb-2 font-medium text-gray-300" > Email</ label >
39+ < input
40+ type = "email"
41+ id = "email"
42+ placeholder = "Enter your Email"
43+ value = { email }
44+ onChange = { ( e ) => setEmail ( e . target . value ) }
45+ required
46+ className = "w-full px-4 py-3 rounded-xl border border-gray-700 bg-gray-900 text-gray-100 focus:outline-none focus:ring-2 focus:ring-cyan-400 transition"
47+ />
48+ </ div >
49+
50+ < div >
51+ < label htmlFor = "password" className = "block mb-2 font-medium text-gray-300" > Password</ label >
52+ < div className = "relative" >
53+ < input
54+ type = { showPassword ? "text" : "password" }
55+ id = "password"
56+ placeholder = "Enter your password"
57+ value = { password }
58+ onChange = { ( e ) => setPassword ( e . target . value ) }
59+ required
60+ className = "w-full px-4 py-3 rounded-xl border border-gray-700 bg-gray-900 text-gray-100 focus:outline-none focus:ring-2 focus:ring-cyan-400 pr-12 transition"
61+ />
62+ < button
63+ type = "button"
64+ onClick = { ( ) => setShowPassword ( prev => ! prev ) }
65+ className = "absolute right-3 top-3 text-gray-400 hover:text-cyan-400 transition"
66+ >
67+ { showPassword ? < FaRegEyeSlash /> : < FaRegEye /> }
68+ </ button >
69+ </ div >
70+ </ div >
71+
72+ < div className = "text-right" >
73+ < button
74+ type = "button"
75+ onClick = { ( ) => navigate ( "/forgot-password" ) }
76+ className = "text-cyan-400 font-medium hover:underline transition"
77+ >
78+ Forgot Password?
79+ </ button >
80+ </ div >
81+
82+ { err && < p className = "text-red-500 text-center" > { err } </ p > }
83+
84+ < button
85+ type = "submit"
86+ disabled = { loading }
87+ className = "w-full flex items-center justify-center gap-2 bg-gradient-to-r from-cyan-500 to-blue-500 text-white font-bold py-3 rounded-full shadow-lg hover:scale-105 transition-transform duration-300"
88+ >
89+ { loading ? < ClipLoader size = { 20 } color = "white" /> : "Sign In" }
90+ </ button >
91+ </ form >
92+
93+ < p className = "mt-6 text-center text-gray-300" >
94+ Don't have an account?{ " " }
95+ < span
96+ onClick = { ( ) => navigate ( "/register" ) }
97+ className = "text-cyan-400 font-semibold cursor-pointer hover:underline"
98+ >
99+ Sign Up
100+ </ span >
101+ </ p >
102+ </ div >
81103 </ div >
82104 ) ;
83- }
105+ } ;
106+
107+ export default Login ;
0 commit comments