import React, { useState, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { clearError } from '../store/reducers/authSlice'; // Import the Supabase client import { supabase } from '../services/supabaseClient'; const ResetPassword = () => { const dispatch = useDispatch(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const { loading, error } = useSelector(state => state.auth); const [formData, setFormData] = useState({ token: '', // This is likely unused in the v2 flow, but kept for structure password: '', confirmPassword: '' }); const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); const [passwordStrength, setPasswordStrength] = useState(0); const [isFocused, setIsFocused] = useState({ password: false, confirmPassword: false }); const [authState, setAuthState] = useState({ event: null, session: null }); // --- Listen for auth state changes specifically on this page --- // This helps confirm if PASSWORD_RECOVERY was detected useEffect(() => { console.log("ResetPassword component mounted. Setting up auth listener."); const { data: authListener } = supabase.auth.onAuthStateChange((event, session) => { console.log('Auth state changed within ResetPassword component:', event, session ? `User: ${session.user?.id || 'N/A'}` : 'No session'); setAuthState({ event, session }); if (event === 'PASSWORD_RECOVERY') { console.log('*** PASSWORD_RECOVERY event confirmed in ResetPassword component. ***'); // Optional: You could set some state here to indicate the recovery flow is active } }); // Cleanup listener on unmount return () => { console.log("ResetPassword component unmounting. Removing auth listener."); authListener?.subscription.unsubscribe(); }; }, []); // Get token from URL params (old v1 flow, kept for reference but likely not used) useEffect(() => { const token = searchParams.get('token'); if (token) { console.warn("Token found in search params (v1 flow?). This might be unexpected in v2 flow:", token); setFormData(prev => ({ ...prev, token })); } }, [searchParams]); const calculatePasswordStrength = (password) => { let strength = 0; // Length check if (password.length >= 8) strength += 1; if (password.length >= 12) strength += 1; // Character variety checks if (/[a-z]/.test(password)) strength += 1; if (/[A-Z]/.test(password)) strength += 1; if (/[0-9]/.test(password)) strength += 1; if (/[^A-Za-z0-9]/.test(password)) strength += 1; setPasswordStrength(Math.min(strength, 6)); }; const handleChange = (e) => { const { name, value } = e.target; setFormData({ ...formData, [name]: value }); // Calculate password strength if (name === 'password') { calculatePasswordStrength(value); } }; const handleFocus = (field) => { setIsFocused({ ...isFocused, [field]: true }); }; const handleBlur = (field) => { setIsFocused({ ...isFocused, [field]: false }); }; const togglePasswordVisibility = () => { setShowPassword(!showPassword); }; const toggleConfirmPasswordVisibility = () => { setShowConfirmPassword(!showConfirmPassword); }; const handleSubmit = async (e) => { e.preventDefault(); // Basic validation if (formData.password !== formData.confirmPassword) { alert('Passwords do not match'); return; } if (formData.password.length < 8) { alert('Password must be at least 8 characters long'); return; } try { console.log("Attempting to get current session before password update..."); // --- Check for existing session (recovery session) --- // It's crucial to verify the session was established by the Supabase client // when it processed the URL fragments on app load. const { data: { session: currentSession }, error: sessionError } = await supabase.auth.getSession(); console.log("Current session check result:", currentSession ? `Session for user: ${currentSession.user?.id || 'N/A'}` : 'No session', sessionError); if (sessionError) { console.error('Error getting current session:', sessionError); alert('Failed to get session. Please try resetting your password again.'); return; } if (!currentSession || !currentSession.user) { // This is the likely cause of AuthSessionMissingError console.warn('No active session found in handleSubmit. The URL might not have been processed correctly or the session expired.'); console.log("Auth state at time of submission:", authState); alert('Password reset link may be invalid or expired. Please request a new one.'); // Optionally, redirect to /forgot-password // navigate('/forgot-password'); return; } console.log('Resetting password with Supabase client for user:', currentSession.user?.email); const { data, error } = await supabase.auth.updateUser({ password: formData.password }); console.log("supabase.auth.updateUser result:", data, error); if (error) { console.error('Supabase password reset error:', error); let message = 'Failed to reset password.'; if (error.message.toLowerCase().includes('password')) { message = 'Password does not meet requirements. Please use at least 8 characters.'; } else if (error.message.toLowerCase().includes('session') || error.message.includes("Auth session missing")) { message = 'Password reset session expired. Please request a new reset link.'; } else { message = error.message; } alert(message); return; } console.log('Password updated successfully:', data); alert('Password reset successfully! You can now log in with your new password.'); // After successful reset, sign the user out of the temporary recovery session. await supabase.auth.signOut(); navigate('/login'); } catch (err) { console.error('Unexpected error during password reset:', err); alert('An unexpected error occurred. Please try again.'); } }; const handleBackToLogin = () => { dispatch(clearError()); navigate('/login'); }; return (
Enter your new password below
Auth Event: {authState.event || 'None'}
Auth Session User ID: {authState.session?.user?.id || 'None'}
© 2024 Lin. All rights reserved.