'use client'; import Link from 'next/link'; import { SubmitButton } from '@/components/ui/submit-button'; import { Input } from '@/components/ui/input'; import GoogleSignIn from '@/components/GoogleSignIn'; import { FlickeringGrid } from '@/components/home/ui/flickering-grid'; import { useMediaQuery } from '@/hooks/use-media-query'; import { useState, useEffect, useRef, Suspense } from 'react'; import { useScroll } from 'motion/react'; import { signIn, signUp, forgotPassword } from './actions'; import { useSearchParams, useRouter } from 'next/navigation'; import { ArrowLeft, X, CheckCircle, AlertCircle, MailCheck, Loader2, } from 'lucide-react'; import { useAuth } from '@/components/AuthProvider'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '@/components/ui/dialog'; function LoginContent() { const router = useRouter(); const searchParams = useSearchParams(); const { user, isLoading } = useAuth(); const mode = searchParams.get('mode'); const returnUrl = searchParams.get('returnUrl'); const message = searchParams.get('message'); const isSignUp = mode === 'signup'; const tablet = useMediaQuery('(max-width: 1024px)'); const [mounted, setMounted] = useState(false); const [isScrolling, setIsScrolling] = useState(false); const scrollTimeout = useRef(null); const { scrollY } = useScroll(); // Redirect if user is already logged in, checking isLoading state useEffect(() => { if (!isLoading && user) { router.push(returnUrl || '/dashboard'); } }, [user, isLoading, router, returnUrl]); // Determine if message is a success message const isSuccessMessage = message && (message.includes('Check your email') || message.includes('Account created') || message.includes('success')); // Registration success state const [registrationSuccess, setRegistrationSuccess] = useState(!!isSuccessMessage); const [registrationEmail, setRegistrationEmail] = useState(''); // Forgot password state const [forgotPasswordOpen, setForgotPasswordOpen] = useState(false); const [forgotPasswordEmail, setForgotPasswordEmail] = useState(''); const [forgotPasswordStatus, setForgotPasswordStatus] = useState<{ success?: boolean; message?: string; }>({}); useEffect(() => { setMounted(true); }, []); // Set registration success state from URL params useEffect(() => { if (isSuccessMessage) { setRegistrationSuccess(true); } }, [isSuccessMessage]); // Detect when scrolling is active to reduce animation complexity useEffect(() => { const unsubscribe = scrollY.on('change', () => { setIsScrolling(true); // Clear any existing timeout if (scrollTimeout.current) { clearTimeout(scrollTimeout.current); } // Set a new timeout scrollTimeout.current = setTimeout(() => { setIsScrolling(false); }, 300); // Wait 300ms after scroll stops }); return () => { unsubscribe(); if (scrollTimeout.current) { clearTimeout(scrollTimeout.current); } }; }, [scrollY]); const handleSignIn = async (prevState: any, formData: FormData) => { if (returnUrl) { formData.append('returnUrl', returnUrl); } else { formData.append('returnUrl', '/dashboard'); } const result = await signIn(prevState, formData); // Check for success and redirectTo properties if ( result && typeof result === 'object' && 'success' in result && result.success && 'redirectTo' in result ) { // Use window.location for hard navigation to avoid stale state window.location.href = result.redirectTo as string; return null; // Return null to prevent normal form action completion } return result; }; const handleSignUp = async (prevState: any, formData: FormData) => { // Store email for success state const email = formData.get('email') as string; setRegistrationEmail(email); if (returnUrl) { formData.append('returnUrl', returnUrl); } // Add origin for email redirects formData.append('origin', window.location.origin); const result = await signUp(prevState, formData); // Check for success and redirectTo properties (direct login case) if ( result && typeof result === 'object' && 'success' in result && result.success && 'redirectTo' in result ) { // Use window.location for hard navigation to avoid stale state window.location.href = result.redirectTo as string; return null; // Return null to prevent normal form action completion } // Check if registration was successful but needs email verification if (result && typeof result === 'object' && 'message' in result) { const resultMessage = result.message as string; if (resultMessage.includes('Check your email')) { setRegistrationSuccess(true); // Update URL without causing a refresh const params = new URLSearchParams(window.location.search); params.set('message', resultMessage); const newUrl = window.location.pathname + (params.toString() ? '?' + params.toString() : ''); window.history.pushState({ path: newUrl }, '', newUrl); return result; } } return result; }; const handleForgotPassword = async (e: React.FormEvent) => { e.preventDefault(); setForgotPasswordStatus({}); if (!forgotPasswordEmail || !forgotPasswordEmail.includes('@')) { setForgotPasswordStatus({ success: false, message: 'Please enter a valid email address', }); return; } const formData = new FormData(); formData.append('email', forgotPasswordEmail); formData.append('origin', window.location.origin); const result = await forgotPassword(null, formData); setForgotPasswordStatus(result); }; const resetRegistrationSuccess = () => { setRegistrationSuccess(false); // Remove message from URL and set mode to signin const params = new URLSearchParams(window.location.search); params.delete('message'); params.set('mode', 'signin'); const newUrl = window.location.pathname + (params.toString() ? '?' + params.toString() : ''); window.history.pushState({ path: newUrl }, '', newUrl); router.refresh(); }; // Show loading spinner while checking auth state if (isLoading) { return (
); } // Registration success view if (registrationSuccess) { return (
{/* Background elements from the original view */}
{/* Success content */}

Check your email

We've sent a confirmation link to:

{registrationEmail || 'your email address'}

Click the link in the email to activate your account. If you don't see the email, check your spam folder.

Return to home
); } return (
{/* Hero-like header with flickering grid */}
{/* Left side flickering grid with gradient fades */}
{/* Horizontal fade from left to right */}
{/* Vertical fade from top */}
{/* Vertical fade to bottom */}
{/* Right side flickering grid with gradient fades */}
{/* Horizontal fade from right to left */}
{/* Vertical fade from top */}
{/* Vertical fade to bottom */}
{/* Center content background with rounded bottom */}
{/* Header content */}
Back to home

{isSignUp ? 'Join Suna' : 'Welcome back'}

{isSignUp ? 'Create your account and start building with AI' : 'Sign in to your account to continue'}

{/* Auth form card */}
{/* Non-registration related messages */} {message && !isSuccessMessage && (
{message}
)} {/* Google Sign In */}
{/* Divider */}
or continue with email
{/* Form */}
{isSignUp && (
)}
{!isSignUp ? ( <> Sign in Create new account ) : ( <> Sign up Back to sign in )}
{!isSignUp && (
)}
By continuing, you agree to our{' '} Terms of Service {' '} and{' '} Privacy Policy
{/* Forgot Password Dialog */}
Reset Password
Enter your email address and we'll send you a link to reset your password.
setForgotPasswordEmail(e.target.value)} className="h-12 rounded-full bg-background border-border" required /> {forgotPasswordStatus.message && (
{forgotPasswordStatus.success ? ( ) : ( )} {forgotPasswordStatus.message}
)}
); } export default function Login() { return (
} >
); }