From 905e1d1d6bf666b4cfbba23922ef717a84d95cf4 Mon Sep 17 00:00:00 2001
From: yashksaini-coder <ys3853428@gmail.com>
Date: Fri, 4 Apr 2025 15:29:40 +0530
Subject: [PATCH 1/2] feat: Add Forgot Password and Reset Password pages with
 functionality

---
 app/auth/forgot-password/page.tsx       | 65 +++++++++++++++++++++++
 app/auth/reset-password/page.tsx        | 68 +++++++++++++++++++++++++
 components/AuthComponent/SigninForm.tsx |  5 ++
 3 files changed, 138 insertions(+)
 create mode 100644 app/auth/forgot-password/page.tsx
 create mode 100644 app/auth/reset-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..0a2c155
--- /dev/null
+++ b/app/auth/forgot-password/page.tsx
@@ -0,0 +1,65 @@
+'use client'
+
+import { useState } from 'react'
+import { Button } from '@/components/ui/button'
+import { Alert, AlertDescription } from '@/components/ui/alert'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+import { supabase } from '@/lib/supabaseClient'
+
+export default function ForgotPasswordPage() {
+  const [email, setEmail] = useState('')
+  const [status, setStatus] = useState<'idle' | 'sending' | 'sent' | 'error'>('idle')
+
+  const handleSubmit = async (e: React.FormEvent) => {
+    e.preventDefault()
+    setStatus('sending')
+
+    const { error } = await supabase.auth.resetPasswordForEmail(email, {
+      redirectTo: `${window.location.origin}/auth/reset-password`
+    })
+
+    if (error) {
+      setStatus('error')
+      console.error('Error sending reset email:', error.message)
+    } else {
+      setStatus('sent')
+    }
+  }
+
+  return (
+    <main className="flex min-h-screen items-center justify-center px-4">
+      <Card className="w-full max-w-md rounded-2xl">
+        <CardHeader>
+          <CardTitle className="text-center text-2xl">Forgot Password</CardTitle>
+        </CardHeader>
+        <CardContent className='space-y-4 align-center'>
+          <form onSubmit={handleSubmit} className="space-y-4">
+            <input
+              type="email"
+              placeholder="you@example.com"
+              value={email}
+              onChange={(e) => setEmail(e.target.value)}
+              required
+              className="w-full p-2 border rounded"
+            />
+            <div className="flex justify-center">
+              <Button type="submit" disabled={status === 'sending'}>
+                {status === 'sending' ? 'Sending...' : 'Send Reset Link'}
+              </Button>
+            </div>
+          </form>
+          {status === 'sent' && (
+            <Alert variant="default" className="mt-4">
+              <AlertDescription>Check your email for the reset link.</AlertDescription>
+            </Alert>
+          )}
+          {status === 'error' && (
+            <Alert variant="destructive" className="mt-4">
+              <AlertDescription>Failed to send reset link. Please try again.</AlertDescription>
+            </Alert>
+          )}
+        </CardContent>
+      </Card>
+    </main>
+  )
+} 
\ No newline at end of file
diff --git a/app/auth/reset-password/page.tsx b/app/auth/reset-password/page.tsx
new file mode 100644
index 0000000..75f5158
--- /dev/null
+++ b/app/auth/reset-password/page.tsx
@@ -0,0 +1,68 @@
+'use client'
+
+import { useState } from 'react'
+import { useRouter } from 'next/navigation'
+import { Button } from '@/components/ui/button'
+import { Alert, AlertDescription } from '@/components/ui/alert'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+import { supabase } from '@/lib/supabaseClient'
+
+export default function ResetPasswordPage() {
+  const router = useRouter()
+  const [newPassword, setNewPassword] = useState('')
+  const [status, setStatus] = useState<'idle' | 'updating' | 'updated' | 'error'>('idle')
+
+  const handleSubmit = async (e: React.FormEvent) => {
+    e.preventDefault()
+    setStatus('updating')
+
+    // Use the access token to update the user's password
+    const { data, error } = await supabase.auth.updateUser({ password: newPassword })
+
+    if (error) {
+      setStatus('error')
+      console.error('Error updating password:', error.message)
+    } else {
+      setStatus('updated')
+      // Redirect to login or another page after successful password update
+      setTimeout(() => {
+        router.push('/auth/signin')
+      }, 2000)
+    }
+  }
+
+  return (
+    <main className="flex min-h-screen items-center justify-center px-4">
+      <Card className="w-full max-w-md rounded-2xl">
+        <CardHeader>
+          <CardTitle className="text-center text-2xl">Set New Password</CardTitle>
+        </CardHeader>
+        <CardContent>
+          <form onSubmit={handleSubmit} className="space-y-4">
+            <input
+              type="password"
+              placeholder="New Password"
+              value={newPassword}
+              onChange={(e) => setNewPassword(e.target.value)}
+              required
+              className="w-full p-2 border rounded"
+            />
+            <Button type="submit" disabled={status === 'updating'}>
+              {status === 'updating' ? 'Updating...' : 'Set New Password'}
+            </Button>
+          </form>
+          {status === 'updated' && (
+            <Alert variant="default" className="mt-4">
+              <AlertDescription>Password updated successfully! Redirecting to sign in...</AlertDescription>
+            </Alert>
+          )}
+          {status === 'error' && (
+            <Alert variant="destructive" className="mt-4">
+              <AlertDescription>Failed to update password. Please try again.</AlertDescription>
+            </Alert>
+          )}
+        </CardContent>
+      </Card>
+    </main>
+  )
+} 
\ No newline at end of file
diff --git a/components/AuthComponent/SigninForm.tsx b/components/AuthComponent/SigninForm.tsx
index 9732907..d3dcce1 100644
--- a/components/AuthComponent/SigninForm.tsx
+++ b/components/AuthComponent/SigninForm.tsx
@@ -128,6 +128,11 @@ export default function SigninForm() {
                   title="Sign in"
                   type="submit"
                 />
+                <div className="flex justify-center mt-4">
+                  <a href="/auth/forgot-password" className="text-blue-600 hover:underline">
+                    Forgot Password?
+                  </a>
+                </div>
               </form>
             </Form>
           </CardContent>

From 937e7d2a218f28a44da7202ac4071b462025180f Mon Sep 17 00:00:00 2001
From: yashksaini-coder <ys3853428@gmail.com>
Date: Fri, 4 Apr 2025 15:31:54 +0530
Subject: [PATCH 2/2] feat: Add password confirmation field and error handling
 to Reset Password page

---
 app/auth/reset-password/page.tsx | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/app/auth/reset-password/page.tsx b/app/auth/reset-password/page.tsx
index 75f5158..19f9067 100644
--- a/app/auth/reset-password/page.tsx
+++ b/app/auth/reset-password/page.tsx
@@ -10,10 +10,19 @@ import { supabase } from '@/lib/supabaseClient'
 export default function ResetPasswordPage() {
   const router = useRouter()
   const [newPassword, setNewPassword] = useState('')
+  const [confirmPassword, setConfirmPassword] = useState('')
   const [status, setStatus] = useState<'idle' | 'updating' | 'updated' | 'error'>('idle')
+  const [errorMessage, setErrorMessage] = useState('')
 
   const handleSubmit = async (e: React.FormEvent) => {
     e.preventDefault()
+    setErrorMessage('')
+
+    if (newPassword !== confirmPassword) {
+      setErrorMessage('Passwords do not match.')
+      return
+    }
+
     setStatus('updating')
 
     // Use the access token to update the user's password
@@ -47,6 +56,19 @@ export default function ResetPasswordPage() {
               required
               className="w-full p-2 border rounded"
             />
+            <input
+              type="password"
+              placeholder="Confirm Password"
+              value={confirmPassword}
+              onChange={(e) => setConfirmPassword(e.target.value)}
+              required
+              className="w-full p-2 border rounded"
+            />
+            {errorMessage && (
+              <Alert variant="destructive" className="mt-2">
+                <AlertDescription>{errorMessage}</AlertDescription>
+              </Alert>
+            )}
             <Button type="submit" disabled={status === 'updating'}>
               {status === 'updating' ? 'Updating...' : 'Set New Password'}
             </Button>
@@ -65,4 +87,4 @@ export default function ResetPasswordPage() {
       </Card>
     </main>
   )
-} 
\ No newline at end of file
+}
\ No newline at end of file