'use client'; import { useEffect, useState } from 'react'; import Link from 'next/link'; import { useRouter, useSearchParams } from 'next/navigation'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { BrandedAuthShell } from '@/components/shared/branded-auth-shell'; import { FormErrorSummary } from '@/components/forms/form-error-summary'; import { useFormScrollToError } from '@/hooks/use-form-scroll-to-error'; import { cn } from '@/lib/utils'; const resetSchema = z.object({ email: z.string().email('Please enter a valid email address'), }); type ResetFormData = z.infer; export default function ResetPasswordPage() { const router = useRouter(); const searchParams = useSearchParams(); const [submitted, setSubmitted] = useState(false); const [isLoading, setIsLoading] = useState(false); const { register, handleSubmit, formState: { errors }, } = useForm({ resolver: zodResolver(resetSchema), }); const submitWithScroll = useFormScrollToError(handleSubmit, errors); // If the user landed here from a stale email link that points to // `/reset-password?token=…` instead of `/set-password?token=…`, hand // them off to the set-password form (the one that actually knows how // to consume the token). New emails should point straight at // `/set-password`, but old links live in inboxes for a long time. useEffect(() => { const token = searchParams.get('token'); if (token) { router.replace(`/set-password?token=${encodeURIComponent(token)}`); } }, [router, searchParams]); async function onSubmit(data: ResetFormData) { setIsLoading(true); try { // Better-auth's request-link endpoint is `/api/auth/request-password-reset`. // `/api/auth/reset-password` is the *consume-token* endpoint and silently // rejects an email-only payload, which is why the old code appeared to // "succeed" without ever sending mail. const response = await fetch('/api/auth/request-password-reset', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: data.email, redirectTo: '/set-password' }), }); // Treat 400 "user not found" as success so we don't leak whether the // account exists - the success copy says "if an account exists…". // Anything else (5xx, network) surfaces as a real error. if (!response.ok && response.status !== 400) { toast.error('Something went wrong. Please try again.'); return; } setSubmitted(true); } catch { toast.error('Something went wrong. Please try again.'); } finally { setIsLoading(false); } } return (

Reset your password

We'll email you a link

{submitted ? (

Check your email

If an account exists for that email address, we have sent a password reset link. Please check your inbox and spam folder.

Back to sign in
) : (
{errors.email &&

{errors.email.message}

}

Remember your password?{' '} Sign in

)}
); }