// hooks import { useForm, Controller } from 'react-hook-form'; import React, { useCallback, useState } from 'react'; import styles from './styles.module.scss'; // utils import classNames from 'classnames'; import PhoneInput from "@components/UInput/PhoneInput"; import { useDispatch, useSelector } from "react-redux"; import { getSendCodeStatus, getSendCodeTS, } from "@features/mainSlice"; import { useEffect } from 'react'; import { REQ_STATUS } from "@api/config"; import { reqSendCode } from "@features/api"; import { getCountryPhoneError, validateCountryPhone } from "@utils/helpers"; import { CircularProgress } from "@mui/material"; import { toast } from 'react-toastify'; import MainButton from '@components/Buttons/MainButton'; import { ReactComponent as AlertIcon } from '@assets/singlesvg/icon_alert.svg'; import { getPhoneCode } from '@constants/region'; const i18n = global.i18n; const objInfo = { cdTimer: null, inSubmit: false } const CODE_MIN = 4; const CODE_MAX = 4; const DEFAULT_COUNTRY = String(getPhoneCode()).replace(/^\+/, "") || "44"; const PhoneSMS = ({ children, callback, buttonText, handleStatus, onCountryChange, options = {}, defValues = {}, className = '' }) => { const [country, setCountry] = useState(DEFAULT_COUNTRY); const [phoneValid, setPhoneValid] = useState(Boolean(defValues.phone)); const [phoneMessage] = useState(""); const [sendCount, setSendCount] = useState(0); const dispatch = useDispatch(); const { handleSubmit, control, watch } = useForm({ defaultValues: { // country 由当前区域配置决定。 account: '', password: '', email: "", repassword: "", lang: "", code: "", phone: defValues.phone || "", newpassword: "", renewpassword: "" } }); const otpTimeStamp = useSelector(getSendCodeTS); const [otpCD, setOtpCD] = useState(-1); const otpStatus = useSelector(getSendCodeStatus); const onSendCode = (e) => { if (otpCD > 0) return; if (otpStatus === REQ_STATUS.LOADING) return; let phone = control._formValues.phone; let validate = validatePhone(phone); if (!validate) { let msg = getCountryPhoneError(country); toast.warn(i18n.t(msg), { toastId: "phone_sms" }); // toast.warn(i18n.t("phoneSms.tips_phone"), { toastId: "phone_sms" }); control.setError("phone", true); return; } let params = { phone: phone, country: country }; dispatch(reqSendCode(params)); } const getLeftCD = useCallback(() => { let now = Date.now(); let delta = now - otpTimeStamp; delta = Math.floor(delta / 1000); delta = 60 - delta; if (delta < 0) return -1; else return delta; }, [otpTimeStamp]); const checkPhone = (value) => { const ok = validatePhone(value); if (!ok) { setPhoneValid(false); } else { setPhoneValid(true); } return ok; } const clearTimer = () => { if (objInfo.cdTimer != null) { clearInterval(objInfo.cdTimer); objInfo.cdTimer = null; } } //effect_______ useEffect(() => { return () => { global.authLockPath = null; clearTimer(); objInfo.inSubmit = false; } }, []) useEffect(() => { let left = getLeftCD(); setOtpCD(left); clearTimer(); if (left > 0) { objInfo.cdTimer = setInterval(() => { left = getLeftCD(); setOtpCD(left); if (left < 0) { setSendCount(prev => prev + 1); clearTimer(); } }, 1000) } }, [getLeftCD]) const validatePhone = (value, countryCode = country) => { if (String(defValues.phone) === String(value) && value.length > 0) return true; return validateCountryPhone(countryCode, value || ""); } const codeValue = watch("code"); const phoneValue = watch("phone"); const checkCode = () => { return (!codeValue || codeValue.length < CODE_MIN || codeValue.length > CODE_MAX) } const checkFormOnClaim = (tips = true) => { if (!checkPhone(phoneValue)) { control.setError("phone", true); if (tips) toast.warn(i18n.t("phoneSms.tips_phone"), { toastId: "phone_sms" }); return false; } if (!codeValue || codeValue.length < CODE_MIN || codeValue.length > CODE_MAX) { control.setError("code", true); if (tips) toast.warn(i18n.t("phoneSms.tips_info"), { toastId: "phone_sms" }); return false; } return true; } const onSubmitOTPLogin = (data) => { if (!checkFormOnClaim()) return; //data.phone data.code data.country = country; callback && callback(data); } return (
{ onSubmitOTPLogin(data); })}> { let message = phoneMessage; return ( { onChange(e.target.value); setPhoneValid(validatePhone(e.target.value)); } } onChangeCountry={(country) => { setCountry(country); setPhoneValid(validatePhone(control._formValues.phone, country)); if (onCountryChange != null) onCountryChange(country); }} placeholder={i18n.t('login.phone_ph')} innerRef={ref} {...options} />) }} /> { return (
{ e.target.value = e.target.value.replace(/\D+/g, ''); onChange(e.target.value) }} placeholder={i18n.t('login.otp_ph')} />
) }} />
{i18n.t('login.otp_tips')}
{buttonText} {children} ) } export default PhoneSMS;