import { useRoute } from '@react-navigation/native' import React, { useEffect, useMemo, useState, useGlobal } from 'reactn' import { Text, View } from 'react-native' import { checkIfPasswordIsStrongEnough, handleFirebaseError } from '../actions/signupActions' import { background } from '../assets' import GradientButton from '../components/GradientButton' import { Input } from '../components/Input' import ItemContainer from '../components/ItemContainer/ItemContainer' import firebase from '../config/firebase' import Page from '../layouts/Page' import { isWeb } from '../hooks/useLayoutType' import { Routes } from '../navigation' import { navigate } from '../navigation/NavigationService' import { Palette } from '../styles' import { FONT_FAMILY } from '../styles/Fonts' const PASSWORD_ERROR_MESSAGE = 'Ton mot de passe doit contenir au moins 6 caractères et combiner plusieurs types de caractères.' const PASSWORD_MISMATCH_MESSAGE = 'Les mots de passe ne correspondent pas.' const INVALID_LINK_MESSAGE = "Ce lien de réinitialisation n'est plus valide. Demande un nouveau mot de passe." const ResetPassword = () => { const route = useRoute() const oobCode = (route?.params?.oobCode || '').trim() const [, setTooltip] = useGlobal('_tooltip') const [, setIsLoading] = useGlobal('_isLoading') const [email, setEmail] = useState(route?.params?.email || '') const [password, setPassword] = useState('') const [confirmPassword, setConfirmPassword] = useState('') const [passwordError, setPasswordError] = useState('') const [confirmError, setConfirmError] = useState('') const [codeError, setCodeError] = useState('') const [isVerifyingCode, setIsVerifyingCode] = useState(true) const [isSubmitting, setIsSubmitting] = useState(false) const trimmedPassword = useMemo(() => (password || '').trim(), [password]) const trimmedConfirmPassword = useMemo(() => (confirmPassword || '').trim(), [confirmPassword]) const isPasswordValid = useMemo(() => { if (!trimmedPassword.length) return false return checkIfPasswordIsStrongEnough({ password: trimmedPassword }) }, [trimmedPassword]) const doPasswordsMatch = useMemo(() => { if (!trimmedPassword.length || !trimmedConfirmPassword.length) return false return trimmedPassword === trimmedConfirmPassword }, [trimmedPassword, trimmedConfirmPassword]) useEffect(() => { const verifyCode = async () => { if (!oobCode) { setCodeError(INVALID_LINK_MESSAGE) setTooltip({ text: INVALID_LINK_MESSAGE, type: 'error' }) setIsVerifyingCode(false) return } try { setIsLoading(true) const resetEmail = await firebase.auth().verifyPasswordResetCode(oobCode) setEmail(resetEmail) setCodeError('') } catch (error) { console.log('ResetPassword verify error', error?.message) const message = error?.code && error.code.startsWith('auth/') ? handleFirebaseError(error.code) : error?.message || INVALID_LINK_MESSAGE setCodeError(message || INVALID_LINK_MESSAGE) setTooltip({ text: message || INVALID_LINK_MESSAGE, type: 'error' }) } finally { setIsLoading(false) setIsVerifyingCode(false) } } verifyCode() }, [oobCode, setIsLoading, setTooltip]) useEffect(() => { if (!password?.length) { setPasswordError('') return } if (!isPasswordValid) { setPasswordError(PASSWORD_ERROR_MESSAGE) } else { setPasswordError('') } }, [password, isPasswordValid]) useEffect(() => { if (!confirmPassword?.length) { setConfirmError('') return } if (!doPasswordsMatch) { setConfirmError(PASSWORD_MISMATCH_MESSAGE) } else { setConfirmError('') } }, [confirmPassword, doPasswordsMatch]) const handleSubmit = async () => { if (!isPasswordValid) { setPasswordError(PASSWORD_ERROR_MESSAGE) return } if (!doPasswordsMatch) { setConfirmError(PASSWORD_MISMATCH_MESSAGE) return } try { setIsSubmitting(true) setIsLoading(true) await firebase.auth().confirmPasswordReset(oobCode, trimmedPassword) setTooltip({ text: 'Ton mot de passe a été mis à jour. Tu peux te connecter.', type: 'success', }) navigate(Routes.Login) } catch (error) { console.log('ResetPassword submit error', error?.message) const message = error?.code && error.code.startsWith('auth/') ? handleFirebaseError(error.code) : error?.message || 'Impossible de mettre à jour le mot de passe.' setTooltip({ text: message, type: 'error' }) } finally { setIsLoading(false) setIsSubmitting(false) } } const renderForm = () => ( <> Définis un nouveau mot de passe Utilise au moins 6 caractères pour sécuriser ton compte. {email ? ( Compte concerné : {email} ) : null} {passwordError ? ( {passwordError} ) : null} {confirmError ? ( {confirmError} ) : null} ) const renderCodeError = () => ( Lien invalide ou expiré {codeError || INVALID_LINK_MESSAGE} ) const handleFallbackNavigation = () => { navigate(Routes.ForgotPassword) } const buttonDisabled = codeError ? isSubmitting : isVerifyingCode || isSubmitting || !isPasswordValid || !doPasswordsMatch const buttonLabel = codeError ? 'Demander un nouveau lien' : isSubmitting ? 'Mise à jour...' : isVerifyingCode ? 'Vérification...' : 'Mettre à jour le mot de passe' const buttonAction = codeError ? handleFallbackNavigation : handleSubmit return ( {codeError ? renderCodeError() : renderForm()} ) } export default ResetPassword