feat: add authentication

This commit is contained in:
2025-03-01 23:22:18 +07:00
parent b53859ae23
commit f8e65ccc0e
21 changed files with 375 additions and 27 deletions
+21
View File
@@ -0,0 +1,21 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { z } from "zod";
import { loginSchema } from "./schema";
import api from "@/lib/api";
import { toast } from "sonner";
export const useLogin = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (body: z.infer<typeof loginSchema>) => {
return api.post("/auth/login", { body });
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["auth"] });
},
onError: (err) => {
toast.error(err?.message || "Unknown error");
},
});
};
+54
View File
@@ -0,0 +1,54 @@
import Button from "@/components/ui/button";
import { zodResolver } from "@hookform/resolvers/zod";
import { Card } from "react-daisyui";
import { useForm } from "react-hook-form";
import { loginSchema } from "./schema";
import { InputField } from "@/components/ui/input";
import { useLogin } from "./hooks";
export default function LoginPage() {
const form = useForm({
resolver: zodResolver(loginSchema),
defaultValues: { username: "", password: "" },
});
const login = useLogin();
return (
<form onSubmit={form.handleSubmit((v) => login.mutate(v))}>
<Card className="w-full max-w-md" bordered>
<Card.Body>
<Card.Title tag="h2">Login</Card.Title>
<p className="text-base-content/60">
Enter username and password below to log in to your account
</p>
<InputField
form={form}
name="username"
title="Username"
placeholder="Enter your username"
/>
<InputField
form={form}
name="password"
title="Password"
type="password"
placeholder="Enter your password"
/>
<Card.Actions className="mt-4">
<Button
type="submit"
color="primary"
className="w-full md:w-auto min-w-[100px]"
loading={login.isPending}
>
Login
</Button>
</Card.Actions>
</Card.Body>
</Card>
</form>
);
}
+6
View File
@@ -0,0 +1,6 @@
import { z } from "zod";
export const loginSchema = z.object({
username: z.string().min(1, "Username is required"),
password: z.string().min(1, "Password is required"),
});