import React, { useEffect, useState, useRef } from 'react'; import { useTheme } from 'styled-components/native'; import { StyleSheet, Text, View, TextInput, SafeAreaView, TouchableOpacity, ScrollView, } from 'react-native'; import { UserVerification as UserVerificationController, UserFormDetails as UserFormController, useToast, useSession, useLanguage, ToastType, useConfig } from 'ordering-components/native'; import { OText, OInput, OButton, OModal } from '../shared'; import { LogoutButton } from '../LogoutButton' import { UserFormDetailsUI } from '../UserFormDetails' import { PhoneInputNumber } from '../PhoneInputNumber'; import { Container, InputsSection, WrapperText, InputWrapper, WrappCountdown, CountDownContainer, OtpSection, DigitInput, ButtonsActions, WrapperActions } from './styles' const CONDITIONAL_CODES = [1787] const TIME_COUNTDOWN = 60 * 10 // 10 minutes const UserDetails = (props: any) => { const userDetailsProps = { ...props, isEdit: true, useValidationFields: true, useDefualtSessionManager: true, UIComponent: UserFormDetailsUI } return } const UserVerificationUI = (props: any) => { const { verifyEmailState, verifyPhoneState, sendVerifyEmailCode, sendVerifyPhoneCode, checkVerifyEmailCode, checkVerifyPhoneCode, cleanErrorsState, useWhatsappVerification, } = props const theme = useTheme(); const [, t] = useLanguage() const [{ configs }] = useConfig() const [{ auth, user }] = useSession() const [, { showToast }] = useToast(); const isEmailVerifyRequired = auth && configs?.verification_email_required?.value === '1' && !user?.email_verified const isPhoneVerifyRequired = auth && configs?.verification_phone_required?.value === '1' && !user?.phone_verified const CODE_LENGTH = isEmailVerifyRequired ? 6 : 4 const ref = useRef(null); const [otpState, setOtpState] = useState('') const [timer, setTimer] = useState(`${TIME_COUNTDOWN / 60}:00`) const [isSendCodeAgain, setIsSendCodeAgain] = useState(false) const [containerIsFocused, setContainerIsFocused] = useState(false); const [phoneState, setPhoneState] = useState(null) const [verificationState, setVerificationState] = useState({ email: false, phone: false }) const [selectedChannel, setSelectedChannel] = useState(2) const codeDigitsArray = new Array(CODE_LENGTH).fill(0); const phoneLength = phoneState?.cellphone && phoneState?.country_phone_code && phoneState?.cellphone?.split('')?.length const lastNumbers = phoneState?.cellphone && phoneState?.country_phone_code && phoneState?.cellphone?.split('').fill('*', 0, phoneLength - 2).join('') const style = StyleSheet.create({ inputContainer: { borderWidth: 1, borderRadius: 7.6, padding: 12, borderColor: theme.colors.disabled, }, inputContainerFocused: { borderColor: theme.colors.primary, }, hiddenCodeInput: { position: 'absolute', height: 0, width: 0, opacity: 0, }, inputStyle: { marginBottom: 28, borderWidth: 1, borderColor: theme.colors.border, borderRadius: 7.6, }, btnStyle: { borderRadius: 7.6, marginTop: 5, marginBottom: 2 }, phoneSelect: { borderWidth: 0, marginStart: -5, marginEnd: 0, marginTop: -3, height: 32, width: 44 }, phoneInputStyle: { height: 30, borderWidth: 1, fontSize: 12, paddingBottom: 0, marginBottom: -0, paddingHorizontal: 10 } }); const handleOnPress = () => { setContainerIsFocused(true); ref?.current?.focus(); }; const handleOnBlur = () => { setContainerIsFocused(false); }; const toDigitInput = (_value: number, idx: number) => { const emptyInputChar = '0'; const digit = otpState[idx] || emptyInputChar; const isCurrentDigit = idx === otpState.length; const isLastDigit = idx === CODE_LENGTH - 1; const isCodeFull = otpState.length === CODE_LENGTH; const isFocused = isCurrentDigit || (isLastDigit && isCodeFull); const containerStyle = containerIsFocused && isFocused ? { ...style.inputContainer, ...style.inputContainerFocused } : style.inputContainer; return ( {digit} ); }; const handleSendOtp = (opt: string = '', channel?: number) => { setTimer(`${TIME_COUNTDOWN / 60}:00`) setIsSendCodeAgain(true) if (opt === 'phone') { const ch = channel || 2 setSelectedChannel(ch) let cellphone = phoneState?.cellphone let country_phone_code = phoneState?.country_phone_code if (CONDITIONAL_CODES.includes(Number(country_phone_code))) { if (Number(country_phone_code) === 1787) { cellphone = `787${cellphone}` country_phone_code = '1' } } sendVerifyPhoneCode({ cellphone, country_phone_code, channel: ch }) return } sendVerifyEmailCode({ email: user?.email }) } const setupUserPhoneNumber = () => { if (!user || !user?.cellphone || !user?.country_phone_code) return setPhoneState({ cellphone: user?.country_code === "PR" ? user?.cellphone.replace('787', '') : user?.cellphone, country_phone_code: user?.country_code === "PR" ? '1787' : user?.country_phone_code, formatted: `+${user?.country_phone_code} ${user?.cellphone}` }) } useEffect(() => { if (verificationState.phone) { let _timer = TIME_COUNTDOWN - 1; let minutes = 0; let seconds = 0; const interval = setInterval(() => { minutes = _timer / 60; seconds = _timer % 60; minutes = minutes < 10 ? 0 + minutes : minutes; seconds = seconds < 10 ? 0 + seconds : seconds; const formatMinutes = parseInt(minutes.toString()) < 10 ? `0${parseInt(minutes.toString())}` : parseInt(minutes.toString()); const formatseconds = parseInt(seconds.toString()) < 10 ? `0${parseInt(seconds.toString())}` : parseInt(seconds.toString()); setTimer(`${formatMinutes}:${formatseconds}`); if (--_timer < 0) { clearInterval(interval); } if (timer === `${TIME_COUNTDOWN / 60}:00` && isSendCodeAgain) { setIsSendCodeAgain(false) clearInterval(interval); } }, 1000); return () => clearInterval(interval) } }, [isSendCodeAgain, verificationState.phone]) useEffect(() => { if (otpState?.length === CODE_LENGTH) { if (verificationState.email) { checkVerifyEmailCode({ code: otpState }) return } if (verificationState.phone) { checkVerifyPhoneCode({ cellphone: phoneState?.cellphone, country_phone_code: +(phoneState?.country_phone_code), code: otpState, channel: selectedChannel }) return } } }, [otpState]) useEffect(() => { if (verifyEmailState?.errorSendCode || verifyEmailState?.errorCheckCode) { showToast( ToastType.Error, verifyEmailState?.errorSendCode?.[0] ?? verifyEmailState?.errorCheckCode?.[0] ?? t('ERROR', 'Error'), ); setTimeout(() => { cleanErrorsState(); cleanErrorsState('phone'); setOtpState(''); }, 2000); } if (verifyPhoneState?.errorSendCode || verifyPhoneState?.errorCheckCode) { showToast( ToastType.Error, verifyPhoneState?.errorSendCode?.[0] ?? verifyPhoneState?.errorCheckCode?.[0] ?? t('ERROR', 'Error'), ); setTimeout(() => { cleanErrorsState(); cleanErrorsState('phone'); setOtpState(''); }, 2000); } }, [verifyEmailState, verifyPhoneState]) useEffect(() => { if (!verifyEmailState?.loadingSendCode && isEmailVerifyRequired) { setVerificationState({ ...verificationState, email: !!verifyEmailState?.resultSendCode }) } if (!verifyPhoneState?.loadingSendCode && isPhoneVerifyRequired && !isEmailVerifyRequired) { setVerificationState({ ...verificationState, phone: !!verifyPhoneState?.resultSendCode }) } }, [verifyEmailState, verifyPhoneState]) useEffect(() => { setupUserPhoneNumber() }, [user?.cellphone, user?.country_phone_code]) return ( {t('VERIFICATION_CODE', 'Verification Code')} {isEmailVerifyRequired && ( {!verificationState.email ? ( t('VERIFICATION_EMAIL_CODE_MESSAGE', 'In order to continue using our platform please verify your email') ) : ( t('VERIFICATION_EMAIL_CODE_SENT_MESSAGE', 'Please type the verification code sent to your email') )} )} {isPhoneVerifyRequired && !isEmailVerifyRequired && ( {!verificationState.phone ? ( t('VERIFICATION_PHONE_CODE_MESSAGE', 'In order to continue using our platform please verify your phone number') ) : ( t('VERIFICATION_PHONE_CODE_SENT_MESSAGE', 'Please, enter the verification code we sent to your mobile ending with :number').replace(':number', lastNumbers) )} )} {isEmailVerifyRequired && ( !verificationState.email ? ( ) : ( <> {timer} {codeDigitsArray.map(toDigitInput)} handleSendOtp()} > {t('RESEND_AGAIN', 'Resend again?')} ) )} {isPhoneVerifyRequired && !isEmailVerifyRequired && ( !verificationState.phone ? ( phoneState?.formatted ? ( <> { }} defaultValue={phoneState?.cellphone} defaultCode={phoneState?.country_phone_code.replace('+', '')} boxStyle={style.phoneSelect} inputStyle={style.phoneInputStyle} defaultCodeFallback={phoneState?.country_phone_code.replace('+', '')} textStyle={{ color: theme.colors.textNormal, fontSize: 12, padding: 0 }} noDropIcon isDisabled updateStateWithSubmit /> ) : ( {t('WARNING_PHONE_CODE_VALIDATION', 'Please update your phone number to continue')} ) ) : ( <> {timer} {codeDigitsArray.map(toDigitInput)} handleSendOtp('phone', selectedChannel)} disabled={verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode} > {t('RESEND_AGAIN', 'Resend again?')} ) )} {!!phoneState?.cellphone && ( {(verificationState.email || verificationState.phone) ? ( setVerificationState({ email: false, phone: false })} text={t('CANCEL', 'Cancel')} bgColor={theme.colors.secundary} borderColor={theme.colors.secundary} textStyle={{ color: 'black' }} imgRightSrc={null} isLoading={verifyEmailState?.loadingSendCode || verifyEmailState?.loadingCheckCode || verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode} style={style.btnStyle} /> ) : useWhatsappVerification && isPhoneVerifyRequired && !isEmailVerifyRequired ? ( handleSendOtp('phone', 2)} text={t('SEND_BY_SMS', 'Send by SMS')} imgRightSrc={null} isLoading={verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode} parentStyle={{ flex: 1 }} style={{ borderRadius: 7.6 }} /> handleSendOtp('phone', 4)} text={t('SEND_BY_WHATSAPP', 'Send by WhatsApp')} imgRightSrc={null} isLoading={verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode} parentStyle={{ flex: 1 }} style={{ borderRadius: 7.6 }} /> ) : ( handleSendOtp(isPhoneVerifyRequired && !isEmailVerifyRequired ? 'phone' : '')} text={t('SEND_CODE', 'Send code')} imgRightSrc={null} isLoading={verifyEmailState?.loadingSendCode || verifyEmailState?.loadingCheckCode || verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode} style={{ borderRadius: 7.6 }} /> )} )} ) } export const UserVerification = (props: any) => { const verifyProps = { ...props, UIComponent: UserVerificationUI } return ( ) }