From 116519a70b73d4a96fc1194272cdfafd4d9d0722 Mon Sep 17 00:00:00 2001 From: cfngc4594 Date: Fri, 14 Mar 2025 17:08:11 +0800 Subject: [PATCH] feat(auth): refactor sign up and sign in forms with react-hook-form and zod validation --- src/components/credentials-sign-in.tsx | 113 +++++++++++++++++----- src/components/credentials-sign-up.tsx | 124 ++++++++++++++++++------- 2 files changed, 181 insertions(+), 56 deletions(-) diff --git a/src/components/credentials-sign-in.tsx b/src/components/credentials-sign-in.tsx index 12ed60e..4213154 100644 --- a/src/components/credentials-sign-in.tsx +++ b/src/components/credentials-sign-in.tsx @@ -1,28 +1,99 @@ -import { signIn } from "@/lib/auth"; +"use client"; + +import { z } from "zod"; +import { + Form, + FormField, + FormItem, + FormControl, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { useState } from "react"; +import { authSchema } from "@/lib/zod"; +import { useForm } from "react-hook-form"; import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { signInWithCredentials } from "@/app/actions/auth"; +import { EyeIcon, EyeOffIcon, MailIcon } from "lucide-react"; export function CredentialsSignIn() { + const form = useForm>({ + resolver: zodResolver(authSchema), + defaultValues: { + email: "", + password: "", + }, + }); + + const [isVisible, setIsVisible] = useState(false); + + const toggleVisibility = () => setIsVisible((prevState) => !prevState); + return ( -
{ - "use server"; - await signIn("credentials", formData); - }} - > -
- - -
-
- - -
- -
+
+ signInWithCredentials(data))} + className="grid gap-6" + > + ( + + Email + +
+ +
+
+
+
+ +
+ )} + /> + + ( + + Password + +
+ + +
+
+ +
+ )} + /> + + + + ); } diff --git a/src/components/credentials-sign-up.tsx b/src/components/credentials-sign-up.tsx index 40c02cb..d939290 100644 --- a/src/components/credentials-sign-up.tsx +++ b/src/components/credentials-sign-up.tsx @@ -1,45 +1,99 @@ -import bcrypt from "bcrypt"; -import prisma from "@/lib/prisma"; +"use client"; + +import { z } from "zod"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { useState } from "react"; import { authSchema } from "@/lib/zod"; -import { redirect } from "next/navigation"; +import { useForm } from "react-hook-form"; import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { signUpWithCredentials } from "@/app/actions/auth"; +import { EyeIcon, EyeOffIcon, MailIcon } from "lucide-react"; export function CredentialsSignUp() { + const form = useForm>({ + resolver: zodResolver(authSchema), + defaultValues: { + email: "", + password: "", + }, + }); + + const [isVisible, setIsVisible] = useState(false); + + const toggleVisibility = () => setIsVisible((prevState) => !prevState); + return ( -
{ - "use server"; - const email = formData.get("email"); - const password = formData.get("password"); + + signUpWithCredentials(data))} + className="grid gap-6" + > + ( + + Email + +
+ +
+
+
+
+ +
+ )} + /> - const validatedData = await authSchema.parseAsync({ email, password }); - const saltRounds = 10; - const pwHash = await bcrypt.hash(validatedData.password, saltRounds); + ( + + Password + +
+ + +
+
+ +
+ )} + /> - await prisma.user.create({ - data: { - email: validatedData.email, - password: pwHash, - }, - }); - - redirect("/sign-in"); - }} - > -
- - -
-
- - -
- - + + + ); }