98 lines
No EOL
3.8 KiB
TypeScript
98 lines
No EOL
3.8 KiB
TypeScript
|
|
import React, { useEffect, useState } from 'react';
|
|
import { Link, useLocation, useNavigate } from 'react-router';
|
|
import { useAuth } from '@/context/AuthContext';
|
|
import { login } from "@/utils/api/auth";
|
|
import useRoutes from "@/hooks/useRoutes";
|
|
import SolidButton from "@/components/ui/Buttons/SolidButton";
|
|
import Alert from "@/components/ui/Alert";
|
|
|
|
const LoginForm = () => {
|
|
const { login: authLogin } = useAuth();
|
|
const routes = useRoutes();
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [error, setError] = useState('');
|
|
const [alertSuccess, setAlertSuccess] = useState<string[]>([])
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const searchParams = new URLSearchParams(location.search);
|
|
const isRegistered = searchParams.get('registered') === 'true';
|
|
|
|
useEffect(() => {
|
|
if (isRegistered) {
|
|
setAlertSuccess(['Registration successful!',' You can now log in.']);
|
|
|
|
const timer = setTimeout(() => {
|
|
const params = new URLSearchParams(searchParams.toString());
|
|
params.delete('registered');
|
|
const newUrl = `${window.location.pathname}?${params.toString()}`;
|
|
|
|
navigate(newUrl, { replace: true });
|
|
}, 3000);
|
|
|
|
return () => clearTimeout(timer)
|
|
}
|
|
}, [isRegistered, navigate, searchParams])
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
|
|
try {
|
|
await login(email, password);
|
|
authLogin();
|
|
navigate('/', { replace: true });
|
|
} catch (err) {
|
|
const errorMessage =
|
|
err instanceof Error
|
|
? err.message
|
|
: 'Login failed';
|
|
setError(errorMessage);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div style={{ marginTop: '15vh' }} className="lg:w-1/3 lg:mx-auto">
|
|
<div className="pt-2 text-2xl font-syncopate text-primary">
|
|
DISH PLANNER
|
|
</div>
|
|
<div className="border-2 border-secondary rounded-lg px-5 pt-5 pb-3 lg:pt-10 lg:pb-7">
|
|
{ alertSuccess.length > 0 &&
|
|
<Alert type="success" className="mb-4 px-5 py-2 capitalize text-center">
|
|
{alertSuccess.map((msg, index) => (
|
|
<React.Fragment key={index}>
|
|
{msg}
|
|
<br />
|
|
</React.Fragment>
|
|
))}
|
|
</Alert>
|
|
}
|
|
<form onSubmit={handleSubmit} className="max-w-sm mx-auto flex flex-col">
|
|
{error && <p className="text-red-600 mb-4">{error}</p>}
|
|
<input
|
|
type="email"
|
|
placeholder="Email"
|
|
value={email}
|
|
onChange={e => setEmail(e.target.value)}
|
|
required
|
|
className="w-full p-2 mb-4 border rounded border-secondary bg-gray-600 text-secondary"
|
|
/>
|
|
<input
|
|
type="password"
|
|
placeholder="Password"
|
|
value={password}
|
|
onChange={e => setPassword(e.target.value)}
|
|
required
|
|
className="w-full p-2 mb-4 border rounded text-secondary border-secondary bg-gray-600"
|
|
/>
|
|
<SolidButton type="submit">Login</SolidButton>
|
|
<Link to={routes.auth.register()} className="lowercase hover:underline text-center mt-1 text-secondary underline">
|
|
Create an account
|
|
</Link>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default LoginForm |