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 (
)
}