"use client"; import { useRouter } from "next/navigation"; import { signIn, signUp } from "@opencut/auth/client"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { useState } from "react"; import { Input } from "@/components/ui/input"; import { Separator } from "@/components/ui/separator"; import Link from "next/link"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { ArrowLeft, Loader2 } from "lucide-react"; import { GoogleIcon } from "@/components/icons"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; // Zod schemas const loginSchema = z.object({ email: z.string().email("Please enter a valid email address"), password: z.string().min(1, "Password is required"), }); const signupSchema = z.object({ name: z.string().min(2, "Name must be at least 2 characters"), email: z.string().email("Please enter a valid email address"), password: z.string().min(8, "Password must be at least 8 characters"), }); type LoginFormData = z.infer; type SignupFormData = z.infer; interface AuthFormProps { mode: "login" | "signup"; } const authConfig = { login: { title: "Welcome back", description: "Sign in to your account to continue", buttonText: "Sign in", linkText: "Don't have an account?", linkHref: "/signup", linkLabel: "Sign up", successRedirect: "/editor", }, signup: { title: "Create your account", description: "Get started with your free account today", buttonText: "Create account", linkText: "Already have an account?", linkHref: "/login", linkLabel: "Sign in", successRedirect: "/login", }, } as const; interface AuthFormContentProps { error: string | null; setError: (error: string | null) => void; isGoogleLoading: boolean; config: typeof authConfig.login | typeof authConfig.signup; router: ReturnType; } function LoginFormContent({ error, setError, isGoogleLoading, config, router, }: AuthFormContentProps) { const form = useForm({ resolver: zodResolver(loginSchema), defaultValues: { email: "", password: "" }, }); const { isSubmitting } = form.formState; const isAnyLoading = isSubmitting || isGoogleLoading; const onSubmit = async (data: LoginFormData) => { setError(null); try { const { error } = await signIn.email({ email: data.email, password: data.password, }); if (error) { setError(error.message || "An unexpected error occurred."); return; } router.push(config.successRedirect); } catch (error) { setError("An unexpected error occurred. Please try again."); } }; return (
( Email )} /> ( Password )} /> ); } function SignupFormContent({ error, setError, isGoogleLoading, config, router, }: AuthFormContentProps) { const form = useForm({ resolver: zodResolver(signupSchema), defaultValues: { email: "", password: "", name: "" }, }); const { isSubmitting } = form.formState; const isAnyLoading = isSubmitting || isGoogleLoading; const onSubmit = async (data: SignupFormData) => { setError(null); try { const { error } = await signUp.email({ name: data.name, email: data.email, password: data.password, }); if (error) { setError(error.message || "An unexpected error occurred."); return; } router.push(config.successRedirect); } catch (error) { setError("An unexpected error occurred. Please try again."); } }; return (
( Full Name )} /> ( Email )} /> ( Password )} /> ); } export function AuthForm({ mode }: AuthFormProps) { const router = useRouter(); const [error, setError] = useState(null); const [isGoogleLoading, setIsGoogleLoading] = useState(false); const config = authConfig[mode]; const handleGoogleAuth = async () => { setError(null); setIsGoogleLoading(true); try { await signIn.social({ provider: "google", }); router.push(config.successRedirect); } catch (error) { setError( `Failed to ${mode === "login" ? "sign in" : "sign up"} with Google. Please try again.` ); setIsGoogleLoading(false); } }; return (
{config.title} {config.description}
{error && ( Error {error} )}
Or continue with
{mode === "login" ? ( ) : ( )}
{config.linkText}{" "} {config.linkLabel}
); }