diff --git a/src/app/components/AuthForm.js b/src/app/components/AuthForm.js index 9736603..5b4fe44 100644 --- a/src/app/components/AuthForm.js +++ b/src/app/components/AuthForm.js @@ -7,12 +7,14 @@ import Link from "next/link"; export default function AuthPage() { const router = useRouter(); - const { user, loading: authLoading, isAuthenticated, login, register } = useAuth(); +const { user, loading: authLoading, isAuthenticated, login, register,sendPasswordResetEmail, resetPassword } = useAuth(); const [isLoginForm, setIsLoginForm] = useState(true); const [darkMode, setDarkMode] = useState(false); const [loading, setLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); - +const [showResetForm, setShowResetForm] = useState(false); +const [resetEmail, setResetEmail] = useState(""); +const [resetSent, setResetSent] = useState(false); // Form states const [loginData, setLoginData] = useState({ email: "", @@ -33,6 +35,26 @@ export default function AuthPage() { general: "", }); + // -----------reset password------------------------ + const handleForgotPassword = async (e) => { + e.preventDefault(); + setLoading(true); + setErrors({ ...errors, general: "" }); + + try { + await sendPasswordResetEmail(resetEmail); + setResetSent(true); + } catch (error) { + console.error("Reset error:", error); + setErrors({ + ...errors, + general: "Failed to send reset email. Please try again." + }); + } finally { + setLoading(false); + } +}; +// ------------------------------------------ // Redirect if already authenticated useEffect(() => { if (!authLoading && isAuthenticated) { @@ -153,27 +175,74 @@ export default function AuthPage() { } return ( -
-
-
-
-

- {isLoginForm ? "Sign In" : "Sign Up"} -

-

- {isLoginForm +

+
+
+
+

+ {showResetForm ? "Reset Password" : isLoginForm ? "Sign In" : "Sign Up"} +

+

+ {showResetForm + ? resetSent + ? "Check your email for reset instructions" + : "Enter your email to receive a reset link" + : isLoginForm ? "Enter your email and password to sign in" : "Create your account to get started"} -

+

+
+ + {errors.general && ( +
+ {errors.general}
+ )} - {errors.general && ( -
- {errors.general} -
- )} - - {isLoginForm ? ( + {showResetForm ? ( + // Password Reset Form +
+ {resetSent ? ( +
+ We've sent a password reset link to your email. Please check your inbox. +
+ ) : ( +
+
+ + setResetEmail(e.target.value)} + className="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:text-white" + placeholder="your@email.com" + required + /> +
+ +
+ )} + +
+ ) :isLoginForm ? ( // Login Form
@@ -354,6 +423,7 @@ export default function AuthPage() { )} + {!showResetForm && (

{isLoginForm ? "Don't have an account?" : "Already have an account?"} @@ -367,26 +437,39 @@ export default function AuthPage() { {isLoginForm ? "Sign up" : "Sign in"}

+ {/* {isLoginForm && ( + + )} */}
-
-
- - {/* Dark mode toggle */} - +
- ); + + {/* Dark mode toggle */} + +
+); } \ No newline at end of file diff --git a/src/app/context/AuthContext.js b/src/app/context/AuthContext.js index 2a87aea..d5424f9 100644 --- a/src/app/context/AuthContext.js +++ b/src/app/context/AuthContext.js @@ -55,7 +55,40 @@ export const AuthProvider = ({ children }) => { throw error; } }; +// --------password reset------------------------ +const sendPasswordResetEmail = async (email) => { + try { + await account.createRecovery( + email, + `${window.location.origin}/reset-password` // Your reset password URL + ); + return true; + } catch (error) { + console.error("Password reset error:", error); + throw error; + } +}; +const resetPassword = async (userId, secret, newPassword, confirmPassword) => { + if (newPassword !== confirmPassword) { + throw new Error("Passwords don't match"); + } + + try { + await account.updateRecovery( + userId, + secret, + newPassword, + confirmPassword + ); + return true; + } catch (error) { + console.error("Password update error:", error); + throw error; + } +}; + +// ----------------------------------------------- return ( { login, register, logout, + sendPasswordResetEmail, + resetPassword, }} > {children} diff --git a/src/app/pages/reset-password/page.js b/src/app/pages/reset-password/page.js new file mode 100644 index 0000000..678bcb4 --- /dev/null +++ b/src/app/pages/reset-password/page.js @@ -0,0 +1,116 @@ +'use client'; +import { useState } from 'react'; +import { useRouter, useSearchParams } from 'next/navigation'; +import { useAuth } from '../../context/AuthContext'; + +export default function ResetPassword() { + const router = useRouter(); + const searchParams = useSearchParams(); + const { resetPassword } = useAuth(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + const [success, setSuccess] = useState(false); + + // Get userId and secret from URL + const userId = searchParams.get('userId'); + const secret = searchParams.get('secret'); + + const [formData, setFormData] = useState({ + password: '', + confirmPassword: '' + }); + + const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + setError(''); + + try { + await resetPassword( + userId, + secret, + formData.password, + formData.confirmPassword + ); + setSuccess(true); + setTimeout(() => router.push('/'), 3000); + } catch (err) { + setError(err.message || 'Password reset failed'); + } finally { + setLoading(false); + } + }; + + const handleChange = (e) => { + setFormData({ + ...formData, + [e.target.name]: e.target.value + }); + }; + + if (!userId || !secret) { + return ( +
+

Invalid reset link

+

The password reset link is invalid or has expired.

+
+ ); + } + + if (success) { + return ( +
+

Password reset successful!

+

You will be redirected to the login page shortly.

+
+ ); + } + + return ( +
+

Reset Password

+ + {error && ( +
+ {error} +
+ )} + +
+
+ + +
+ +
+ + +
+ + +
+
+ ); +} \ No newline at end of file