index.jsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 {getLoginStatus, getRegStatus} from "@features/mainSlice";
  21. import {useLocation} from "react-router";
  22. import {useEffect} from 'react';
  23. import SmallLoading from "@components/SmallLoading";
  24. import {REQ_STATUS} from "@api/config";
  25. import {reqLogin, reqRegister} from "@features/api";
  26. import {ROUTE_PATH} from "@constants/routes";
  27. import {APP_THEME} from "@constants/app";
  28. import {validateCountryPhone} from "@utils/helpers";
  29. const i18n=global.i18n;
  30. const TYPE_LOGIN="login";
  31. const TYPE_REGISTER="register";
  32. const LoginForm = ({close}) => {
  33. const {theme,isMobile} = useThemeProvider();
  34. const [showType,setShowType]=useState(TYPE_LOGIN);
  35. const [open, setOpen] = useState(false);
  36. const [country, setCountry] = useState("55");
  37. const logourl=(theme===APP_THEME.DARK?logo_dark:logo_light);
  38. const loginStatus=useSelector(getLoginStatus);
  39. const regStatus=useSelector(getRegStatus);
  40. const dispatch = useDispatch();
  41. const navigate=useNavigate();
  42. const {register, handleSubmit, formState: {errors}, control} = useForm({
  43. defaultValues: {
  44. // country:'55',
  45. account: '',
  46. password: '',
  47. email:"",
  48. repassword:"",
  49. lang:""
  50. }
  51. });
  52. const {pathname,hash} = useLocation();
  53. useEffect(()=>{
  54. return ()=>{
  55. global.authLockPath=null;
  56. }
  57. },[])
  58. useEffect(() => {
  59. if (hash===ROUTE_PATH.SIGN_IN){
  60. setShowType(TYPE_LOGIN);
  61. }
  62. else if (hash===ROUTE_PATH.SIGN_UP){
  63. setShowType(TYPE_REGISTER);
  64. }
  65. }, [pathname,hash]);
  66. const navigatRoute=(route)=>{
  67. navigate(route,{replace:true});
  68. }
  69. const onCallback=(code)=>{
  70. // global.authLockPath=null;
  71. if (code==200){
  72. if (global.authLockPath!=null){
  73. let path=global.authLockPath;
  74. global.authLockPath=null;
  75. navigate(path,{replace:true});
  76. }
  77. else{
  78. if (close)close();
  79. }
  80. }
  81. }
  82. const onSubmitLogin=(data)=>{
  83. data.country=country;
  84. data.callback=onCallback;
  85. dispatch(reqLogin(data));
  86. }
  87. const onSubmitReg=(data)=>{
  88. data.country=country;
  89. data.callback=onCallback;
  90. dispatch(reqRegister(data));
  91. }
  92. const validatePhone=(value)=>{
  93. return validateCountryPhone(country,value);
  94. }
  95. const renderLoading=()=>{
  96. return (<SmallLoading fill={"#fff"}/>)
  97. }
  98. const renderLogo=()=>{
  99. return (
  100. <div className={styles.l_logo}>
  101. <img className={styles.logo_img} src={logourl}/>
  102. </div>
  103. )
  104. }
  105. const renderLoginForm=()=>{
  106. return (
  107. <Spring type="slideUp" >
  108. <div className={styles.l_title}>{i18n.t("login.login_title")}</div>
  109. <form autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
  110. onSubmitLogin(data);
  111. })}>
  112. <Controller control={control}
  113. name="account"
  114. rules={{required: true}}
  115. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  116. let message=error?i18n.t("form_errors.phone_"+country):"";
  117. return (<PhoneInput
  118. className={classNames({'input-control--error': error})}
  119. value={value}
  120. message={message}
  121. onChange={e => onChange(e.target.value)}
  122. onChangeCountry={(country)=>{
  123. setCountry(country);
  124. }}
  125. placeholder={i18n.t('login.phone_ph')}
  126. innerRef={ref}/>)
  127. }}
  128. />
  129. <Controller control={control}
  130. name="password"
  131. rules={{required: true,minLength:6}}
  132. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  133. <PasswordInput
  134. className={classNames({'input-control--error': error})}
  135. value={value}
  136. message={error?i18n.t("form_errors.pass"):''}
  137. onChange={e => onChange(e.target.value)}
  138. placeholder={i18n.t('login.login_pwd')}
  139. innerRef={ref}/>
  140. )}
  141. />
  142. {/*<div className={styles.l_forgot}>*/}
  143. {/* <button className={styles.forgot_btn}>*/}
  144. {/* {i18n.t("login.forgot")}*/}
  145. {/* </button>*/}
  146. {/*</div>*/}
  147. <button className={"button-green"}>
  148. {
  149. loginStatus===REQ_STATUS.LOADING?renderLoading():i18n.t("login.sign_in_btn")
  150. }
  151. </button>
  152. <div className={styles.l_reg_new}>
  153. <div>{i18n.t("login.reg_new_des")}</div>
  154. <div className={styles.reg_btn} onClick={()=>{
  155. // setShowType(TYPE_REGISTER);
  156. if(isMobile())navigatRoute(ROUTE_PATH.SIGN_UP)
  157. else setShowType(TYPE_REGISTER);
  158. }}>
  159. {i18n.t("sign_up")}
  160. </div>
  161. </div>
  162. </form>
  163. </Spring>
  164. )
  165. }
  166. const renderRegisterForm=()=>{
  167. return (
  168. <Spring type="slideUp">
  169. <div className={styles.l_title}>{i18n.t("login.reg_title")}</div>
  170. <form autoComplete="off" className={styles.l_form} onSubmit={handleSubmit((data) => {
  171. onSubmitReg(data);
  172. })}>
  173. <Controller control={control}
  174. name="account"
  175. rules={{required: true,validate:validatePhone}}
  176. render={({field: {ref, onChange, value}, fieldState: {error}}) => {
  177. let message=error?i18n.t("form_errors.phone_"+country):"";
  178. return (<PhoneInput
  179. className={classNames({'input-control--error': error})}
  180. value={value}
  181. message={message}
  182. onChange={e => onChange(e.target.value)}
  183. onChangeCountry={(country)=>{
  184. setCountry(country);
  185. }}
  186. placeholder={i18n.t('login.phone_ph')}
  187. innerRef={ref}/>)
  188. }}
  189. />
  190. <Controller control={control}
  191. name="password"
  192. rules={{required: true,minLength:6}}
  193. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  194. <PasswordInput
  195. className={classNames({'input-control--error': error})}
  196. value={value}
  197. message={error?i18n.t("form_errors.pass"):''}
  198. onChange={e => onChange(e.target.value)}
  199. placeholder={i18n.t('login.login_pwd')}
  200. innerRef={ref}/>
  201. )}
  202. />
  203. <Controller control={control}
  204. name="repassword"
  205. rules={{required: true,minLength:6}}
  206. render={({field: {ref, onChange, value}, fieldState: {error}}) => (
  207. <PasswordInput
  208. className={classNames({'input-control--error': error})}
  209. value={value}
  210. message={error?i18n.t("form_errors.pass"):''}
  211. onChange={e => onChange(e.target.value)}
  212. placeholder={i18n.t('login.re_pwd')}
  213. innerRef={ref}/>
  214. )}
  215. />
  216. <button className={"button-green"}>
  217. {
  218. regStatus===REQ_STATUS.LOADING?renderLoading():i18n.t("login.sign_up_btn")
  219. }
  220. </button>
  221. <div className={styles.l_reg_new}>
  222. <div>{i18n.t("login.login_des")}</div>
  223. <div className={styles.reg_btn} onClick={()=>{
  224. // setShowType(TYPE_LOGIN);
  225. if(isMobile())navigatRoute(ROUTE_PATH.SIGN_IN)
  226. else setShowType(TYPE_LOGIN);
  227. }}>
  228. {i18n.t("login.sign_in_btn")}
  229. </div>
  230. </div>
  231. </form>
  232. </Spring>
  233. )
  234. }
  235. const renderForm=()=>{
  236. let form=(<></>);
  237. if (showType===TYPE_LOGIN){
  238. form=renderLoginForm();
  239. }
  240. else if (showType===TYPE_REGISTER){
  241. form=renderRegisterForm();
  242. }
  243. return (
  244. <div className={styles.l_form_container}>
  245. {form}
  246. </div>
  247. )
  248. }
  249. return (
  250. <div className={styles.container}>
  251. {renderLogo()}
  252. {renderForm()}
  253. </div>
  254. )
  255. }
  256. export default LoginForm;