79 lines
2.6 KiB
TypeScript
79 lines
2.6 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { useAuth } from '../../context/AuthContext.tsx';
|
|
import { errorMessage } from '../../services/apiClient.ts';
|
|
|
|
const LoginForm: React.FC = () => {
|
|
const { login } = useAuth();
|
|
const [userLogin, setUserLogin] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [error, setError] = useState('');
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setError('');
|
|
setIsLoading(true);
|
|
try {
|
|
await login(userLogin, password);
|
|
} catch (err) {
|
|
setError(errorMessage(err));
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<form onSubmit={(e) => void handleSubmit(e)} className="space-y-6">
|
|
{error && (
|
|
<div className="rounded-lg bg-red-50 text-red-700 text-sm px-3 py-2 border border-red-100">
|
|
{error}
|
|
</div>
|
|
)}
|
|
<div>
|
|
<label htmlFor="user_login" className="block text-sm font-medium text-gray-700">
|
|
Login
|
|
</label>
|
|
<div className="mt-1">
|
|
<input
|
|
id="user_login"
|
|
name="user_login"
|
|
type="text"
|
|
autoComplete="username"
|
|
required
|
|
value={userLogin}
|
|
onChange={(e) => setUserLogin(e.target.value)}
|
|
className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
|
|
placeholder="Login pengguna"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label htmlFor="password" className="block text-sm font-medium text-gray-700">
|
|
Kata Sandi
|
|
</label>
|
|
<div className="mt-1">
|
|
<input
|
|
id="password"
|
|
name="password"
|
|
type="password"
|
|
autoComplete="current-password"
|
|
required
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
disabled={isLoading}
|
|
className="w-full flex justify-center py-2.5 px-4 border border-transparent rounded-md shadow-sm text-sm font-semibold text-white bg-red-600 hover:bg-red-700 disabled:opacity-60"
|
|
>
|
|
{isLoading ? 'Masuk...' : 'Masuk'}
|
|
</button>
|
|
</form>
|
|
);
|
|
};
|
|
|
|
export default LoginForm;
|