120 lines
3.5 KiB
React
120 lines
3.5 KiB
React
|
|
import { useState } from 'react';
|
||
|
|
import api from '../utils/api';
|
||
|
|
|
||
|
|
const LoginForm = ({ onLoginSuccess }) => {
|
||
|
|
const [formData, setFormData] = useState({
|
||
|
|
email: '',
|
||
|
|
password: ''
|
||
|
|
});
|
||
|
|
|
||
|
|
const [errors, setErrors] = useState({});
|
||
|
|
const [isLoading, setIsLoading] = useState(false);
|
||
|
|
|
||
|
|
const handleChange = (e) => {
|
||
|
|
const { name, value } = e.target;
|
||
|
|
setFormData(prevState => ({
|
||
|
|
...prevState,
|
||
|
|
[name]: value
|
||
|
|
}));
|
||
|
|
|
||
|
|
if (errors[name]) {
|
||
|
|
setErrors(prevErrors => ({
|
||
|
|
...prevErrors,
|
||
|
|
[name]: ''
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleSubmit = async (e) => {
|
||
|
|
e.preventDefault();
|
||
|
|
setIsLoading(true);
|
||
|
|
setErrors({});
|
||
|
|
|
||
|
|
try {
|
||
|
|
const response = await api.post('/login', formData);
|
||
|
|
|
||
|
|
if (response.data.success) {
|
||
|
|
localStorage.setItem('token', response.data.data.access_token);
|
||
|
|
localStorage.setItem('user', JSON.stringify(response.data.data.user));
|
||
|
|
|
||
|
|
if (onLoginSuccess) {
|
||
|
|
onLoginSuccess(response.data.data);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
if (error.response && error.response.status === 422) {
|
||
|
|
// Validation errors - check both .data and .errors structure
|
||
|
|
const validationErrors = error.response.data.errors || error.response.data.data || {};
|
||
|
|
|
||
|
|
// If it's credential error, show as general message
|
||
|
|
if (validationErrors.email && validationErrors.email[0] === 'The provided credentials are incorrect.') {
|
||
|
|
setErrors({ general: 'Invalid email or password. Please try again.' });
|
||
|
|
} else {
|
||
|
|
setErrors(validationErrors);
|
||
|
|
}
|
||
|
|
} else if (error.response && error.response.status === 401) {
|
||
|
|
// Unauthorized - wrong credentials
|
||
|
|
setErrors({ general: 'Invalid email or password. Please try again.' });
|
||
|
|
} else if (error.response && error.response.data.message) {
|
||
|
|
// Other server errors
|
||
|
|
setErrors({ general: error.response.data.message });
|
||
|
|
} else if (error.request) {
|
||
|
|
// Network error
|
||
|
|
setErrors({ general: 'Unable to connect to server. Please check your connection.' });
|
||
|
|
} else {
|
||
|
|
// Unknown error
|
||
|
|
setErrors({ general: 'Unknown error occurred. Please try again.' });
|
||
|
|
}
|
||
|
|
} finally {
|
||
|
|
setIsLoading(false);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="login-form">
|
||
|
|
<h2>Login</h2>
|
||
|
|
|
||
|
|
{errors.general && (
|
||
|
|
<div className="alert alert-error">
|
||
|
|
{errors.general}
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
<form onSubmit={handleSubmit}>
|
||
|
|
<div className="form-group">
|
||
|
|
<label htmlFor="email">Email:</label>
|
||
|
|
<input
|
||
|
|
type="email"
|
||
|
|
id="email"
|
||
|
|
name="email"
|
||
|
|
value={formData.email}
|
||
|
|
onChange={handleChange}
|
||
|
|
required
|
||
|
|
className={errors.email ? 'error' : ''}
|
||
|
|
/>
|
||
|
|
{errors.email && <span className="error-message">{errors.email[0]}</span>}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="form-group">
|
||
|
|
<label htmlFor="password">Password:</label>
|
||
|
|
<input
|
||
|
|
type="password"
|
||
|
|
id="password"
|
||
|
|
name="password"
|
||
|
|
value={formData.password}
|
||
|
|
onChange={handleChange}
|
||
|
|
required
|
||
|
|
className={errors.password ? 'error' : ''}
|
||
|
|
/>
|
||
|
|
{errors.password && <span className="error-message">{errors.password[0]}</span>}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<button type="submit" disabled={isLoading}>
|
||
|
|
{isLoading ? 'Logging in...' : 'Login'}
|
||
|
|
</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default LoginForm;
|