102 lines
2.7 KiB
TypeScript
102 lines
2.7 KiB
TypeScript
import toast from "react-hot-toast";
|
||
import Input from "../components/Input";
|
||
import useAuthStore from "../stores/useAuthStore";
|
||
import api from "../utils/api";
|
||
import { useState } from "react";
|
||
import { HTTPError } from "ky";
|
||
import { IError } from "../types/IError";
|
||
import { useNavigate } from "react-router";
|
||
import Button from "../components/Button";
|
||
|
||
function LoginPage() {
|
||
const navigate = useNavigate();
|
||
const { setToken } = useAuthStore();
|
||
const [email, setEmail] = useState("");
|
||
const [password, setPassword] = useState("");
|
||
|
||
async function login() {
|
||
return await api
|
||
.post("auth/login", {
|
||
json: {
|
||
email,
|
||
password,
|
||
},
|
||
})
|
||
.json<{ token: string }>();
|
||
}
|
||
|
||
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||
e.preventDefault();
|
||
|
||
let result;
|
||
|
||
try {
|
||
result = await login();
|
||
} catch (error) {
|
||
toast.error((await (error as HTTPError).response.json<IError>()).error);
|
||
}
|
||
|
||
if (!result?.token) {
|
||
return;
|
||
}
|
||
|
||
setToken(result.token);
|
||
navigate("/");
|
||
}
|
||
|
||
return (
|
||
<div className="h-dvh flex flex-col items-center p-8 bg-[#F6F6F6]">
|
||
<div className="flex-1 flex flex-col gap-4 justify-between w-[380px]">
|
||
<div className="flex flex-col items-center justify-between gap-4">
|
||
<img src="/logo-mate.svg" alt="logo" />
|
||
</div>
|
||
<div>
|
||
<form onSubmit={handleSubmit}>
|
||
<div>
|
||
<Input
|
||
label="Email"
|
||
type="email"
|
||
required
|
||
value={email}
|
||
onChange={(e) => setEmail(e.target.value)}
|
||
/>
|
||
</div>
|
||
<div className="mt-6">
|
||
<Input
|
||
label="Пароль"
|
||
type="password"
|
||
required
|
||
value={password}
|
||
onChange={(e) => setPassword(e.target.value)}
|
||
/>
|
||
</div>
|
||
<div className="mt-3">
|
||
<Button type="button" variant="secondary">
|
||
Забыли пароль?
|
||
</Button>
|
||
</div>
|
||
<div className="mt-6">
|
||
<Button
|
||
type="submit"
|
||
variant="cta"
|
||
size="large"
|
||
className="w-full"
|
||
>
|
||
Войти
|
||
</Button>
|
||
</div>
|
||
<div className="mt-6">
|
||
<Button type="button" variant="secondary" className="mx-auto">
|
||
Нет данных для входа?
|
||
</Button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div className="h-[30px]"></div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default LoginPage;
|