"use client"; import { RiFingerprintLine, RiLoader4Line } from "@remixicon/react"; import { useRouter } from "next/navigation"; import { type FormEvent, useEffect, useState } from "react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Field, FieldDescription, FieldGroup, FieldLabel, FieldSeparator, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { authClient, googleSignInAvailable } from "@/lib/auth/client"; import { cn } from "@/lib/utils/ui"; import { Logo } from "../logo"; import { AuthErrorAlert } from "./auth-error-alert"; import { AuthHeader } from "./auth-header"; import AuthSidebar from "./auth-sidebar"; import { GoogleAuthButton } from "./google-auth-button"; type DivProps = React.ComponentProps<"div">; export function LoginForm({ className, ...props }: DivProps) { const router = useRouter(); const isGoogleAvailable = googleSignInAvailable; const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(""); const [loadingEmail, setLoadingEmail] = useState(false); const [loadingGoogle, setLoadingGoogle] = useState(false); const [loadingPasskey, setLoadingPasskey] = useState(false); const [passkeySupported, setPasskeySupported] = useState(false); useEffect(() => { if (typeof window === "undefined") return; if (typeof PublicKeyCredential === "undefined") return; setPasskeySupported(true); }, []); async function handleSubmit(e: FormEvent) { e.preventDefault(); await authClient.signIn.email( { email, password, callbackURL: "/dashboard", rememberMe: false, }, { onRequest: () => { setError(""); setLoadingEmail(true); }, onSuccess: () => { setLoadingEmail(false); toast.success("Login realizado com sucesso!"); router.replace("/dashboard"); }, onError: (ctx) => { if ( ctx.error.status === 500 && ctx.error.statusText === "Internal Server Error" ) { toast.error( "Ocorreu uma falha na requisição. Tente novamente mais tarde.", ); } setError(ctx.error.message); setLoadingEmail(false); }, }, ); } async function handleGoogle() { if (!isGoogleAvailable) { setError("Login com Google não está disponível no momento."); return; } // Ativa loading antes de iniciar o fluxo OAuth setError(""); setLoadingGoogle(true); // OAuth redirect - o loading permanece até a página ser redirecionada await authClient.signIn.social( { provider: "google", callbackURL: "/dashboard", }, { onError: (ctx) => { // Só desativa loading se houver erro setError(ctx.error.message); setLoadingGoogle(false); }, }, ); } async function handlePasskey() { setError(""); setLoadingPasskey(true); const { error: passkeyError } = await authClient.signIn.passkey({ fetchOptions: { onSuccess: () => { setLoadingPasskey(false); router.replace("/dashboard"); }, onError: (ctx) => { setError(ctx.error.message); setLoadingPasskey(false); }, }, }); if (passkeyError) { setError(passkeyError.message || "Erro ao entrar com passkey."); setLoadingPasskey(false); } } return (
E-mail setEmail(e.target.value)} aria-invalid={!!error} />
Senha
setPassword(e.target.value)} aria-invalid={!!error} />
Ou continue com {passkeySupported && ( )} Não tem uma conta?{" "} Inscreva-se
Voltar para o site
); }