Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

LoginScreen.jsx 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import React, { useEffect } from "react";
  2. import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
  3. import MaterialIcons from "@expo/vector-icons/MaterialIcons";
  4. import Ionicons from "@expo/vector-icons/Ionicons";
  5. import LoginSVG from "@assets/images/login.svg";
  6. import GoogleSVG from "@assets/images/google.svg";
  7. import FacebookSVG from "@assets/images/facebook.svg";
  8. import TwitterSVG from "@assets/images/twitter.svg";
  9. import CustomButton from "@components/Buttons/CustomButton";
  10. import InputField from "@components/InputField";
  11. import { globalStyles } from "@styles/global";
  12. import Loader from "@components/Loader";
  13. import { Formik } from "formik";
  14. import { loginSchema } from "@schemas/loginSchema";
  15. import { useDispatch, useSelector } from "react-redux";
  16. import { selectLoginError } from "@store/selectors/loginSelectors";
  17. import { clearLoginErrors, fetchUser } from "@store/actions/login/loginActions";
  18. import { selectIsLoadingByActionType } from "@store/selectors/loadingSelectors";
  19. import { LOGIN_USER_SCOPE } from "@store/actions/login/loginActionConstants";
  20. import { fetchAuthProvider } from "@store/actions/authProvider/authProviderActions";
  21. import useAuthHook from "../hooks/useAuthHook";
  22. import { storeData } from "@service/asyncStorage";
  23. import { ACCESS_TOKEN } from "@constants/localStorage";
  24. import Layout from "@components/Layout/Layout";
  25. import { useTheme } from "@styles";
  26. import { useTranslation } from "react-i18next";
  27. const LoginScreen = ({ navigation }) => {
  28. const { colors } = useTheme();
  29. const { t } = useTranslation();
  30. const { response, promptAsync } = useAuthHook();
  31. const dispatch = useDispatch();
  32. const error = useSelector(selectLoginError);
  33. const isLoading = useSelector(selectIsLoadingByActionType(LOGIN_USER_SCOPE));
  34. const storeToken = async (token) => {
  35. await storeData(ACCESS_TOKEN, token);
  36. };
  37. useEffect(() => {
  38. if (response?.type === "success") {
  39. const accessToken = response.authentication.accessToken;
  40. if (accessToken) {
  41. storeToken(accessToken);
  42. dispatch(fetchAuthProvider({ accessToken }));
  43. }
  44. }
  45. }, [response]);
  46. const handleGoogleAuth = () => {
  47. promptAsync({ useProxy: true, showInRecents: true });
  48. };
  49. const handleLogin = (values) => {
  50. const { email, password } = values;
  51. dispatch(clearLoginErrors());
  52. dispatch(
  53. fetchUser({
  54. identifier: email,
  55. password,
  56. })
  57. );
  58. };
  59. return (
  60. <Layout>
  61. <Loader visible={isLoading} />
  62. <View style={{ paddingHorizontal: 25 }}>
  63. <View style={{ alignItems: "center" }}>
  64. <LoginSVG height={300} width={300} />
  65. </View>
  66. <Formik
  67. initialValues={{
  68. email: "",
  69. password: "",
  70. }}
  71. validationSchema={loginSchema}
  72. onSubmit={handleLogin}
  73. validateOnChange={false}
  74. validateOnBlur={false}
  75. >
  76. {({
  77. handleChange,
  78. handleBlur,
  79. handleSubmit,
  80. values,
  81. isValid,
  82. errors,
  83. }) => (
  84. <>
  85. <Text
  86. style={[globalStyles.boldText, { color: colors.textPrimary }]}
  87. >
  88. {t('login.signIn')}
  89. </Text>
  90. <InputField
  91. name="email"
  92. label={t('login.email')}
  93. keyboardType="email-address"
  94. onChangeText={handleChange("email")}
  95. text={values.email}
  96. style={{ color: colors.textPrimary }}
  97. handleBlur={handleBlur("email")}
  98. icon={
  99. <MaterialIcons
  100. name="alternate-email"
  101. size={20}
  102. color="#666"
  103. style={{ marginRight: 5 }}
  104. />
  105. }
  106. />
  107. {errors.email && (
  108. <Text style={styles.errorMessage}>{errors.email}</Text>
  109. )}
  110. <InputField
  111. name="password"
  112. label={t('login.password')}
  113. filedButtonLabel={t('register.forgot')}
  114. fieldButtonFunction={() => {}}
  115. inputType="password"
  116. handleBlur={handleBlur("password")}
  117. text={values.password}
  118. onChangeText={handleChange("password")}
  119. icon={
  120. <Ionicons
  121. name="ios-lock-closed-outline"
  122. size={20}
  123. color="#666"
  124. style={{ marginRight: 5 }}
  125. />
  126. }
  127. />
  128. {errors.password && (
  129. <Text style={styles.errorMessage}>{errors.password}</Text>
  130. )}
  131. {error && <Text style={styles.errorMessage}>{error}</Text>}
  132. <CustomButton label={t('login.login')} onPress={handleSubmit} />
  133. </>
  134. )}
  135. </Formik>
  136. <Text
  137. style={[
  138. globalStyles.regularCenteredText,
  139. { color: colors.textPrimary },
  140. ]}
  141. >
  142. {t('login.orLoginWith')}
  143. </Text>
  144. <View style={styles.providersContainer}>
  145. <TouchableOpacity
  146. onPress={handleGoogleAuth}
  147. style={globalStyles.iconButton}
  148. >
  149. <GoogleSVG height={24} width={24} />
  150. </TouchableOpacity>
  151. <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}>
  152. <FacebookSVG height={24} width={24} />
  153. </TouchableOpacity>
  154. <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}>
  155. <TwitterSVG height={24} width={24} />
  156. </TouchableOpacity>
  157. </View>
  158. <View style={styles.registerContainer}>
  159. <Text
  160. style={[globalStyles.regularText, { color: colors.textPrimary }]}
  161. >
  162. {t('login.needAccount')}{" "}
  163. </Text>
  164. <TouchableOpacity onPress={() => navigation.navigate("Register")}>
  165. <Text style={styles.registerButtonText}>{t('login.signUp')}</Text>
  166. </TouchableOpacity>
  167. </View>
  168. </View>
  169. </Layout>
  170. );
  171. };
  172. const styles = StyleSheet.create({
  173. providerText: {
  174. textAlign: "center",
  175. color: "#666",
  176. marginBottom: 30,
  177. fontFamily: "poppins-regular",
  178. },
  179. providersContainer: {
  180. flexDirection: "row",
  181. justifyContent: "space-between",
  182. marginBottom: 30,
  183. },
  184. registerContainer: {
  185. flexDirection: "row",
  186. justifyContent: "center",
  187. marginBottom: 30,
  188. },
  189. registerButtonText: {
  190. color: "#AD40AF",
  191. fontWeight: "700",
  192. fontFamily: "poppins-semibold",
  193. },
  194. errorMessage: {
  195. marginBottom: 30,
  196. color: "red",
  197. },
  198. });
  199. export default LoginScreen;