'use client' import { useState } from 'react' import Link from 'next/link' import { useRouter } from 'next/navigation' import { signIn, signInWithGoogle, signInWithOidc } from '@/lib/actions/auth' import { safeRedirectPath } from '@/lib/auth/redirect-target' import { useAuthCapabilities } from '@/lib/contexts/app-user-context' import { cn } from '@/lib/utils/index' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { IconLogo } from '@/components/ui/icons' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { PasswordInput } from './ui/password-input' export function LoginForm({ className, next, confirmed = false, ...props }: React.ComponentPropsWithoutRef<'div'> & { next?: string confirmed?: boolean }) { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [error, setError] = useState(null) const [isLoading, setIsLoading] = useState(false) const router = useRouter() const capabilities = useAuthCapabilities() const handleLogin = async (e: React.FormEvent) => { e.preventDefault() setIsLoading(true) setError(null) try { const result = await signIn({ email, password }) if (!result.success) throw new Error(result.error ?? 'An error occurred') // Redirect to the page that required sign-in (when it is a safe // relative path) and refresh to ensure server components get // updated session router.push(safeRedirectPath(next)) router.refresh() } catch (error: unknown) { setError(error instanceof Error ? error.message : 'An error occurred') } finally { setIsLoading(false) } } const handleSocialLogin = async () => { setIsLoading(true) setError(null) try { // Supabase's redirect allowlist matches the callback URL exactly, so // the destination rides in a short-lived cookie, not the redirectTo. // Always write it: a login without a destination must clear a stale // cookie left by an abandoned attempt, or that old destination would // hijack the later sign-in. document.cookie = next ? `auth_next=${encodeURIComponent( safeRedirectPath(next) )}; path=/; max-age=300; SameSite=Lax` : 'auth_next=; path=/; max-age=0; SameSite=Lax' const result = await signInWithGoogle() if (!result.success) throw new Error(result.error ?? 'An OAuth error occurred') if (result.redirectTo) { window.location.href = result.redirectTo } } catch (error: unknown) { setError( error instanceof Error ? error.message : 'An OAuth error occurred' ) } finally { setIsLoading(false) } } const handleOidcLogin = async () => { setIsLoading(true) setError(null) try { document.cookie = next ? `auth_next=${encodeURIComponent( safeRedirectPath(next) )}; path=/; max-age=300; SameSite=Lax` : 'auth_next=; path=/; max-age=0; SameSite=Lax' const result = await signInWithOidc() if (!result.success) throw new Error(result.error ?? 'An OAuth error occurred') if (result.redirectTo) { window.location.href = result.redirectTo } } catch (error: unknown) { setError( error instanceof Error ? error.message : 'An OAuth error occurred' ) } finally { setIsLoading(false) } } return (
Welcome back {confirmed ? 'If you just confirmed your email, sign in to continue.' : 'Sign in to your account'}
{capabilities.oauth && ( <>
Or
)}
setEmail(e.target.value)} />
{capabilities.passwordReset && ( Forgot password? )}
setPassword(e.target.value)} />
{error &&

{error}

}
{capabilities.signUp && (
Don't have an account?{' '} Sign Up
)}
← Back to Home
) }