From 211117e61afa8ef642c9394a371329733fbcc85b Mon Sep 17 00:00:00 2001 From: weeihan Date: Tue, 21 Jul 2026 22:29:39 +0800 Subject: [PATCH] feat(auth): add forgot-password page --- app/(auth)/forgot-password/page.tsx | 96 +++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 app/(auth)/forgot-password/page.tsx diff --git a/app/(auth)/forgot-password/page.tsx b/app/(auth)/forgot-password/page.tsx new file mode 100644 index 0000000..34f9ac2 --- /dev/null +++ b/app/(auth)/forgot-password/page.tsx @@ -0,0 +1,96 @@ +'use client' + +import { useState } from 'react' +import Link from 'next/link' +import { createClient } from '@/lib/supabase/client' + +export default function ForgotPasswordPage() { + const [email, setEmail] = useState('') + const [loading, setLoading] = useState(false) + const [submitted, setSubmitted] = useState(false) + const [error, setError] = useState(null) + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault() + if (!email) return + setLoading(true) + setError(null) + + const supabase = createClient() + const appUrl = process.env.NEXT_PUBLIC_APP_URL ?? '' + const redirectTo = `${appUrl}/api/auth/callback?next=/reset-password` + + const { error: resetError } = await supabase.auth.resetPasswordForEmail(email, { + redirectTo, + }) + + setLoading(false) + + if (resetError) { + setError('Something went wrong. Please try again.') + return + } + + // Always show success — never reveal whether email exists + setSubmitted(true) + } + + if (submitted) { + return ( +
+
+

Check your email

+

+ If an account exists for {email}, a password reset link has been sent. +

+ + Back to sign in + +
+
+ ) + } + + return ( +
+
+
+

Reset password

+

+ Enter your email and we'll send a reset link. +

+
+ + {error && ( +

+ {error} +

+ )} + + setEmail(e.target.value)} + required + autoComplete="email" + className="border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + + + +

+ + Back to sign in + +

+
+
+ ) +}