import React, { useEffect, useState } from 'react'; import { IonButton, IonButtons, IonContent, IonHeader, IonIcon, IonInput, IonPage, IonTitle, IonToolbar, } from '@ionic/react'; import { chevronBackOutline, lockClosedOutline } from 'ionicons/icons'; import { useHistory, useLocation } from 'react-router-dom'; import { supabase } from '../supabase'; import { useAuth } from '../contexts/AuthContext'; import OtpInputSlots from '../components/OtpInputSlots'; import '../styles/auth.css'; interface LocationState { email?: string; } const VerifyResetPage: React.FC = () => { const history = useHistory(); const location = useLocation(); const { user, refreshProfile, profileStatus } = useAuth(); const email = location.state?.email; const [code, setCode] = useState(['', '', '', '', '', '']); const [newPassword, setNewPassword] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [status, setStatus] = useState(null); const [cooldown, setCooldown] = useState(0); const [passwordUpdated, setPasswordUpdated] = useState(false); useEffect(() => { if (!email) { history.replace('/forgot-password'); } }, [email, history]); useEffect(() => { if (cooldown <= 0) return; const timer = setTimeout(() => setCooldown((current) => current - 1), 1000); return () => clearTimeout(timer); }, [cooldown]); useEffect(() => { if (user && passwordUpdated && profileStatus !== 'loading') { loadProfileAndNavigate(); } }, [user, passwordUpdated, profileStatus]); const showMessage = (message: string, kind: 'error' | 'status') => { if (kind === 'error') { setError(message); setStatus(null); setTimeout(() => setError(null), 4000); } else { setStatus(message); setError(null); setTimeout(() => setStatus(null), 4000); } }; const loadProfileAndNavigate = async () => { if (!user) return; const data = await refreshProfile(); if ( !data || !data.first_name || !data.last_name || !data.phone || !data.country_of_residence ) { history.replace('/setup-profile'); } else { history.replace('/home'); } }; const handleDigitChange = (index: number, value: string) => { const nextCode = [...code]; nextCode[index] = value.replace(/\D/g, '').slice(-1); setCode(nextCode); }; const handlePaste = (event: React.ClipboardEvent) => { event.preventDefault(); const digits = event.clipboardData .getData('Text') .replace(/\D/g, '') .slice(0, 6); if (!digits) return; const nextCode = ['', '', '', '', '', '']; digits.split('').forEach((digit, index) => { nextCode[index] = digit; }); setCode(nextCode); }; const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); const token = code.join(''); if (token.length !== 6) { showMessage('Please enter the 6-digit reset code', 'error'); return; } if (newPassword.length < 6) { showMessage('Password must be at least 6 characters', 'error'); return; } setLoading(true); setError(null); setStatus(null); const { error: verifyError } = await supabase.auth.verifyOtp({ email: email!, token, type: 'recovery', }); if (verifyError) { showMessage(verifyError.message, 'error'); setLoading(false); return; } const { error: updateError } = await supabase.auth.updateUser({ password: newPassword, }); if (updateError) { showMessage(updateError.message, 'error'); setLoading(false); return; } showMessage('Password updated', 'status'); setPasswordUpdated(true); setLoading(false); }; const handleResend = async () => { if (cooldown > 0 || !email) return; const { error: resendError } = await supabase.auth.resetPasswordForEmail(email); if (resendError) { showMessage(resendError.message, 'error'); return; } showMessage('A new reset code has been sent', 'status'); setCooldown(60); }; return ( history.goBack()} style={ { '--color': '#111827', '--border-radius': '12px', } as React.CSSProperties } aria-label="Go back" > New password

Enter your reset code

Use the 6-digit code sent to {email}, then choose a new password.

setNewPassword(event.detail.value ?? '')} disabled={loading} placeholder="Enter a new password" style={ { '--background': '#fafafa', '--border-radius': '12px', '--padding-start': '14px', '--padding-end': '14px', '--highlight-color-focused': '#6d28d9', } as React.CSSProperties } /> {error && (

{error}

)} {status && (

{status}

)} {loading ? 'Updating password...' : 'Update password'}
); }; export default VerifyResetPage;