index.jsx 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. // components
  2. import PasswordInput from '@components/UInput/PasswordInput';
  3. import BasicCheckbox from '@ui/BasicCheckbox';
  4. import ResetPasswordPopup from '@components/ResetPasswordPopup';
  5. // hooks
  6. import {useForm, Controller} from 'react-hook-form';
  7. import {useNavigate} from 'react-router-dom';
  8. import React, {useState} from 'react';
  9. import styles from './styles.module.scss';
  10. import logo_dark from '@assets/logo/logo.png';
  11. import logo_light from '@assets/logo/logo_w.png';
  12. // utils
  13. import classNames from 'classnames';
  14. import {useThemeProvider} from "@contexts/themeContext";
  15. import Spring from "@components/Spring";
  16. import PhoneInput from "@components/UInput/PhoneInput";
  17. import {animated,useSpring} from "@react-spring/web";
  18. import {toast} from 'react-toastify';
  19. import {useDispatch, useSelector} from "react-redux";
  20. import {
  21. getAccountLogin,
  22. getChangePassStatus,
  23. getLoginStatus,
  24. getRegStatus,
  25. getSendCodeStatus,
  26. getSendCodeTS,
  27. getSMSLoginStatus
  28. } from "@features/mainSlice";
  29. import {useLocation} from "react-router";
  30. import {useEffect} from 'react';
  31. import SmallLoading from "@components/SmallLoading";
  32. import {REQ_STATUS} from "@api/config";
  33. import {reqForgetPass, reqLogin, reqRegister, reqSendCode, reqSMSLogin} from "@features/api";
  34. import {ROUTE_PATH} from "@constants/routes";
  35. import {APP_THEME} from "@constants/app";
  36. import {validateCountryPhone} from "@utils/helpers";
  37. import {CircularProgress} from "@mui/material";
  38. const i18n=global.i18n;
  39. const TYPE_LOGIN="login";
  40. const TYPE_REGISTER="register";
  41. const TYPE_FORGET_PASS="forgetPassword";
  42. const LOGIN_TYPE_PASS=0;
  43. const LOGIN_TYPE_OTP=1;
  44. const LOGIN_TYPE_ACOUNT=2;
  45. const REG_TYPE_PHONE=0;
  46. const REG_TYPE_ACCOUNT=1;
  47. const objInfo={
  48. cdTimer:null,
  49. inSubmit:false
  50. }
  51. const LoginForm = ({close}) => {
  52. const {theme,isMobile} = useThemeProvider();
  53. const [showType,setShowType]=useState(TYPE_LOGIN);
  54. const [open, setOpen] = useState(false);
  55. const [country, setCountry] = useState("55");
  56. const logourl=(theme===APP_THEME.DARK?logo_dark:logo_light);
  57. const loginStatus=useSelector(getLoginStatus);
  58. const regStatus=useSelector(getRegStatus);
  59. const forgetStatus=useSelector(getChangePassStatus);
  60. const dispatch = useDispatch();
  61. const navigate=useNavigate();
  62. const [loginType,setLoginType]=useState(LOGIN_TYPE_PASS);
  63. const {register, handleSubmit, formState: {errors}, control} = useForm({
  64. defaultValues: {
  65. // country:'55',
  66. account: '',
  67. password: '',
  68. email:"",
  69. repassword:"",
  70. lang:"",
  71. code:"",
  72. phone:"",
  73. newpassword:"",
  74. renewpassword:"",
  75. acc_account:"",
  76. acc_password:"",
  77. acc_repassword:""
  78. }
  79. });
  80. const {pathname,hash} = useLocation();
  81. const otpTimeStamp=useSelector(getSendCodeTS);
  82. const [otpCD,setOtpCD]=useState(-1);
  83. const otpStatus=useSelector(getSendCodeStatus);
  84. const smsLoginStatus=useSelector(getSMSLoginStatus);
  85. const isAccountLogin=useSelector(getAccountLogin);
  86. const [regType,setRegType]=useState(REG_TYPE_PHONE);
  87. const onSendCode=(e)=>{
  88. if (otpCD>0)return;
  89. if (otpStatus===REQ_STATUS.LOADING)return;
  90. let phone=control._formValues.phone;
  91. if (phone==null||phone==="")return;
  92. let validate=validatePhone(phone);
  93. if (!validate){
  94. control.setError("phone",true)
  95. return;
  96. }
  97. let params={phone:phone};
  98. dispatch(reqSendCode(params));
  99. }
  100. const getLeftCD=()=>{
  101. let now=Date.now();
  102. let delta=now-otpTimeStamp;
  103. delta=Math.floor(delta/1000);
  104. delta=60-delta;
  105. if (delta<0)return -1;
  106. else return delta;
  107. }
  108. const clearTimer=()=>{
  109. if (objInfo.cdTimer!=null){
  110. clearInterval(objInfo.cdTimer);
  111. objInfo.cdTimer=null;
  112. }
  113. }
  114. const onSubmitOTPLogin=(data)=>{
  115. if (smsLoginStatus===REQ_STATUS.LOADING)return;
  116. data.callback=onCallback;
  117. dispatch(reqSMSLogin(data));
  118. }
  119. useEffect(()=>{
  120. return ()=>{
  121. global.authLockPath=null;
  122. clearTimer();
  123. objInfo.inSubmit=false;
  124. }
  125. },[])
  126. useEffect(() => {
  127. if (hash===ROUTE_PATH.SIGN_IN){
  128. setShowType(TYPE_LOGIN);
  129. }
  130. else if (hash===ROUTE_PATH.SIGN_UP){
  131. setShowType(TYPE_REGISTER);
  132. }
  133. }, [pathname,hash]);
  134. useEffect(()=>{
  135. let left=getLeftCD();
  136. setOtpCD(left);
  137. clearTimer();
  138. if (left>0){
  139. objInfo.cdTimer=setInterval(()=>{
  140. left=getLeftCD();
  141. setOtpCD(left);
  142. if (left<0){
  143. clearTimer();
  144. }
  145. },1000)
  146. }
  147. },[otpTimeStamp])
  148. const navigatRoute=(route)=>{
  149. navigate(route,{replace:true});
  150. }
  151. const onCallback=(code)=>{
  152. // global.authLockPath=null;
  153. objInfo.inSubmit=false;
  154. if (code==200){
  155. if (global.authLockPath!=null){
  156. let path=global.authLockPath;
  157. global.authLockPath=null;
  158. navigate(path,{replace:true});
  159. }
  160. else{
  161. if (close)close();
  162. }
  163. }
  164. }
  165. const onSubmitLogin=(data)=>{
  166. if (loginStatus===REQ_STATUS.LOADING)return;
  167. if (objInfo.inSubmit)return;
  168. data.country=country;
  169. data.callback=onCallback;
  170. dispatch(reqLogin(data));
  171. objInfo.inSubmit=true;
  172. }
  173. const onSubmitReg=(data)=>{
  174. if (regStatus===REQ_STATUS.LOADING)return;
  175. if (objInfo.inSubmit)return;
  176. data.country=country;
  177. data.callback=onCallback;
  178. dispatch(reqRegister(data));
  179. objInfo.inSubmit=true;
  180. }
  181. const onSubmitForget=(data)=>{
  182. if (forgetStatus===REQ_STATUS.LOADING)return;
  183. if (objInfo.inSubmit)return;
  184. data.country=country;
  185. data.callback=onCallback;
  186. dispatch(reqForgetPass(data));
  187. objInfo.inSubmit=true;
  188. }
  189. const onSubmitAccountLogin=(data)=>{
  190. }
  191. const validatePhone=(value)=>{
  192. return validateCountryPhone(country,value);
  193. }
  194. const renderLoading=()=>{
  195. return (<SmallLoading fill={"#fff"}/>)
  196. }
  197. const renderLogo=()=>{
  198. return (
  199. <div className={styles.l_logo}>
  200. <img className={styles.logo_img} src={logourl}/>
  201. </div>
  202. )
  203. }
  204. const renderLoginToReg=()=>{
  205. return (
  206. <div className={styles.l_reg_new}>
  207. <div>{i18n.t("login.reg_new_des")}</div>
  208. <div className={styles.reg_btn} onClick={() => {
  209. // setShowType(TYPE_REGISTER);
  210. if (isMobile()) navigatRoute(ROUTE_PATH.SIGN_UP)
  211. else setShowType(TYPE_REGISTER);
  212. }}>
  213. {i18n.t("sign_up")}
  214. </div>
  215. </div>
  216. )
  217. }
  218. const renderGuestLogin=()=>{
  219. // return (
  220. // <button type={"button"} className={styles.guest_btn}>
  221. // {i18n.t("login.guest_login")}
  222. // </button>
  223. // )
  224. }
  225. //login__________
  226. const renderPassLogin = () => {
  227. return (
  228. <form key={"pass"} autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
  229. onSubmitLogin(data);
  230. })}>
  231. <Controller control={control}
  232. name="account"
  233. rules={{required: true}}
  234. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  235. let message = error ? i18n.t("form_errors.phone_" + country) : "";
  236. return (<PhoneInput
  237. key={"account"}
  238. className={classNames({'input-control--error': error})}
  239. value={value}
  240. message={message}
  241. onChange={e => onChange(e.target.value)}
  242. onChangeCountry={(country) => {
  243. setCountry(country);
  244. }}
  245. placeholder={i18n.t('login.phone_ph')}
  246. innerRef={ref}/>)
  247. }}
  248. />
  249. <Controller control={control}
  250. name="password"
  251. rules={{required: true, minLength: 6}}
  252. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  253. <PasswordInput
  254. className={classNames({'input-control--error': error})}
  255. value={value}
  256. message={error ? i18n.t("form_errors.pass") : ''}
  257. onChange={e => onChange(e.target.value)}
  258. placeholder={i18n.t('login.login_pwd')}
  259. innerRef={ref}/>
  260. )}
  261. />
  262. <div className={styles.l_forgot}>
  263. <button type={"button"} className={styles.forgot_btn} onClick={()=>{
  264. setShowType(TYPE_FORGET_PASS);
  265. }}>
  266. {i18n.t("login.forgot")}
  267. </button>
  268. </div>
  269. <button className={"button-green"}>
  270. {
  271. loginStatus === REQ_STATUS.LOADING ? renderLoading() : i18n.t("login.sign_in_btn")
  272. }
  273. </button>
  274. {renderGuestLogin()}
  275. {renderLoginToReg()}
  276. </form>
  277. )
  278. }
  279. const renderOTPLogin=()=>{
  280. return (
  281. <form key={"otp"} autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
  282. onSubmitOTPLogin(data);
  283. })}>
  284. <Controller control={control}
  285. name="phone"
  286. rules={{required: true}}
  287. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  288. let message = error ? i18n.t("form_errors.phone_" + country) : "";
  289. return (<PhoneInput
  290. key={"phone"}
  291. className={classNames({'input-control--error': error})}
  292. value={value}
  293. message={message}
  294. onChange={e => onChange(e.target.value)}
  295. onChangeCountry={(country) => {
  296. setCountry(country);
  297. }}
  298. placeholder={i18n.t('login.phone_ph')}
  299. innerRef={ref}/>)
  300. }}
  301. />
  302. <Controller control={control}
  303. name="code"
  304. rules={{required: true}}
  305. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  306. return (
  307. <div className={`d-flex flex-column g-6`}>
  308. <div
  309. className={`input-control ${classNames({'input-control--error': error})}`}>
  310. <input
  311. type={'text'}
  312. autoComplete="off"
  313. ref={ref}
  314. onChange={e => onChange(e.target.value)}
  315. placeholder={i18n.t('login.otp_ph')}
  316. />
  317. <button type={"button"}
  318. className={`${styles.otp_btn} ${otpCD > 0 ? styles.cd_timer : ''}`}
  319. onClick={onSendCode}>
  320. {
  321. otpStatus === REQ_STATUS.LOADING ? (
  322. <CircularProgress color="success" size={22} thickness={5}/>) : (
  323. <>
  324. {
  325. otpCD <= 0 ? i18n.t('login.btn_otp') : otpCD + "S"
  326. }
  327. </>
  328. )
  329. }
  330. </button>
  331. </div>
  332. </div>
  333. )
  334. }}
  335. />
  336. <button className={"button-green"}>
  337. {
  338. smsLoginStatus === REQ_STATUS.LOADING ? renderLoading() : i18n.t("login.sign_in_btn")
  339. }
  340. </button>
  341. {renderGuestLogin()}
  342. {renderLoginToReg()}
  343. </form>
  344. )
  345. }
  346. const renderAccountLogin=()=>{
  347. return (
  348. <form key={"account"} autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
  349. onSubmitAccountLogin(data);
  350. })}>
  351. <Controller control={control}
  352. name="acc_account"
  353. rules={{required: true, minLength: 6}}
  354. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  355. return (
  356. <div className={`d-flex flex-column g-6`}>
  357. <div
  358. className={`input-control ${classNames({'input-control--error': error})}`}>
  359. <input
  360. type={'text'}
  361. autoComplete="off"
  362. ref={ref}
  363. onChange={e => onChange(e.target.value)}
  364. placeholder={i18n.t('login.account_ph')}
  365. />
  366. </div>
  367. {
  368. error?(<div className="input-prompt-error">{i18n.t('form_errors.account')}</div>):(<></>)
  369. }
  370. </div>
  371. )
  372. }}
  373. />
  374. <Controller control={control}
  375. name="acc_password"
  376. rules={{required: true, minLength: 6}}
  377. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  378. <PasswordInput
  379. className={classNames({'input-control--error': error})}
  380. value={value}
  381. message={error ? i18n.t("form_errors.pass") : ''}
  382. onChange={e => onChange(e.target.value)}
  383. placeholder={i18n.t('login.login_pwd')}
  384. innerRef={ref}/>
  385. )}
  386. />
  387. <button className={"button-green"}>
  388. {
  389. loginStatus === REQ_STATUS.LOADING ? renderLoading() : i18n.t("login.sign_in_btn")
  390. }
  391. </button>
  392. {renderGuestLogin()}
  393. {renderLoginToReg()}
  394. </form>
  395. )
  396. }
  397. const renderLoginType = () => {
  398. if (loginType === LOGIN_TYPE_PASS) {
  399. return renderPassLogin();
  400. } else if (loginType === LOGIN_TYPE_OTP){
  401. return renderOTPLogin();
  402. } else if (loginType === LOGIN_TYPE_ACOUNT){
  403. return renderAccountLogin();
  404. }
  405. return (<></>);
  406. }
  407. const renderLoginForm = () => {
  408. return (
  409. <Spring type="slideUp">
  410. <div className={styles.l_title}>{i18n.t("login.login_title")}</div>
  411. <div className={styles.l_type_tabs}>
  412. <button className={`${styles.l_type_btn} ${loginType === LOGIN_TYPE_PASS ? styles.active : ''}`}
  413. onClick={() => {
  414. setLoginType(LOGIN_TYPE_PASS)
  415. }}>
  416. <span>{i18n.t("login.login_type.password")}</span>
  417. </button>
  418. <button className={`${styles.l_type_btn} ${loginType === LOGIN_TYPE_OTP ? styles.active : ''}`}
  419. onClick={() => {
  420. setLoginType(LOGIN_TYPE_OTP)
  421. }}>
  422. <span>{i18n.t("login.login_type.otp")}</span>
  423. </button>
  424. {
  425. isAccountLogin?(
  426. <button className={`${styles.l_type_btn} ${loginType === LOGIN_TYPE_ACOUNT ? styles.active : ''}`}
  427. onClick={() => {
  428. setLoginType(LOGIN_TYPE_ACOUNT)
  429. }}>
  430. <span>{i18n.t("login.login_type.account")}</span>
  431. </button>
  432. ):(<></>)
  433. }
  434. </div>
  435. {
  436. // loginType===LOGIN_TYPE_PASS?renderPassLogin():renderOTPLogin()
  437. renderLoginType()
  438. }
  439. </Spring>
  440. )
  441. }
  442. //login__________
  443. //register_______________
  444. const renderRegToLogin=()=>{
  445. return (
  446. <div className={styles.l_reg_new}>
  447. <div>{i18n.t("login.login_des")}</div>
  448. <div className={styles.reg_btn} onClick={() => {
  449. // setShowType(TYPE_LOGIN);
  450. if (isMobile()) navigatRoute(ROUTE_PATH.SIGN_IN)
  451. else setShowType(TYPE_LOGIN);
  452. }}>
  453. {i18n.t("login.sign_in_btn")}
  454. </div>
  455. </div>
  456. )
  457. }
  458. const renderRegPhone = () => {
  459. return (
  460. <form key={"reg_phone"} autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
  461. onSubmitReg(data);
  462. })}>
  463. <Controller control={control}
  464. name="account"
  465. rules={{required: true, validate: validatePhone}}
  466. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  467. let message = error ? i18n.t("form_errors.phone_" + country) : "";
  468. return (<PhoneInput
  469. className={classNames({'input-control--error': error})}
  470. value={value}
  471. message={message}
  472. onChange={e => onChange(e.target.value)}
  473. onChangeCountry={(country) => {
  474. setCountry(country);
  475. }}
  476. placeholder={i18n.t('login.phone_ph')}
  477. innerRef={ref}/>)
  478. }}
  479. />
  480. <Controller control={control}
  481. name="password"
  482. rules={{required: true, minLength: 6}}
  483. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  484. <PasswordInput
  485. className={classNames({'input-control--error': error})}
  486. value={value}
  487. message={error ? i18n.t("form_errors.pass") : ''}
  488. onChange={e => onChange(e.target.value)}
  489. placeholder={i18n.t('login.login_pwd')}
  490. innerRef={ref}/>
  491. )}
  492. />
  493. <Controller control={control}
  494. name="repassword"
  495. rules={{required: true, minLength: 6}}
  496. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  497. <PasswordInput
  498. className={classNames({'input-control--error': error})}
  499. value={value}
  500. message={error ? i18n.t("form_errors.pass") : ''}
  501. onChange={e => onChange(e.target.value)}
  502. placeholder={i18n.t('login.re_pwd')}
  503. innerRef={ref}/>
  504. )}
  505. />
  506. <button className={"button-green"}>
  507. {
  508. regStatus === REQ_STATUS.LOADING ? renderLoading() : i18n.t("login.sign_up_btn")
  509. }
  510. </button>
  511. {renderRegToLogin()}
  512. </form>
  513. )
  514. }
  515. const renderRegAccount=()=>{
  516. return (
  517. <form key={"reg_account"} autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
  518. // onSubmitReg(data);
  519. })}>
  520. <Controller control={control}
  521. name="acc_account"
  522. rules={{required: true, minLength: 6}}
  523. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  524. return (
  525. <div className={`d-flex flex-column g-6`}>
  526. <div
  527. className={`input-control ${classNames({'input-control--error': error})}`}>
  528. <input
  529. type={'text'}
  530. autoComplete="off"
  531. ref={ref}
  532. onChange={e => onChange(e.target.value)}
  533. placeholder={i18n.t('login.account_ph')}
  534. />
  535. </div>
  536. {
  537. error?(<div className="input-prompt-error">{i18n.t('form_errors.account')}</div>):(<></>)
  538. }
  539. </div>
  540. )
  541. }}
  542. />
  543. <Controller control={control}
  544. name="acc_password"
  545. rules={{required: true, minLength: 6}}
  546. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  547. <PasswordInput
  548. className={classNames({'input-control--error': error})}
  549. value={value}
  550. message={error ? i18n.t("form_errors.pass") : ''}
  551. onChange={e => onChange(e.target.value)}
  552. placeholder={i18n.t('login.login_pwd')}
  553. innerRef={ref}/>
  554. )}
  555. />
  556. <Controller control={control}
  557. name="acc_repassword"
  558. rules={{required: true, minLength: 6}}
  559. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  560. <PasswordInput
  561. className={classNames({'input-control--error': error})}
  562. value={value}
  563. message={error ? i18n.t("form_errors.pass") : ''}
  564. onChange={e => onChange(e.target.value)}
  565. placeholder={i18n.t('login.re_pwd')}
  566. innerRef={ref}/>
  567. )}
  568. />
  569. <button className={"button-green"}>
  570. {
  571. regStatus === REQ_STATUS.LOADING ? renderLoading() : i18n.t("login.sign_up_btn")
  572. }
  573. </button>
  574. {renderRegToLogin()}
  575. </form>
  576. )
  577. }
  578. const renderRegType=()=>{
  579. if (regType===REG_TYPE_PHONE){
  580. return renderRegPhone();
  581. }
  582. else if (regType===REG_TYPE_ACCOUNT){
  583. return renderRegAccount();
  584. }
  585. return (<></>);
  586. }
  587. const renderRegisterForm = () => {
  588. return (
  589. <Spring type="slideUp">
  590. <div className={styles.l_title}>{i18n.t("login.reg_title")}</div>
  591. {
  592. isAccountLogin?(
  593. <div className={styles.l_type_tabs}>
  594. <button className={`${styles.l_type_btn} ${regType === REG_TYPE_PHONE ? styles.active : ''}`}
  595. onClick={() => {
  596. setRegType(REG_TYPE_PHONE);
  597. }}>
  598. <span>{i18n.t("login.reg_type.phone")}</span>
  599. </button>
  600. <button
  601. className={`${styles.l_type_btn} ${regType === REG_TYPE_ACCOUNT ? styles.active : ''}`}
  602. onClick={() => {
  603. setRegType(REG_TYPE_ACCOUNT)
  604. }}>
  605. <span>{i18n.t("login.login_type.account")}</span>
  606. </button>
  607. </div>
  608. ):(<></>)
  609. }
  610. {renderRegType()}
  611. </Spring>
  612. )
  613. }
  614. //register_______________
  615. const renderForgetForm = () => {
  616. return (
  617. <Spring type="slideUp">
  618. <div className={styles.l_title}>{i18n.t("login.forget_title")}</div>
  619. <form key={"forget"} autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
  620. onSubmitForget(data);
  621. })}>
  622. <Controller control={control}
  623. name="phone"
  624. rules={{required: true}}
  625. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  626. let message = error ? i18n.t("form_errors.phone_" + country) : "";
  627. return (<PhoneInput
  628. key={"phone"}
  629. className={classNames({'input-control--error': error})}
  630. value={value}
  631. message={message}
  632. onChange={e => onChange(e.target.value)}
  633. onChangeCountry={(country) => {
  634. setCountry(country);
  635. }}
  636. placeholder={i18n.t('login.phone_ph')}
  637. innerRef={ref}/>)
  638. }}
  639. />
  640. <Controller control={control}
  641. name="newpassword"
  642. rules={{required: true, minLength: 6}}
  643. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  644. <PasswordInput
  645. className={classNames({'input-control--error': error})}
  646. value={value}
  647. message={error ? i18n.t("form_errors.pass") : ''}
  648. onChange={e => onChange(e.target.value)}
  649. placeholder={i18n.t('user.password.newpassword')}
  650. innerRef={ref}/>
  651. )}
  652. />
  653. <Controller control={control}
  654. name="renewpassword"
  655. rules={{required: true, minLength: 6}}
  656. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  657. <PasswordInput
  658. className={classNames({'input-control--error': error})}
  659. value={value}
  660. message={error ? i18n.t("form_errors.pass") : ''}
  661. onChange={e => onChange(e.target.value)}
  662. placeholder={i18n.t('user.password.renewpassword')}
  663. innerRef={ref}/>
  664. )}
  665. />
  666. <Controller control={control}
  667. name="code"
  668. rules={{required: true}}
  669. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  670. return (
  671. <div className={`d-flex flex-column g-6`}>
  672. <div
  673. className={`input-control ${classNames({'input-control--error': error})}`}>
  674. <input
  675. type={'text'}
  676. autoComplete="off"
  677. ref={ref}
  678. onChange={e => onChange(e.target.value)}
  679. placeholder={i18n.t('login.otp_ph')}
  680. />
  681. <button type={"button"}
  682. className={`${styles.otp_btn} ${otpCD > 0 ? styles.cd_timer : ''}`}
  683. onClick={onSendCode}>
  684. {
  685. otpStatus === REQ_STATUS.LOADING ? (
  686. <CircularProgress color="success" size={22}
  687. thickness={5}/>) : (
  688. <>
  689. {
  690. otpCD <= 0 ? i18n.t('login.btn_otp') : otpCD + "S"
  691. }
  692. </>
  693. )
  694. }
  695. </button>
  696. </div>
  697. </div>
  698. )
  699. }}
  700. />
  701. <button className={"button-green"}>
  702. {
  703. forgetStatus === REQ_STATUS.LOADING ? (
  704. <SmallLoading fill={"#fff"}/>) : i18n.t("login.forget_title")
  705. }
  706. </button>
  707. <div className={styles.l_reg_new}>
  708. <div>{i18n.t("login.back_to_login")}</div>
  709. <div className={styles.reg_btn} onClick={() => {
  710. setShowType(TYPE_LOGIN);
  711. }}>
  712. {i18n.t("login.sign_in_btn")}
  713. </div>
  714. </div>
  715. </form>
  716. </Spring>
  717. )
  718. }
  719. const renderForm = () => {
  720. let form = (<></>);
  721. if (showType === TYPE_LOGIN) {
  722. form = renderLoginForm();
  723. } else if (showType === TYPE_REGISTER) {
  724. form = renderRegisterForm();
  725. } else if (showType === TYPE_FORGET_PASS) {
  726. form = renderForgetForm();
  727. }
  728. return (
  729. <div className={styles.l_form_container}>
  730. {form}
  731. </div>
  732. )
  733. }
  734. return (
  735. <div className={styles.container}>
  736. {renderLogo()}
  737. {renderForm()}
  738. </div>
  739. )
  740. }
  741. export default LoginForm;