87 lines
2.1 KiB
TypeScript
87 lines
2.1 KiB
TypeScript
"use client"
|
||
|
||
import type { JSX } from "react"
|
||
|
||
import { FunctionComponent } from "react"
|
||
import { useForm } from "react-hook-form"
|
||
|
||
import Link from "next/link"
|
||
import { useRouter } from "next/navigation"
|
||
|
||
import api from "@shared/api"
|
||
import { useCookie } from "@shared/hooks/useCookie"
|
||
import {
|
||
ACCESS_TOKEN_COOKIE,
|
||
REFRESH_TOKEN_COOKIE,
|
||
} from "@shared/lib/constants"
|
||
import { Button, Form, TextField } from "@shared/ui"
|
||
|
||
import { ILoginPageProps } from "./LoginPage.d"
|
||
import styles from "./LoginPage.module.scss"
|
||
|
||
interface ILoginFormData {
|
||
login: string
|
||
password: string
|
||
}
|
||
|
||
export const LoginPage: FunctionComponent<
|
||
ILoginPageProps
|
||
> = (): JSX.Element => {
|
||
const router = useRouter()
|
||
const [, setAccessTokenCookie] = useCookie(ACCESS_TOKEN_COOKIE)
|
||
const [, setRefreshTokenCookie] = useCookie(REFRESH_TOKEN_COOKIE)
|
||
|
||
const { mutate, isPending } = api.useMutation("post", "/auth/login", {
|
||
onSuccess: ({ access, refresh, user }) => {
|
||
setAccessTokenCookie(access)
|
||
setRefreshTokenCookie(refresh)
|
||
router.push("/")
|
||
},
|
||
onError: (error) => {
|
||
console.error("Login failed:", error)
|
||
},
|
||
})
|
||
|
||
const { register, handleSubmit } = useForm<ILoginFormData>()
|
||
|
||
const onSubmit = (data: ILoginFormData): void => {
|
||
mutate({
|
||
body: {
|
||
username: data.login,
|
||
password: data.password,
|
||
},
|
||
})
|
||
}
|
||
|
||
return (
|
||
<div className={styles.root} data-testid="LoginPage">
|
||
<Form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
|
||
<h1 className={styles.title}>Вход</h1>
|
||
<div className={styles.fields}>
|
||
<TextField
|
||
id="login"
|
||
label="Логин"
|
||
placeholder="Ваш логин"
|
||
{...register("login")}
|
||
/>
|
||
<TextField
|
||
id="password"
|
||
label="Пароль"
|
||
placeholder="Ваш пароль"
|
||
type="password"
|
||
{...register("password")}
|
||
/>
|
||
</div>
|
||
<Button type="submit" variant="primary" disabled={isPending}>
|
||
Войти
|
||
</Button>
|
||
<div className={styles.actions}>
|
||
<Link className={styles.link} href="/register">
|
||
Нет аккаунта? Зарегистрироваться
|
||
</Link>
|
||
</div>
|
||
</Form>
|
||
</div>
|
||
)
|
||
}
|