trip-planner/frontend/src/components/LoginForm.jsx
myrmidex 8c68cdfe9f Implement Sanctum (#23)
Reviewed-on: https://codeberg.org/lvl0/trip-planner/pulls/23
Co-authored-by: myrmidex <myrmidex@myrmidex.net>
Co-committed-by: myrmidex <myrmidex@myrmidex.net>
2025-09-26 21:50:44 +02:00

120 lines
No EOL
3.5 KiB
JavaScript

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;