@@ -4,44 +4,75 @@ import { Link, useNavigate } from "react-router";
44
55import { useAuth } from "../hooks/useAuth" ;
66import Input from "@/Component/ui/Input" ;
7- import { useCallback } from "react" ;
7+ import { useCallback , useState } from "react" ;
88
99const LoginPage = ( ) => {
1010 const { loginMutation } = useAuth ( ) ;
1111
1212 const navigate = useNavigate ( ) ;
1313
14+ const [ fieldErrors , setFieldErrors ] = useState < { email ?: string ; password ?: string } > ( { } ) ;
15+ const [ serverError , setServerError ] = useState < string | null > ( null ) ;
16+
17+ const validateFields = useCallback ( ( email : string , password : string ) : boolean => {
18+ const errors : { email ?: string ; password ?: string } = { } ;
19+
20+ if ( ! email . trim ( ) ) {
21+ errors . email = "Email is required" ;
22+ } else if ( ! / ^ [ ^ \s @ ] + @ [ ^ \s @ ] + \. [ ^ \s @ ] + $ / . test ( email ) ) {
23+ errors . email = "Please enter a valid email address" ;
24+ }
25+
26+ if ( ! password ) {
27+ errors . password = "Password is required" ;
28+ }
29+
30+ setFieldErrors ( errors ) ;
31+ return Object . keys ( errors ) . length === 0 ;
32+ } , [ ] ) ;
33+
1434 const handleLogin = useCallback (
1535 async ( e : React . FormEvent < HTMLFormElement > ) => {
1636 e . preventDefault ( ) ;
37+ setServerError ( null ) ;
1738
1839 const formData = new FormData ( e . currentTarget ) ;
1940
2041 const email = formData . get ( "email" ) as string ;
2142 const password = formData . get ( "password" ) as string ;
2243
44+ if ( ! validateFields ( email , password ) ) {
45+ return ;
46+ }
47+
2348 try {
2449 const response = await loginMutation . mutateAsync ( {
2550 email,
2651 password,
2752 } ) ;
2853
2954 const Role = response . data . role ;
30- console . log ( "User role:" , Role ) ;
3155
3256 if ( Role === "organization" ) {
3357 navigate ( "/org/dashboard" ) ;
3458 return ;
3559 }
3660
37- console . log ( "Login successful:" , response ) ;
61+ if ( Role === "member" ) {
62+ navigate ( "/member/dashboard" ) ;
63+ return ;
64+ }
3865
39- // redirect / save token / navigate
40- } catch ( error ) {
41- console . error ( "Login failed:" , error ) ;
66+ navigate ( "/" ) ;
67+ } catch ( error : any ) {
68+ const message =
69+ error ?. response ?. data ?. message ||
70+ error ?. message ||
71+ "Login failed. Please check your credentials and try again." ;
72+ setServerError ( message ) ;
4273 }
4374 } ,
44- [ loginMutation ] ,
75+ [ loginMutation , navigate , validateFields ] ,
4576 ) ;
4677
4778 return (
@@ -62,7 +93,12 @@ const LoginPage = () => {
6293 < div className = "w-[80%]" >
6394 < h2 className = "text-3xl mb-2 inter text-gray-700" > Sign in</ h2 >
6495 < p className = "text-gray-500 mb-6 inter" > Please login to your account to continue.</ p >
65- < form className = "space-y-4 mt-[7vh]" onSubmit = { handleLogin } >
96+ < form className = "space-y-4 mt-[7vh]" onSubmit = { handleLogin } noValidate >
97+ { serverError && (
98+ < div className = "bg-red-50 border border-red-300 text-red-700 px-4 py-3 rounded-md text-sm inter" >
99+ { serverError }
100+ </ div >
101+ ) }
66102 < div className = "flex flex-col gap-2 text-md" >
67103 < label
68104 htmlFor = "email"
@@ -72,10 +108,15 @@ const LoginPage = () => {
72108 </ label >
73109 < Input
74110 name = "email"
75- className = "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
111+ className = { `w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
112+ fieldErrors . email ? "border-red-500" : "border-gray-300"
113+ } `}
76114 placeholder = "Enter your email"
77115 type = "email"
78116 />
117+ { fieldErrors . email && (
118+ < p className = "text-red-500 text-xs inter" > { fieldErrors . email } </ p >
119+ ) }
79120 </ div >
80121 < div className = "flex flex-col gap-2" >
81122 < label
@@ -93,16 +134,22 @@ const LoginPage = () => {
93134
94135 < Input
95136 name = "password"
96- className = "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
137+ className = { `w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
138+ fieldErrors . password ? "border-red-500" : "border-gray-300"
139+ } `}
97140 placeholder = "Enter your password"
98141 type = "password"
99142 />
143+ { fieldErrors . password && (
144+ < p className = "text-red-500 text-xs inter" > { fieldErrors . password } </ p >
145+ ) }
100146 </ div >
101147 < button
102148 type = "submit"
103- className = "w-full bg-[#4f46e5] text-white py-2 hover:bg-blue-600 transition duration-200 inter py-[1.5vh] text-lg"
149+ disabled = { loginMutation . isPending }
150+ className = "w-full bg-[#4f46e5] text-white py-2 hover:bg-blue-600 transition duration-200 inter py-[1.5vh] text-lg disabled:opacity-50 disabled:cursor-not-allowed"
104151 >
105- Sign In
152+ { loginMutation . isPending ? "Signing In..." : " Sign In" }
106153 </ button >
107154
108155 < div className = "flex justify-end" >
0 commit comments