'use client'; import { useState } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { Loader2 } from 'lucide-react'; import { authClient } from '@/lib/auth-client'; type Step = 'phone' | 'code'; export function SignInForm() { const router = useRouter(); const searchParams = useSearchParams(); const next = searchParams.get('next') ?? '/jobs'; const [step, setStep] = useState('phone'); const [phone, setPhone] = useState(''); const [code, setCode] = useState(''); const [error, setError] = useState(null); const [busy, setBusy] = useState(false); async function sendCode(event: React.FormEvent) { event.preventDefault(); setError(null); setBusy(true); const { error: sendError } = await authClient.phoneNumber.sendOtp({ phoneNumber: phone }); setBusy(false); if (sendError) { setError(sendError.message ?? 'We could not send that code. Check the number and try again.'); return; } setStep('code'); } async function verifyCode(event: React.FormEvent) { event.preventDefault(); setError(null); setBusy(true); const { error: verifyError } = await authClient.phoneNumber.verify({ phoneNumber: phone, code, }); setBusy(false); if (verifyError) { // better-auth returns TOO_MANY_ATTEMPTS after 3 wrong codes; say so plainly // rather than letting someone keep guessing at a dead code. setError( verifyError.status === 403 ? 'Too many incorrect attempts. Request a new code.' : (verifyError.message ?? 'That code is not right.'), ); return; } router.push(next); router.refresh(); } return (
{step === 'phone' ? (
setPhone(e.target.value.replace(/\s/g, ''))} className="rounded-xl border border-[var(--border)] bg-[var(--card)] px-4 py-3 text-base outline-none focus:border-[var(--color-brand-500)]" /> Send code
) : (
setCode(e.target.value.replace(/\D/g, ''))} className="rounded-xl border border-[var(--border)] bg-[var(--card)] px-4 py-3 text-center text-2xl tracking-[0.4em] outline-none focus:border-[var(--color-brand-500)]" /> Sign in
)} {error && (

{error}

)}
or

Signing in with Google creates a separate account from a phone sign-in. If you have used both, contact us and we will link them.

); } function SubmitButton({ busy, children }: { busy: boolean; children: React.ReactNode }) { return ( ); }