From 925a214a3f349483a0989c64c5226447e0a3812c Mon Sep 17 00:00:00 2001 From: Mgrdich Date: Sat, 11 May 2024 06:12:21 +0400 Subject: [PATCH] Working Login --- frontend/.eslintrc | 1 + frontend/src/hooks/api/constants.ts | 2 + frontend/src/hooks/useLogin.ts | 22 ++++++++++ frontend/src/hooks/useRegister.ts | 24 ++++++++++ frontend/src/pages/Auth/Login.tsx | 44 ++++++++++++++----- .../Auth/components/FormSubmitButton.tsx | 11 ++++- frontend/src/ui/Input.tsx | 8 ++-- frontend/src/ui/InputWithLabel.tsx | 1 + 8 files changed, 97 insertions(+), 16 deletions(-) create mode 100644 frontend/src/hooks/useLogin.ts create mode 100644 frontend/src/hooks/useRegister.ts diff --git a/frontend/.eslintrc b/frontend/.eslintrc index 8e4e90c..220412a 100644 --- a/frontend/.eslintrc +++ b/frontend/.eslintrc @@ -40,6 +40,7 @@ } }, "rules": { + "implicit-arrow-linebreak": "off", "@typescript-eslint/no-unused-vars": "off", "no-unused-vars": "off", "object-curly-newline": "off", diff --git a/frontend/src/hooks/api/constants.ts b/frontend/src/hooks/api/constants.ts index 4a7f935..185ffc5 100644 --- a/frontend/src/hooks/api/constants.ts +++ b/frontend/src/hooks/api/constants.ts @@ -14,3 +14,5 @@ export const getContinueConversationPath = (id: ConversationId) => `${getConvers // User export const UserPath = `${basePath}/me`; +export const LoginPath = `${basePath}/login`; +export const RegisterPath = `${basePath}/register`; diff --git a/frontend/src/hooks/useLogin.ts b/frontend/src/hooks/useLogin.ts new file mode 100644 index 0000000..31b0b1e --- /dev/null +++ b/frontend/src/hooks/useLogin.ts @@ -0,0 +1,22 @@ +import { useMutation } from "@tanstack/react-query"; +import useApi from "./useApi.ts"; +import { LoginPath } from "./api/constants.ts"; +import { useAuth } from "../context/AuthContext.tsx"; + +interface LoginRequest { + username: string; + password: string; +} + +export default function useLogin() { + const callApi = useApi(); + const { setToken } = useAuth(); + + return useMutation({ + mutationFn: ({ username, password }: LoginRequest) => + callApi<{ token: string }>({ url: LoginPath, body: { username, password }, method: "POST" }), + onSuccess: (res) => { + setToken(res.token); + }, + }); +} diff --git a/frontend/src/hooks/useRegister.ts b/frontend/src/hooks/useRegister.ts new file mode 100644 index 0000000..98d4386 --- /dev/null +++ b/frontend/src/hooks/useRegister.ts @@ -0,0 +1,24 @@ +import { useMutation } from "@tanstack/react-query"; +import { RolesType } from "models/User.ts"; +import useApi from "./useApi.ts"; +import { LoginPath } from "./api/constants.ts"; + +interface RegisterRequest { + username: string; + firstname: string; + lastname: string; + role: RolesType; + password: string; +} + +export default function useRegister() { + const callApi = useApi(); + return useMutation({ + mutationFn: ({ username, password, firstname, lastname, role }: RegisterRequest) => + callApi<{ name: string }>({ + url: LoginPath, + body: { username, password, firstname, lastname, role }, + method: "POST", + }), + }); +} diff --git a/frontend/src/pages/Auth/Login.tsx b/frontend/src/pages/Auth/Login.tsx index b0603d6..0a64aec 100644 --- a/frontend/src/pages/Auth/Login.tsx +++ b/frontend/src/pages/Auth/Login.tsx @@ -1,37 +1,59 @@ import InputWithLabel from "ui/InputWithLabel.tsx"; -import Checkbox from "ui/Checkbox.tsx"; import LinkText from "ui/LinkText.tsx"; -import FormSubmitButton from "./components/FormSubmitButton.tsx"; +import { useState } from "react"; +import useLogin from "hooks/useLogin.ts"; +import { useNavigate } from "react-router-dom"; +import Button from "ui/Button.tsx"; function Login() { + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + const { mutateAsync, isPending } = useLogin(); + const navigate = useNavigate(); + + const onSubmit = async () => { + await mutateAsync({ username, password }); + navigate("/conversation"); + }; + return (

Welcome Back :)

-
+
- + setUsername(e.currentTarget.value)} + />
- + setPassword(e.currentTarget.value)} + />
-
- - Remember me -
Forgot password ?
- Sign In +
Not a member? Register
- +
); diff --git a/frontend/src/pages/Auth/components/FormSubmitButton.tsx b/frontend/src/pages/Auth/components/FormSubmitButton.tsx index fd41bde..039cfcc 100644 --- a/frontend/src/pages/Auth/components/FormSubmitButton.tsx +++ b/frontend/src/pages/Auth/components/FormSubmitButton.tsx @@ -1,13 +1,20 @@ import { PropsWithChildren } from "react"; -function FormSubmitButton({ children }: PropsWithChildren) { +interface FormSubmitButtonProps extends PropsWithChildren { + disabled: boolean; +} + +function FormSubmitButton({ children, disabled }: FormSubmitButtonProps) { return ( diff --git a/frontend/src/ui/Input.tsx b/frontend/src/ui/Input.tsx index ae44811..8fd65ab 100644 --- a/frontend/src/ui/Input.tsx +++ b/frontend/src/ui/Input.tsx @@ -1,13 +1,15 @@ import { ComponentProps } from "react"; import { twMerge } from "tailwind-merge"; -interface InputProps extends Omit, "type"> {} +interface InputProps extends Omit, "type"> { + type: "text" | "password"; +} -export default function Input({ className, ...rest }: InputProps) { +export default function Input({ type = "text", className, ...rest }: InputProps) { return ( { label: string; + type: "text" | "password"; } function InputWithLabel({ label, name, ...rest }: InputWithLabelProps) {