11import { useState } from 'react' ;
22import { useAuth } from '@/context/AuthContext' ;
33import { motion } from 'framer-motion' ;
4+ import { Eye , EyeOff } from 'lucide-react' ;
45
56export default function LoginForm ( { onSuccess, onBack, theme } ) {
67 const [ formData , setFormData ] = useState ( {
78 email : '' ,
89 password : '' ,
9- rememberMe : false
10+ rememberMe : false ,
1011 } ) ;
1112 const [ errors , setErrors ] = useState ( { } ) ;
1213 const [ isLoading , setIsLoading ] = useState ( false ) ;
13-
14+ const [ showPassword , setShowPassword ] = useState ( false ) ;
15+
1416 const { login } = useAuth ( ) ;
1517
1618 const validateForm = ( ) => {
1719 const newErrors = { } ;
18-
20+
1921 if ( ! formData . email ) {
2022 newErrors . email = 'Email is required' ;
2123 } else if ( ! / \S + @ \S + \. \S + / . test ( formData . email ) ) {
2224 newErrors . email = 'Email is invalid' ;
2325 }
24-
26+
2527 if ( ! formData . password ) {
2628 newErrors . password = 'Password is required' ;
2729 }
28-
30+
2931 setErrors ( newErrors ) ;
3032 return Object . keys ( newErrors ) . length === 0 ;
3133 } ;
3234
3335 const handleSubmit = async ( e ) => {
3436 e . preventDefault ( ) ;
35-
37+
3638 if ( ! validateForm ( ) ) return ;
37-
39+
3840 setIsLoading ( true ) ;
3941 try {
40- const result = await login ( formData . email , formData . password , formData . rememberMe ) ;
42+ const result = await login (
43+ formData . email ,
44+ formData . password ,
45+ formData . rememberMe ,
46+ ) ;
4147 onSuccess ( result ) ;
4248 } catch ( error ) {
4349 setErrors ( { submit : error . message } ) ;
@@ -48,13 +54,13 @@ export default function LoginForm({ onSuccess, onBack, theme }) {
4854
4955 const handleChange = ( e ) => {
5056 const { name, value, type, checked } = e . target ;
51- setFormData ( prev => ( {
57+ setFormData ( ( prev ) => ( {
5258 ...prev ,
53- [ name ] : type === 'checkbox' ? checked : value
59+ [ name ] : type === 'checkbox' ? checked : value ,
5460 } ) ) ;
55-
61+
5662 if ( errors [ name ] ) {
57- setErrors ( prev => ( { ...prev , [ name ] : '' } ) ) ;
63+ setErrors ( ( prev ) => ( { ...prev , [ name ] : '' } ) ) ;
5864 }
5965 } ;
6066
@@ -77,8 +83,11 @@ export default function LoginForm({ onSuccess, onBack, theme }) {
7783 < p className = "text-white/70" > Sign in to continue to OrbitOS</ p >
7884 </ div >
7985
86+ { /** Login Form */ }
87+
8088 < form onSubmit = { handleSubmit } className = "space-y-6" >
8189 < div className = "space-y-4" >
90+ { /** Email */ }
8291 < div >
8392 < label className = "block text-sm font-medium text-white/90 mb-2" >
8493 Email Address
@@ -103,21 +112,39 @@ export default function LoginForm({ onSuccess, onBack, theme }) {
103112 </ motion . p >
104113 ) }
105114 </ div >
106-
107- < div >
115+ { /** Password */ }
116+ < div className = "relative mb-4" >
108117 < label className = "block text-sm font-medium text-white/90 mb-2" >
109118 Password
110119 </ label >
111- < input
112- type = "password"
113- name = "password"
114- value = { formData . password }
115- onChange = { handleChange }
116- className = { `w-full px-4 py-3 rounded-xl bg-white/5 border ${
117- errors . password ? 'border-red-400' : 'border-white/20'
118- } text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all backdrop-blur-sm`}
119- placeholder = "Enter your password"
120- />
120+
121+ { /* Input Wrapper with Icon */ }
122+ < div className = "relative" >
123+ < input
124+ type = { showPassword ? 'text' : 'password' }
125+ name = "password"
126+ value = { formData . password }
127+ onChange = { handleChange }
128+ className = { `w-full px-4 py-3 pr-10 rounded-xl bg-white/5 border ${
129+ errors . password ? 'border-red-400' : 'border-white/20'
130+ } text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all backdrop-blur-sm`}
131+ placeholder = "Enter your password"
132+ />
133+
134+ { /* Eye Icon */ }
135+ < span
136+ onClick = { ( ) => setShowPassword ( ! showPassword ) }
137+ className = "absolute right-4 top-1/2 -translate-y-1/2 text-white/70 cursor-pointer hover:text-white transition-colors"
138+ >
139+ { showPassword ? (
140+ < Eye size = { 18 } strokeWidth = { 2 } />
141+ ) : (
142+ < EyeOff size = { 18 } strokeWidth = { 2 } />
143+ ) }
144+ </ span >
145+ </ div >
146+
147+ { /* Error Message */ }
121148 { errors . password && (
122149 < motion . p
123150 initial = { { opacity : 0 , y : - 10 } }
@@ -141,7 +168,10 @@ export default function LoginForm({ onSuccess, onBack, theme }) {
141168 />
142169 < span className = "ml-2 text-sm text-white/80" > Remember me</ span >
143170 </ label >
144- < button type = "button" className = "text-sm text-blue-400 hover:text-blue-300 transition-colors" >
171+ < button
172+ type = "button"
173+ className = "text-sm text-blue-400 hover:text-blue-300 transition-colors"
174+ >
145175 Forgot password?
146176 </ button >
147177 </ div >
@@ -176,4 +206,4 @@ export default function LoginForm({ onSuccess, onBack, theme }) {
176206 </ div >
177207 </ motion . div >
178208 ) ;
179- }
209+ }
0 commit comments