Skip to content

Commit

Permalink
Working Login
Browse files Browse the repository at this point in the history
  • Loading branch information
Mgrdich committed May 11, 2024
1 parent 0695ab0 commit 925a214
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 16 deletions.
1 change: 1 addition & 0 deletions frontend/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
}
},
"rules": {
"implicit-arrow-linebreak": "off",
"@typescript-eslint/no-unused-vars": "off",
"no-unused-vars": "off",
"object-curly-newline": "off",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/hooks/api/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
22 changes: 22 additions & 0 deletions frontend/src/hooks/useLogin.ts
Original file line number Diff line number Diff line change
@@ -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);
},
});
}
24 changes: 24 additions & 0 deletions frontend/src/hooks/useRegister.ts
Original file line number Diff line number Diff line change
@@ -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",
}),
});
}
44 changes: 33 additions & 11 deletions frontend/src/pages/Auth/Login.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="bg-neutral-50 min-h-screen flex flex-col items-center justify-center dark:bg-neutral-900">
<h1 className="mt-0 mb-16 text-5xl text-white font-bold tracking-tight md:text-5xl xl:text-5xl self-center">
Welcome Back :)
</h1>
<div className="block p-6 rounded-lg shadow-lg bg-white max-w-sm">
<form>
<div>
<div className="form-group mb-6">
<InputWithLabel label="Email" name="email" type="text" placeholder="Enter Email" />
<InputWithLabel
label="Username"
name="username"
type="text"
placeholder="Enter Username"
onInput={(e) => setUsername(e.currentTarget.value)}
/>
</div>
<div className="form-group mb-6">
<InputWithLabel label="Password" type="password" name="password" placeholder="Enter Password" />
<InputWithLabel
label="Password"
type="password"
name="password"
placeholder="Enter Password"
onInput={(e) => setPassword(e.currentTarget.value)}
/>
</div>
<div className="flex justify-between items-center mb-6">
<div className="form-group form-check">
<Checkbox name="remeber_me" />
<span className="form-check-label inline-block text-gray-800">Remember me</span>
</div>
<div className="ml-4">
<LinkText to="/forgot-password">Forgot password ?</LinkText>
</div>
</div>
<FormSubmitButton>Sign In</FormSubmitButton>
<Button disabled={isPending} className="w-full" onClick={onSubmit}>
Sign In
</Button>
<div className="text-gray-800 mt-6 text-center">
Not a member?
<LinkText to="/register">Register</LinkText>
</div>
</form>
</div>
</div>
</div>
);
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/pages/Auth/components/FormSubmitButton.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { PropsWithChildren } from "react";

function FormSubmitButton({ children }: PropsWithChildren) {
interface FormSubmitButtonProps extends PropsWithChildren {
disabled: boolean;
}

function FormSubmitButton({ children, disabled }: FormSubmitButtonProps) {
return (
<button
type="submit"
disabled={disabled}
className="w-full px-6 py-2.5 bg-blue-600 text-white font-medium text-xs
leading-tight uppercase rounded shadow-md hover:bg-blue-700 hover:shadow-lg focus:bg-blue-700
focus:shadow-lg focus:outline-none focus:ring-0
active:bg-blue-800 active:shadow-lg transition duration-150 ease-in-out"
active:bg-blue-800 active:shadow-lg transition duration-150 ease-in-out
disabled:bg-blue-200
"
>
{children}
</button>
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/ui/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { ComponentProps } from "react";
import { twMerge } from "tailwind-merge";

interface InputProps extends Omit<ComponentProps<"input">, "type"> {}
interface InputProps extends Omit<ComponentProps<"input">, "type"> {
type: "text" | "password";
}

export default function Input({ className, ...rest }: InputProps) {
export default function Input({ type = "text", className, ...rest }: InputProps) {
return (
<input
{...rest}
type="text"
type={type}
className={twMerge(
"form-control block w-full px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding" +
" border border-solid border-gray-300 rounded transition ease-in-out m-0 " +
Expand Down
1 change: 1 addition & 0 deletions frontend/src/ui/InputWithLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Input from "./Input.tsx";

interface InputWithLabelProps extends ComponentProps<"input"> {
label: string;
type: "text" | "password";
}

function InputWithLabel({ label, name, ...rest }: InputWithLabelProps) {
Expand Down

0 comments on commit 925a214

Please sign in to comment.