From 23e3ce296bb4ae5355dd356f94ef41293f1864ca Mon Sep 17 00:00:00 2001 From: Bereket Engida Date: Tue, 4 Mar 2025 10:06:15 +0300 Subject: [PATCH] demo: use the default BA sign-in/sign-up components --- demo/nextjs/components/sign-in.tsx | 264 ++++++++----------------- demo/nextjs/components/sign-up.tsx | 300 ++++++++--------------------- 2 files changed, 167 insertions(+), 397 deletions(-) diff --git a/demo/nextjs/components/sign-in.tsx b/demo/nextjs/components/sign-in.tsx index abf037abaf..9a336c16ff 100644 --- a/demo/nextjs/components/sign-in.tsx +++ b/demo/nextjs/components/sign-in.tsx @@ -4,54 +4,28 @@ import { Button } from "@/components/ui/button"; import { Card, CardContent, - CardDescription, CardHeader, CardTitle, + CardDescription, + CardFooter, } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { PasswordInput } from "@/components/ui/password-input"; -import { signIn } from "@/lib/auth-client"; -import { DiscordLogoIcon, GitHubLogoIcon } from "@radix-ui/react-icons"; +import { Checkbox } from "@/components/ui/checkbox"; +import { useState } from "react"; import { Loader2 } from "lucide-react"; +import { signIn } from "@/lib/auth-client"; import Link from "next/link"; -import { useRouter } from "next/navigation"; -import { useState, useEffect } from "react"; -import { toast } from "sonner"; -import { z } from "zod"; - -const signInSchema = z.object({ - email: z.string().email("Invalid email address"), - password: z.string().min(8, "Password must be at least 8 characters"), -}); +import { cn } from "@/lib/utils"; export default function SignIn() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); - const [rememberMe, setRememberMe] = useState(false); - const [errors, setErrors] = useState({ email: "", password: "" }); - const [isValid, setIsValid] = useState(false); - const [touched, setTouched] = useState({ email: false, password: false }); - const router = useRouter(); const [loading, setLoading] = useState(false); - - useEffect(() => { - const validationResult = signInSchema.safeParse({ email, password }); - if (!validationResult.success) { - const newErrors: any = {}; - validationResult.error.errors.forEach((err) => { - newErrors[err.path[0]] = err.message; - }); - setErrors(newErrors); - setIsValid(false); - } else { - setErrors({ email: "", password: "" }); - setIsValid(true); - } - }, [email, password]); + const [rememberMe, setRememberMe] = useState(false); return ( - + Sign In @@ -69,90 +43,59 @@ export default function SignIn() { required onChange={(e) => { setEmail(e.target.value); - setTouched((prev) => ({ ...prev, email: true })); }} value={email} /> - {touched.email && errors.email && ( -

{errors.email}

- )} +
- + Forgot your password?
- { - setPassword(e.target.value); - setTouched((prev) => ({ ...prev, password: true })); - }} + type="password" + placeholder="password" autoComplete="password" - placeholder="Password" + value={password} + onChange={(e) => setPassword(e.target.value)} /> - {touched.password && errors.password && ( -

{errors.password}

- )}
+ +
+ { + setRememberMe(!rememberMe); + }} + /> + +
+ -
+
- - - - - - +
+ +
+

+ Powered by{" "} + + better-auth. + +

+
+
); } diff --git a/demo/nextjs/components/sign-up.tsx b/demo/nextjs/components/sign-up.tsx index 6ba5c7b07b..d25227796f 100644 --- a/demo/nextjs/components/sign-up.tsx +++ b/demo/nextjs/components/sign-up.tsx @@ -1,102 +1,46 @@ "use client"; -import Image from "next/image"; + import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, + CardFooter, CardHeader, CardTitle, } from "@/components/ui/card"; -import { toast } from "sonner"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { PasswordInput } from "@/components/ui/password-input"; -import { signUp, signIn } from "@/lib/auth-client"; -import { useRouter } from "next/navigation"; -import { useState, useEffect, ChangeEvent } from "react"; -import { z } from "zod"; -import { DiscordLogoIcon, GitHubLogoIcon } from "@radix-ui/react-icons"; +import { useState } from "react"; +import Image from "next/image"; import { Loader2, X } from "lucide-react"; -const signUpSchema = z - .object({ - firstName: z.string().min(1, "First name is required"), - lastName: z.string().min(1, "Last name is required"), - email: z.string().email("Invalid email address"), - image: z - .instanceof(File) - .optional() - .refine((file) => !file || file.type.startsWith("image/"), { - message: "Invalid file type. Only images are allowed.", - path: ["image"], - }), - password: z.string().min(6, "Password must be at least 6 characters"), - passwordConfirmation: z - .string() - .min(6, "Password must be at least 6 characters"), - }) - - .refine((data) => data.password === data.passwordConfirmation, { - message: "Passwords do not match", - path: ["passwordConfirmation"], - }); - -type FormDataType = z.infer; - -type ErrorsType = Partial>; - -type TouchedType = Partial>; +import { signUp } from "@/lib/auth-client"; +import { toast } from "sonner"; +import { useRouter } from "next/navigation"; export function SignUp() { - const [formData, setFormData] = useState({ - firstName: "", - lastName: "", - email: "", - password: "", - image: undefined, - passwordConfirmation: "", - }); - const [errors, setErrors] = useState({}); - const [isValid, setIsValid] = useState(false); - const [touched, setTouched] = useState({}); - const [loading, setLoading] = useState(false); + const [firstName, setFirstName] = useState(""); + const [lastName, setLastName] = useState(""); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [passwordConfirmation, setPasswordConfirmation] = useState(""); const [image, setImage] = useState(null); const [imagePreview, setImagePreview] = useState(null); const router = useRouter(); + const [loading, setLoading] = useState(false); - useEffect(() => { - const validationResult = signUpSchema.safeParse(formData); - if (!validationResult.success) { - const newErrors: ErrorsType = {}; - validationResult.error.errors.forEach((err) => { - if (err.path[0]) - newErrors[err.path[0] as keyof FormDataType] = err.message; - }); - setErrors(newErrors); - setIsValid(false); - } else { - setErrors({}); - setIsValid(true); - } - }, [formData]); - - const handleChange = (e: ChangeEvent) => { - const { id, value } = e.target; - setFormData((prev) => ({ ...prev, [id]: value })); - setTouched((prev) => ({ ...prev, [id]: true })); - }; - const handleImageChange = (e: ChangeEvent) => { - const file = e.target.files?.[0] || null; - setImage(file); - setFormData((prev) => ({ ...prev, image: file || undefined })); + const handleImageChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; if (file) { + setImage(file); const reader = new FileReader(); - reader.onload = () => setImagePreview(reader.result as string); + reader.onloadend = () => { + setImagePreview(reader.result as string); + }; reader.readAsDataURL(file); - } else { - setImagePreview(null); } }; + return ( @@ -109,28 +53,28 @@ export function SignUp() {
- + { + setFirstName(e.target.value); + }} + value={firstName} /> - {touched.firstName && errors.firstName && ( -

{errors.firstName}

- )}
- + { + setLastName(e.target.value); + }} + value={lastName} /> - {touched.lastName && errors.lastName && ( -

{errors.lastName}

- )}
@@ -139,38 +83,34 @@ export function SignUp() { id="email" type="email" placeholder="m@example.com" - value={formData.email} - onChange={handleChange} + required + onChange={(e) => { + setEmail(e.target.value); + }} + value={email} /> - {touched.email && errors.email && ( -

{errors.email}

- )}
- setPassword(e.target.value)} + autoComplete="new-password" placeholder="Password" /> - {touched.password && errors.password && ( -

{errors.password}

- )}
- - Confirm Password + setPasswordConfirmation(e.target.value)} + autoComplete="new-password" placeholder="Confirm Password" /> - {touched.passwordConfirmation && errors.passwordConfirmation && ( -

- {errors.passwordConfirmation} -

- )}
@@ -185,36 +125,36 @@ export function SignUp() { />
)} - - {imagePreview && ( - { - setImage(null); - setImagePreview(null); - }} +
+ - )} + {imagePreview && ( + { + setImage(null); + setImagePreview(null); + }} + /> + )} +
-
- - - - -
+ +
+

+ Secured by better-auth. +

+
+
); } + async function convertImageToBase64(file: File): Promise { return new Promise((resolve, reject) => { const reader = new FileReader();