amati/apps/frontend/src/routes/login/index.lazy.tsx
2024-08-30 08:33:01 +07:00

191 lines
5.3 KiB
TypeScript

import { createLazyFileRoute, useNavigate } from "@tanstack/react-router";
import { useMutation } from "@tanstack/react-query";
import { Input } from '@/shadcn/components/ui/input.tsx';
import { Button } from '@/shadcn/components/ui/button.tsx';
import { Alert } from '@/shadcn/components/ui/alert.tsx';
import { Card } from '@/shadcn/components/ui/card.tsx';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage
} from '@/shadcn/components/ui/form.tsx';
import client from "../../honoClient";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect, useState } from "react";
import useAuth from "@/hooks/useAuth";
import { TbArrowNarrowRight } from "react-icons/tb";
export const Route = createLazyFileRoute("/login/")({
component: LoginPage,
});
type FormSchema = {
username: string;
password: string;
};
const formSchema = z.object({
username: z.string().min(1, "This field is required"),
password: z.string().min(1, "This field is required"),
});
export default function LoginPage() {
const [errorMessage, setErrorMessage] = useState("");
const navigate = useNavigate();
const { isAuthenticated, saveAuthData } = useAuth();
const form = useForm<FormSchema>({
resolver: zodResolver(formSchema),
defaultValues: {
username: "",
password: "",
},
});
useEffect(() => {
if (isAuthenticated) {
navigate({
to: "/dashboard",
replace: true,
});
}
}, [navigate, isAuthenticated]);
const loginMutation = useMutation({
mutationFn: async (values: FormSchema) => {
const res = await client.auth.login.$post({
form: values,
});
if (res.ok) {
return await res.json();
}
throw res;
},
onSuccess: (data) => {
saveAuthData(
{
id: data.user.id,
name: data.user.name,
permissions: data.user.permissions,
},
data.accessToken
);
},
onError: async (error) => {
console.log("error!");
if (error instanceof Response) {
const body = await error.json();
setErrorMessage(body.message as string);
return;
}
console.log("bukan error");
},
});
const handleSubmit = (values: FormSchema) => {
loginMutation.mutate(values);
};
return (
<div
className="flex items-center justify-center bg-contain bg-top lg:bg-right
bg-no-repeat bg-[url('../src/assets/backgrounds/backgroundLoginMobile.png')]
lg:bg-[url('../src/assets/backgrounds/backgroundLogin.png')]"
>
<div className="absolute top-[1.688rem] left-[1.875rem] text-base font-bold leading-[1.21rem]">
Amati
</div>
<div className="w-screen h-screen flex ml-0 lg:ml-[7.063rem] justify-center lg:justify-start items-center">
<Card className="w-[19.125rem] sm:w-[26.063rem] lg:w-[29.5rem] h-auto bg-transparent border-none">
<h1 className="mb-2 text-[2.625rem] font-bold leading-[3.177rem] tracking-tightest">Sign In</h1>
<p className="text-sm mb-10 leading-[1.059rem]">
New to this app?{' '}
<a
href="/register"
className="text-blue-500 font-bold hover:text-blue-800"
>
Register now
</a>
</p>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)}>
<div className="space-y-5">
{errorMessage && (
<Alert variant="destructive">
<p>{errorMessage}</p>
</Alert>
)}
<FormField
name="username"
render={({ field }) => (
<FormItem className="text-sm">
<FormLabel className="font-semibold leading-[1.059rem]">Email/Username</FormLabel>
<FormControl>
<Input
placeholder="eg; user@mail.com"
disabled={loginMutation.isPending}
className={form.formState.errors.username ? "border-red-500" : ""}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
name="password"
render={({ field }) => (
<FormItem className="text-sm">
<FormLabel className="font-semibold leading-[1.059rem]">Password</FormLabel>
<FormControl>
<Input
type="password"
placeholder="*****"
disabled={loginMutation.isPending}
className={form.formState.errors.password ? "border-red-500" : ""}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<p className="text-sm">
<a
href="/forgot-password"
className="text-blue-500 font-bold hover:text-blue-800 leading-[1.059rem]"
>
Forgot Password?
</a>
</p>
</div>
<div className="flex justify-between mt-10">
<Button
type="submit"
disabled={loginMutation.isPending}
variant="default"
className="w-full flex items-center justify-center space-x-[13.125rem] sm:space-x-[20rem]
lg:space-x-[23.125rem] bg-[#2555FF] text-white hover:bg-[#1e4ae0]"
>
<span className="leading-[1.25rem]">Sign In</span>
<TbArrowNarrowRight className="h-5 w-5" />
</Button>
</div>
</form>
</Form>
</Card>
</div>
</div>
);
}