Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

RegisterScreen.jsx 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import React, { useEffect } from "react";
  2. import {
  3. ScrollView,
  4. View,
  5. Text,
  6. TouchableOpacity,
  7. StyleSheet,
  8. Alert,
  9. } from "react-native";
  10. import InputField from "@components/InputField";
  11. import MaterialIcons from "@expo/vector-icons/MaterialIcons";
  12. import Ionicons from "@expo/vector-icons/Ionicons";
  13. import RegistrationSVG from "@assets/images/registration.svg";
  14. import GoogleSVG from "@assets/images/google.svg";
  15. import FacebookSVG from "@assets/images/facebook.svg";
  16. import TwitterSVG from "@assets/images/twitter.svg";
  17. import CustomButton from "@components/Buttons/CustomButton";
  18. import { globalStyles } from "@styles/global";
  19. import Loader from "@components/Loader";
  20. import { Formik } from "formik";
  21. import { registerSchema } from "@schemas/registerSchema";
  22. import { useDispatch, useSelector } from "react-redux";
  23. import { selectRegisterError } from "@store/selectors/registerSelectors";
  24. import { selectIsLoadingByActionType } from "@store/selectors/loadingSelectors";
  25. import { REGISTER_USER_SCOPE } from "@store/actions/register/registerActionConstants";
  26. import {
  27. clearRegisterErrors,
  28. registerUser,
  29. } from "@store/actions/register/registerActions";
  30. import useAuthHook from "../hooks/useAuthHook";
  31. import { fetchAuthProvider } from "@store/actions/authProvider/authProviderActions";
  32. import { ACCESS_TOKEN } from "@constants/localStorage";
  33. import { storeData } from "@service/asyncStorage";
  34. import Layout from "@components/Layout/Layout";
  35. import { useTheme } from "@styles";
  36. import { useTranslation } from "react-i18next";
  37. const RegisterScreen = ({ navigation }) => {
  38. const { colors } = useTheme();
  39. const { t } = useTranslation();
  40. const { response, promptAsync } = useAuthHook();
  41. const dispatch = useDispatch();
  42. const error = useSelector(selectRegisterError);
  43. const isLoading = useSelector(
  44. selectIsLoadingByActionType(REGISTER_USER_SCOPE)
  45. );
  46. const storeToken = async (token) => {
  47. await storeData(ACCESS_TOKEN, token);
  48. };
  49. const handleApiResponseSuccess = () => {
  50. Alert.alert(t("common.success"), t("register.successRegisterAccount"), [
  51. {
  52. text: "OK",
  53. onPress: () => navigation.navigate("Login"),
  54. },
  55. ]);
  56. };
  57. const handleSignup = (values) => {
  58. const { username, email, password } = values;
  59. dispatch(clearRegisterErrors());
  60. dispatch(
  61. registerUser({ username, email, password, handleApiResponseSuccess })
  62. );
  63. };
  64. const handleGoogleAuth = () => {
  65. promptAsync({ useProxy: true, showInRecents: true });
  66. };
  67. useEffect(() => {
  68. if (response?.type === "success") {
  69. const accessToken = response.authentication.accessToken;
  70. if (accessToken) {
  71. storeToken(accessToken);
  72. dispatch(fetchAuthProvider({ accessToken }));
  73. }
  74. }
  75. }, [response]);
  76. return (
  77. <Layout>
  78. <Loader visible={isLoading} />
  79. <ScrollView
  80. showsVerticalScrollIndicator={false}
  81. style={{ paddingHorizontal: 25 }}
  82. >
  83. <View style={{ alignItems: "center" }}>
  84. <RegistrationSVG width={300} height={300} />
  85. </View>
  86. <Text style={[globalStyles.boldText, { color: colors.textPrimary }]}>
  87. {t("register.register")}
  88. </Text>
  89. <View style={styles.providersContainer}>
  90. <TouchableOpacity
  91. onPress={handleGoogleAuth}
  92. style={globalStyles.iconButton}
  93. >
  94. <GoogleSVG height={24} width={24} />
  95. </TouchableOpacity>
  96. <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}>
  97. <FacebookSVG height={24} width={24} />
  98. </TouchableOpacity>
  99. <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}>
  100. <TwitterSVG height={24} width={24} />
  101. </TouchableOpacity>
  102. </View>
  103. <Text
  104. style={[
  105. globalStyles.regularCenteredText,
  106. { color: colors.textPrimary },
  107. ]}
  108. >
  109. {t("register.orSignUpWithMail")}
  110. </Text>
  111. <Formik
  112. initialValues={{
  113. username: "",
  114. email: "",
  115. password: "",
  116. confirmPassword: "",
  117. }}
  118. validationSchema={registerSchema}
  119. onSubmit={handleSignup}
  120. validateOnChange={false}
  121. validateOnBlur={false}
  122. >
  123. {({
  124. handleChange,
  125. handleBlur,
  126. handleSubmit,
  127. values,
  128. isValid,
  129. errors,
  130. }) => (
  131. <>
  132. <InputField
  133. name={"username"}
  134. text={values.username}
  135. onChangeText={handleChange("username")}
  136. label={t("register.username")}
  137. handleBlur={handleBlur("username")}
  138. icon={
  139. <Ionicons
  140. name="person-outline"
  141. size={20}
  142. color="#666"
  143. style={{ marginRight: 5 }}
  144. />
  145. }
  146. />
  147. {errors.username && (
  148. <Text style={styles.errorMessage}>{errors.username}</Text>
  149. )}
  150. <InputField
  151. name={"email"}
  152. text={values.email}
  153. onChangeText={handleChange("email")}
  154. label={t("register.email")}
  155. handleBlur={handleBlur("email")}
  156. icon={
  157. <MaterialIcons
  158. name="alternate-email"
  159. size={20}
  160. color="#666"
  161. style={{ marginRight: 5 }}
  162. />
  163. }
  164. keyboardType="email-address"
  165. />
  166. {errors.email && (
  167. <Text style={styles.errorMessage}>{errors.email}</Text>
  168. )}
  169. <InputField
  170. name={"password"}
  171. text={values.password}
  172. onChangeText={handleChange("password")}
  173. label={t("register.password")}
  174. handleBlur={handleBlur("password")}
  175. icon={
  176. <Ionicons
  177. name="ios-lock-closed-outline"
  178. size={20}
  179. color="#666"
  180. style={{ marginRight: 5 }}
  181. />
  182. }
  183. inputType="password"
  184. />
  185. {errors.password && (
  186. <Text style={styles.errorMessage}>{errors.password}</Text>
  187. )}
  188. <InputField
  189. name={"confirmPassword"}
  190. text={values.confirmPassword}
  191. onChangeText={handleChange("confirmPassword")}
  192. label={t("register.confirmPassword")}
  193. handleBlur={handleBlur("confirmPassword")}
  194. icon={
  195. <Ionicons
  196. name="ios-lock-closed-outline"
  197. size={20}
  198. color="#666"
  199. style={{ marginRight: 5 }}
  200. />
  201. }
  202. inputType="password"
  203. />
  204. {errors.confirmPassword && (
  205. <Text style={styles.errorMessage}>
  206. {errors.confirmPassword}
  207. </Text>
  208. )}
  209. {error && <Text style={styles.errorMessage}>{error}</Text>}
  210. <CustomButton
  211. label={t("register.signUp")}
  212. onPress={handleSubmit}
  213. />
  214. </>
  215. )}
  216. </Formik>
  217. <View style={styles.alreadyRegistered}>
  218. <Text
  219. style={[globalStyles.regularText, { color: colors.textPrimary }]}
  220. >
  221. {t("register.alreadyRegistered")}{" "}
  222. </Text>
  223. <TouchableOpacity onPress={() => navigation.goBack()}>
  224. <Text style={globalStyles.primaryBold}>{t("register.signIn")}</Text>
  225. </TouchableOpacity>
  226. </View>
  227. </ScrollView>
  228. </Layout>
  229. );
  230. };
  231. const styles = StyleSheet.create({
  232. providersContainer: {
  233. flexDirection: "row",
  234. justifyContent: "space-between",
  235. marginBottom: 30,
  236. },
  237. dateOfBirthContainer: {
  238. flexDirection: "row",
  239. borderBottomColor: "#ccc",
  240. borderBottomWidth: 1,
  241. paddingBottom: 8,
  242. marginBottom: 30,
  243. },
  244. dateOfBirthLabel: {
  245. color: "#666",
  246. marginLeft: 5,
  247. marginTop: 5,
  248. },
  249. alreadyRegistered: {
  250. flexDirection: "row",
  251. justifyContent: "center",
  252. marginBottom: 30,
  253. },
  254. errorMessage: {
  255. marginBottom: 30,
  256. color: "red",
  257. },
  258. });
  259. export default RegisterScreen;