|
|
@@ -19,12 +19,19 @@ import PhoneInput from "@components/UInput/PhoneInput";
|
|
|
import {animated,useSpring} from "@react-spring/web";
|
|
|
import {toast} from 'react-toastify';
|
|
|
import {useDispatch, useSelector} from "react-redux";
|
|
|
-import {getLoginStatus, getRegStatus, getSendCodeStatus, getSendCodeTS, getSMSLoginStatus} from "@features/mainSlice";
|
|
|
+import {
|
|
|
+ getChangePassStatus,
|
|
|
+ getLoginStatus,
|
|
|
+ getRegStatus,
|
|
|
+ getSendCodeStatus,
|
|
|
+ getSendCodeTS,
|
|
|
+ getSMSLoginStatus
|
|
|
+} from "@features/mainSlice";
|
|
|
import {useLocation} from "react-router";
|
|
|
import {useEffect} from 'react';
|
|
|
import SmallLoading from "@components/SmallLoading";
|
|
|
import {REQ_STATUS} from "@api/config";
|
|
|
-import {reqLogin, reqRegister, reqSendCode, reqSMSLogin} from "@features/api";
|
|
|
+import {reqForgetPass, reqLogin, reqRegister, reqSendCode, reqSMSLogin} from "@features/api";
|
|
|
import {ROUTE_PATH} from "@constants/routes";
|
|
|
import {APP_THEME} from "@constants/app";
|
|
|
import {validateCountryPhone} from "@utils/helpers";
|
|
|
@@ -33,11 +40,13 @@ import {CircularProgress} from "@mui/material";
|
|
|
const i18n=global.i18n;
|
|
|
const TYPE_LOGIN="login";
|
|
|
const TYPE_REGISTER="register";
|
|
|
+const TYPE_FORGET_PASS="forgetPassword";
|
|
|
|
|
|
const LOGIN_TYPE_PASS=0;
|
|
|
const LOGIN_TYPE_OTP=1;
|
|
|
const objInfo={
|
|
|
- cdTimer:null
|
|
|
+ cdTimer:null,
|
|
|
+ inSubmit:false
|
|
|
}
|
|
|
|
|
|
const LoginForm = ({close}) => {
|
|
|
@@ -48,6 +57,7 @@ const LoginForm = ({close}) => {
|
|
|
const logourl=(theme===APP_THEME.DARK?logo_dark:logo_light);
|
|
|
const loginStatus=useSelector(getLoginStatus);
|
|
|
const regStatus=useSelector(getRegStatus);
|
|
|
+ const forgetStatus=useSelector(getChangePassStatus);
|
|
|
const dispatch = useDispatch();
|
|
|
const navigate=useNavigate();
|
|
|
const [loginType,setLoginType]=useState(LOGIN_TYPE_PASS);
|
|
|
@@ -60,7 +70,9 @@ const LoginForm = ({close}) => {
|
|
|
repassword:"",
|
|
|
lang:"",
|
|
|
code:"",
|
|
|
- phone:""
|
|
|
+ phone:"",
|
|
|
+ newpassword:"",
|
|
|
+ renewpassword:""
|
|
|
}
|
|
|
});
|
|
|
const {pathname,hash} = useLocation();
|
|
|
@@ -104,6 +116,7 @@ const LoginForm = ({close}) => {
|
|
|
return ()=>{
|
|
|
global.authLockPath=null;
|
|
|
clearTimer();
|
|
|
+ objInfo.inSubmit=false;
|
|
|
}
|
|
|
},[])
|
|
|
useEffect(() => {
|
|
|
@@ -133,6 +146,7 @@ const LoginForm = ({close}) => {
|
|
|
}
|
|
|
const onCallback=(code)=>{
|
|
|
// global.authLockPath=null;
|
|
|
+ objInfo.inSubmit=false;
|
|
|
if (code==200){
|
|
|
if (global.authLockPath!=null){
|
|
|
let path=global.authLockPath;
|
|
|
@@ -146,15 +160,27 @@ const LoginForm = ({close}) => {
|
|
|
}
|
|
|
const onSubmitLogin=(data)=>{
|
|
|
if (loginStatus===REQ_STATUS.LOADING)return;
|
|
|
+ if (objInfo.inSubmit)return;
|
|
|
data.country=country;
|
|
|
data.callback=onCallback;
|
|
|
dispatch(reqLogin(data));
|
|
|
+ objInfo.inSubmit=true;
|
|
|
}
|
|
|
const onSubmitReg=(data)=>{
|
|
|
if (regStatus===REQ_STATUS.LOADING)return;
|
|
|
+ if (objInfo.inSubmit)return;
|
|
|
data.country=country;
|
|
|
data.callback=onCallback;
|
|
|
dispatch(reqRegister(data));
|
|
|
+ objInfo.inSubmit=true;
|
|
|
+ }
|
|
|
+ const onSubmitForget=(data)=>{
|
|
|
+ if (forgetStatus===REQ_STATUS.LOADING)return;
|
|
|
+ if (objInfo.inSubmit)return;
|
|
|
+ data.country=country;
|
|
|
+ data.callback=onCallback;
|
|
|
+ dispatch(reqForgetPass(data));
|
|
|
+ objInfo.inSubmit=true;
|
|
|
}
|
|
|
const validatePhone=(value)=>{
|
|
|
return validateCountryPhone(country,value);
|
|
|
@@ -226,6 +252,13 @@ const LoginForm = ({close}) => {
|
|
|
innerRef={ref}/>
|
|
|
)}
|
|
|
/>
|
|
|
+ <div className={styles.l_forgot}>
|
|
|
+ <button type={"button"} className={styles.forgot_btn} onClick={()=>{
|
|
|
+ setShowType(TYPE_FORGET_PASS);
|
|
|
+ }}>
|
|
|
+ {i18n.t("login.forgot")}
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
<button className={"button-green"}>
|
|
|
{
|
|
|
loginStatus === REQ_STATUS.LOADING ? renderLoading() : i18n.t("login.sign_in_btn")
|
|
|
@@ -396,13 +429,118 @@ const LoginForm = ({close}) => {
|
|
|
</Spring>
|
|
|
)
|
|
|
}
|
|
|
- const renderForm=()=>{
|
|
|
- let form=(<></>);
|
|
|
- if (showType===TYPE_LOGIN){
|
|
|
- form=renderLoginForm();
|
|
|
- }
|
|
|
- else if (showType===TYPE_REGISTER){
|
|
|
- form=renderRegisterForm();
|
|
|
+ const renderForgetForm=()=>{
|
|
|
+ return (
|
|
|
+ <Spring type="slideUp">
|
|
|
+ <div className={styles.l_title}>{i18n.t("login.forget_title")}</div>
|
|
|
+ <form key={"forget"} autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
|
|
|
+ onSubmitForget(data);
|
|
|
+ })}>
|
|
|
+ <Controller control={control}
|
|
|
+ name="phone"
|
|
|
+ rules={{required: true}}
|
|
|
+ render={({field: {ref, onChange, value}, fieldState: {error}}) => {
|
|
|
+ let message = error ? i18n.t("form_errors.phone_" + country) : "";
|
|
|
+ return (<PhoneInput
|
|
|
+ key={"phone"}
|
|
|
+ className={classNames({'input-control--error': error})}
|
|
|
+ value={value}
|
|
|
+ message={message}
|
|
|
+ onChange={e => onChange(e.target.value)}
|
|
|
+ onChangeCountry={(country) => {
|
|
|
+ setCountry(country);
|
|
|
+ }}
|
|
|
+ placeholder={i18n.t('login.phone_ph')}
|
|
|
+ innerRef={ref}/>)
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Controller control={control}
|
|
|
+ name="newpassword"
|
|
|
+ rules={{required: true, minLength: 6}}
|
|
|
+ render={({field: {ref, onChange, value}, fieldState: {error}}) => (
|
|
|
+ <PasswordInput
|
|
|
+ className={classNames({'input-control--error': error})}
|
|
|
+ value={value}
|
|
|
+ message={error ? i18n.t("form_errors.pass") : ''}
|
|
|
+ onChange={e => onChange(e.target.value)}
|
|
|
+ placeholder={i18n.t('user.password.newpassword')}
|
|
|
+ innerRef={ref}/>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ <Controller control={control}
|
|
|
+ name="renewpassword"
|
|
|
+ rules={{required: true, minLength: 6}}
|
|
|
+ render={({field: {ref, onChange, value}, fieldState: {error}}) => (
|
|
|
+ <PasswordInput
|
|
|
+ className={classNames({'input-control--error': error})}
|
|
|
+ value={value}
|
|
|
+ message={error ? i18n.t("form_errors.pass") : ''}
|
|
|
+ onChange={e => onChange(e.target.value)}
|
|
|
+ placeholder={i18n.t('user.password.renewpassword')}
|
|
|
+ innerRef={ref}/>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ <Controller control={control}
|
|
|
+ name="code"
|
|
|
+ rules={{required: true}}
|
|
|
+ render={({field: {ref, onChange, value}, fieldState: {error}}) => {
|
|
|
+ return (
|
|
|
+ <div className={`d-flex flex-column g-6`}>
|
|
|
+ <div
|
|
|
+ className={`input-control ${classNames({'input-control--error': error})}`}>
|
|
|
+ <input
|
|
|
+ type={'text'}
|
|
|
+ autoComplete="off"
|
|
|
+ ref={ref}
|
|
|
+ onChange={e => onChange(e.target.value)}
|
|
|
+ placeholder={i18n.t('login.otp_ph')}
|
|
|
+ />
|
|
|
+ <button type={"button"}
|
|
|
+ className={`${styles.otp_btn} ${otpCD > 0 ? styles.cd_timer : ''}`}
|
|
|
+ onClick={onSendCode}>
|
|
|
+ {
|
|
|
+ otpStatus === REQ_STATUS.LOADING ? (
|
|
|
+ <CircularProgress color="success" size={22}
|
|
|
+ thickness={5}/>) : (
|
|
|
+ <>
|
|
|
+ {
|
|
|
+ otpCD <= 0 ? i18n.t('login.btn_otp') : otpCD + "S"
|
|
|
+ }
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <button className={"button-green"}>
|
|
|
+ {
|
|
|
+ forgetStatus === REQ_STATUS.LOADING ? (
|
|
|
+ <SmallLoading fill={"#fff"}/>) : i18n.t("login.forget_title")
|
|
|
+ }
|
|
|
+ </button>
|
|
|
+ <div className={styles.l_reg_new}>
|
|
|
+ <div>{i18n.t("login.back_to_login")}</div>
|
|
|
+ <div className={styles.reg_btn} onClick={() => {
|
|
|
+ setShowType(TYPE_LOGIN);
|
|
|
+ }}>
|
|
|
+ {i18n.t("login.sign_in_btn")}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ </Spring>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ const renderForm = () => {
|
|
|
+ let form = (<></>);
|
|
|
+ if (showType === TYPE_LOGIN) {
|
|
|
+ form = renderLoginForm();
|
|
|
+ } else if (showType === TYPE_REGISTER) {
|
|
|
+ form = renderRegisterForm();
|
|
|
+ } else if (showType === TYPE_FORGET_PASS) {
|
|
|
+ form = renderForgetForm();
|
|
|
}
|
|
|
return (
|
|
|
<div className={styles.l_form_container}>
|