diff --git a/package.json b/package.json
index 6805923..54b9764 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
},
"dependencies": {
"axios": "0.18.0",
+ "formik": "^1.5.8",
"prop-types": "15.7.2",
"react": "16.8.3",
"react-native": "0.59.8",
@@ -22,12 +23,12 @@
"react-native-size-matters": "0.2.1",
"react-navigation": "3.11.0",
"react-navigation-redux-helpers": "3.0.2",
- "react-redux": "5.0.7",
- "redux": "4.0.0",
- "redux-act": "1.7.4",
- "redux-form": "7.4.2",
- "redux-persist": "5.10.0",
- "redux-saga": "1.0.2"
+ "react-redux": "7.1.1",
+ "redux": "4.0.4",
+ "redux-act": "1.7.7",
+ "redux-persist": "6.0.0",
+ "redux-saga": "1.1.1",
+ "yup": "^0.27.0"
},
"devDependencies": {
"@babel/core": "^7.4.4",
diff --git a/src/App.js b/src/App.js
index ef629d0..fc75e96 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
-import { PersistGate } from 'redux-persist/lib/integration/react';
+import { PersistGate } from 'redux-persist/integration/react';
import { Provider } from 'react-redux';
-
+import ApiProvider from './utils/apiProvider';
import store, { persistor } from './redux';
import RootNavigator from './navigation';
@@ -14,7 +14,9 @@ export default class App extends Component {
persistor={persistor}
loading={null}
>
-
+
+
+
);
diff --git a/src/components/AuthFormInput/index.js b/src/components/AuthFormInput/index.js
index 5ab6ad1..695dcdd 100644
--- a/src/components/AuthFormInput/index.js
+++ b/src/components/AuthFormInput/index.js
@@ -9,57 +9,64 @@ import styles from './styles';
const FormInput = (props) => {
const {
- input,
containerStyle,
inputContainerStyle,
- meta: { error, touched },
inlineImage,
+ name,
+ handleChange,
+ handleBlur,
+ errors,
+ touched,
+ value,
...inputProps
} = props;
+ const hasError = touched[name] && errors[name];
+
const renderError = () => {
- if (touched && error) {
- return {error};
+ if (hasError) {
+ return {errors[name]};
}
return null;
};
+
return (
- {
- renderError()
- }
+ {renderError()}
);
};
FormInput.propTypes = {
+ ...DefaultInput.propTypes,
input: PropTypes.object,
containerStyle: PropTypes.any,
- meta: PropTypes.shape({
- touched: PropTypes.bool,
- error: PropTypes.any,
- }),
inlineImage: PropTypes.any,
inputContainerStyle: PropTypes.any,
+ name: PropTypes.string.isRequired,
+ handleChange: PropTypes.func,
+ handleBlur: PropTypes.func,
+ errors: PropTypes.object,
+ touched: PropTypes.object,
+ value: DefaultInput.propTypes.value,
};
export default FormInput;
diff --git a/src/components/DefaultInput/index.js b/src/components/DefaultInput/index.js
index 24deb77..7272de6 100644
--- a/src/components/DefaultInput/index.js
+++ b/src/components/DefaultInput/index.js
@@ -18,7 +18,8 @@ const DefaultInput = ({ inputRef, style, ...rest }) => (
);
DefaultInput.propTypes = {
- inputRef: PropTypes.func,
+ ...TextInput.propTypes,
+ inputRef: PropTypes.any,
style: PropTypes.any,
};
diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js
index 71b0fb0..701543f 100644
--- a/src/constants/endpoints.js
+++ b/src/constants/endpoints.js
@@ -4,4 +4,4 @@
export const SIGN_IN_ENDPOINT = '';
export const SIGN_UP_ENDPOINT = '';
export const TEST_AUTH_ENDPOINT = '';
-export const REFRESH_ACCESS_TOKEN_ENPOINT = '';
+export const REFRESH_ACCESS_TOKEN_ENDPOINT = '';
diff --git a/src/redux/index.js b/src/redux/index.js
index 84e9ba9..d8899ba 100644
--- a/src/redux/index.js
+++ b/src/redux/index.js
@@ -1,8 +1,8 @@
+import { AsyncStorage } from 'react-native';
import { createStore, applyMiddleware, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { persistStore, persistReducer } from 'redux-persist';
-import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import { navigationMiddleware } from '../navigation';
@@ -17,7 +17,7 @@ const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const persistConfig = {
key: 'root',
- storage,
+ storage: AsyncStorage,
stateReconciler: autoMergeLevel2,
blacklist: ['nav', 'form'],
whitelist: ['auth'],
diff --git a/src/redux/reducers/index.js b/src/redux/reducers/index.js
index 7b654da..f693963 100644
--- a/src/redux/reducers/index.js
+++ b/src/redux/reducers/index.js
@@ -1,10 +1,8 @@
import { combineReducers } from 'redux';
-import { reducer as form } from 'redux-form';
import nav from '../../navigation/reducer';
import auth from './auth';
const reducer = combineReducers({
- form,
nav,
auth,
});
diff --git a/src/redux/sagas/api.js b/src/redux/sagas/api.js
index 921af34..b0bec84 100644
--- a/src/redux/sagas/api.js
+++ b/src/redux/sagas/api.js
@@ -1,15 +1,11 @@
-import { put as sagaPut, call, select } from 'redux-saga/effects';
+import { call } from 'redux-saga/effects';
import api, { setAuthHeader, resetAuthHeader } from '../../utils/axios';
-import { REFRESH_ACCESS_TOKEN_ENPOINT } from '../../constants/endpoints';
-import * as actions from '../actions';
-
-const getRefreshToken = state => state.auth.refreshToken;
export function* get(endpoint, options) {
try {
return yield call(api.get, endpoint, options || {});
} catch (error) {
- return yield call(checkForTokenError, error, retryRequest, 'accessToken');
+ throw error;
}
}
@@ -17,7 +13,7 @@ export function* post(endpoint, data, options) {
try {
return yield call(api.post, endpoint, data, options || {});
} catch (error) {
- return yield call(checkForTokenError, error, retryRequest, 'accessToken');
+ throw error;
}
}
@@ -25,57 +21,8 @@ export function* put(endpoint, data, options) {
try {
return yield call(api.put, endpoint, data, options || {});
} catch (error) {
- return yield call(checkForTokenError, error, retryRequest, 'accessToken');
- }
-}
-
-function* retryRequest(error) {
- const newToken = yield call(refreshAccessToken);
- const newError = { ...error };
- newError.config.headers.Authorization = `Bearer ${newToken}`;
- return yield call(api.request, newError.config);
-}
-
-function* checkForTokenError(error, onAccessTokeErrorCallback, paramToCheck) {
- if (error.response) {
- const accessTokenError = error.response.data.find(e => e.param === paramToCheck);
- if (accessTokenError) {
- return yield call(onAccessTokeErrorCallback, error);
- }
-
throw error;
- } else if (error.request) {
- throw createSimpleErrorObject('Server does not respond');
}
-
- throw createSimpleErrorObject('Please, check your internet connection');
-}
-
-function* refreshAccessToken() {
- try {
- const refreshToken = yield select(getRefreshToken);
- const response = yield call(api.post, REFRESH_ACCESS_TOKEN_ENPOINT, { refreshToken });
- setAuthHeader(response.data.accessToken);
- yield sagaPut(actions.accessTokenUpdatedAction(response.data));
- return response.data.accessToken;
- } catch (error) {
- return yield call(checkForTokenError, error, onRefreshTokenError, 'refreshToken');
- }
-}
-
-function* onRefreshTokenError(error) {
- yield sagaPut(actions.signOutAction());
- throw error;
-}
-
-function createSimpleErrorObject(error) {
- return {
- response: {
- data: {
- _error: error,
- },
- },
- };
}
export { resetAuthHeader, setAuthHeader };
diff --git a/src/screens/Root.js b/src/screens/Root.js
index a424906..10d6234 100644
--- a/src/screens/Root.js
+++ b/src/screens/Root.js
@@ -1,28 +1,25 @@
-import { Component } from 'react';
+import { useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { testAuthAction } from '../redux/actions';
-@connect(null, ({
- testAuth: testAuthAction,
-}))
-class Root extends Component {
- static navigationOptions = {
- header: null,
- }
+const Root = ({ testAuth }) => {
+ useEffect(() => {
+ testAuth();
+ }, []);
- static propTypes = {
- testAuth: PropTypes.func,
- };
+ return null;
+};
- componentDidMount() {
- this.props.testAuth();
- }
+Root.navigationOptions = {
+ header: null,
+};
- render() {
- return null;
- }
-}
+Root.propTypes = {
+ testAuth: PropTypes.func,
+};
-export default Root;
+export default connect(null, ({
+ testAuth: testAuthAction,
+}))(Root);
diff --git a/src/screens/SignInScreen/FormProvider.js b/src/screens/SignInScreen/FormProvider.js
new file mode 100644
index 0000000..68f227a
--- /dev/null
+++ b/src/screens/SignInScreen/FormProvider.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Formik } from 'formik';
+import { object, string } from 'yup';
+
+const SignInSchema = object().shape({
+ email: string()
+ .email('Invalid email')
+ .required('Required'),
+ password: string().required('Required'),
+});
+
+const INITIAL_SIGN_IN_VALUES = {
+ email: '',
+ password: '',
+};
+
+const FormProvider = ({ children, onSubmit }) => {
+ /* :: (object, object) -> Promise */
+ const handleSignIn = async (formData, actions) => {
+ try {
+ onSubmit(formData);
+ } catch (error) {
+ actions.resetForm();
+ actions.setFieldValue('email', formData.email);
+ }
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+FormProvider.propTypes = {
+ onSubmit: PropTypes.func.isRequired,
+ children: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,
+};
+
+export default FormProvider;
diff --git a/src/screens/SignInScreen/SignIn.js b/src/screens/SignInScreen/SignIn.js
index 5073523..dd51af3 100644
--- a/src/screens/SignInScreen/SignIn.js
+++ b/src/screens/SignInScreen/SignIn.js
@@ -1,29 +1,14 @@
-import React, { Component } from 'react';
-import { View, Keyboard } from 'react-native';
-import { reduxForm, Field } from 'redux-form';
+import React, { useRef } from 'react';
+import { View } from 'react-native';
import PropTypes from 'prop-types';
-
import KeyboardAvoidingWrapper from '../../components/KeyboardAvoidingWrapper';
import FormInput from '../../components/AuthFormInput';
import DefaultButton from '../../components/DefaultButton';
import DefaultText from '../../components/DefaultText';
-
-import validate from '../../validators/auth-validator';
import styles from './styles';
-@reduxForm({ form: 'signin', validate })
-export default class SignIn extends Component {
- static propTypes = {
- onGoToSignUpPress: PropTypes.func,
- handleSubmit: PropTypes.func,
- };
-
- handleSubmit = (data) => {
- Keyboard.dismiss();
- this.props.handleSubmit(data);
- }
-
- renderTitle = () => (
+const SignIn = ({ handleSubmit, values, ...props }) => {
+ const renderTitle = () => (
);
- render() {
- const {
- onGoToSignUpPress,
- } = this.props;
+ const passwordRef = useRef(null);
+
+ return (
+
+
+ { renderTitle() }
+ passwordRef.current.focus()}
+ keyboardType='email-address'
+ maxLength={40}
+ value={values.email}
+ {...props}
+ />
+
+
+
+
+ );
+};
+
+SignIn.propTypes = {
+ handleSubmit: PropTypes.func,
+ values: PropTypes.object,
+};
- return (
-
-
- { this.renderTitle() }
- this.passwordRef.focus()}
- keyboardType='email-address'
- maxLength={40}
- />
- { this.passwordRef = ref; }}
- secureTextEntry
- onSubmitEditing={this.handleSubmit}
- maxLength={20}
- />
-
-
-
- );
- }
-}
+export default SignIn;
diff --git a/src/screens/SignInScreen/index.js b/src/screens/SignInScreen/index.js
index 696aae5..6828069 100644
--- a/src/screens/SignInScreen/index.js
+++ b/src/screens/SignInScreen/index.js
@@ -1,31 +1,35 @@
-import React, { Component } from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
+import { Keyboard } from 'react-native';
+import FormProvider from './FormProvider';
import SignIn from './SignIn';
import { signInAction } from '../../redux/actions';
-@connect(null, ({
- signIn: signInAction,
-}))
-class LoginScreen extends Component {
- static propTypes = {
- navigation: PropTypes.object,
- signIn: PropTypes.func,
+const LoginScreen = ({ signIn, navigation }) => {
+ const handleSubmit = (data) => {
+ Keyboard.dismiss();
+ signIn(data);
};
- render() {
- const {
- navigation,
- signIn,
- } = this.props;
- return (
- navigation.replace('SignUpScreen')}
- />
- );
- }
-}
+ return (
+
+ {props => (
+ navigation.replace('SignUpScreen')}
+ {...props}
+ />
+ )}
+
+ );
+};
+
+LoginScreen.propTypes = {
+ navigation: PropTypes.object,
+ signIn: PropTypes.func,
+};
-export default LoginScreen;
+export default connect(null, ({
+ signIn: signInAction,
+}))(LoginScreen);
diff --git a/src/screens/SignUpScreen/FormProvider.js b/src/screens/SignUpScreen/FormProvider.js
new file mode 100644
index 0000000..19d7720
--- /dev/null
+++ b/src/screens/SignUpScreen/FormProvider.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Formik } from 'formik';
+import { object, string } from 'yup';
+
+const SignUpSchema = object().shape({
+ firstName: string().required('Required'),
+ lastName: string().required('Required'),
+ email: string()
+ .email('Invalid email')
+ .required('Required'),
+ password: string().required('Required'),
+});
+
+const INITIAL_SIGN_UP_VALUES = {
+ firstName: '',
+ lastName: '',
+ email: '',
+ password: '',
+};
+
+const FormProvider = ({ children, onSubmit }) => {
+ /* :: (object, object) -> Promise */
+ const handleSignIn = async (formData, actions) => {
+ try {
+ onSubmit(formData);
+ } catch (error) {
+ actions.resetForm();
+ }
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+FormProvider.propTypes = {
+ onSubmit: PropTypes.func.isRequired,
+ children: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,
+};
+
+export default FormProvider;
diff --git a/src/screens/SignUpScreen/SignUp.js b/src/screens/SignUpScreen/SignUp.js
index d738f7e..8e05a75 100644
--- a/src/screens/SignUpScreen/SignUp.js
+++ b/src/screens/SignUpScreen/SignUp.js
@@ -1,83 +1,79 @@
-import React, { Component } from 'react';
-import { View, Keyboard } from 'react-native';
-import { reduxForm, Field } from 'redux-form';
+import React, { useRef } from 'react';
+import { View } from 'react-native';
import PropTypes from 'prop-types';
import KeyboardAvoidingWrapper from '../../components/KeyboardAvoidingWrapper';
import FormInput from '../../components/AuthFormInput';
import DefaultButton from '../../components/DefaultButton';
-
-import validate from '../../validators/auth-validator';
import styles from './styles';
-@reduxForm({ form: 'signup', validate })
-class SignUp extends Component {
- static propTypes = {
- onGoToLoginPress: PropTypes.func,
- handleSubmit: PropTypes.func,
- };
-
- handleSubmit = (data) => {
- Keyboard.dismiss();
- this.props.handleSubmit(data);
- }
+const SignUp = ({ handleSubmit, values, ...props }) => {
+ const passwordRef = useRef(null);
+ const lastNameRef = useRef(null);
+ const emailRef = useRef(null);
- render() {
- const { onGoToLoginPress } = this.props;
+ return (
+
+
+
+ lastNameRef.current.focus()}
+ maxLength={20}
+ value={values.firstName}
+ {...props}
+ />
+ emailRef.current.focus()}
+ inputRef={lastNameRef}
+ maxLength={20}
+ value={values.lastName}
+ {...props}
+ />
+ passwordRef.current.focus()}
+ inputRef={emailRef}
+ keyboardType='email-address'
+ maxLength={40}
+ value={values.email}
+ {...props}
+ />
+
+
+
+
+
+ );
+};
- return (
-
-
-
- this.lastNameRef.focus()}
- maxLength={20}
- />
- this.emailRef.focus()}
- inputRef={(ref) => { this.lastNameRef = ref; }}
- maxLength={20}
- />
- this.passwordRef.focus()}
- inputRef={(ref) => { this.emailRef = ref; }}
- keyboardType='email-address'
- maxLength={40}
- />
- { this.passwordRef = ref; }}
- secureTextEntry
- onSubmitEditing={this.handleSubmit}
- maxLength={20}
- />
-
-
-
-
- );
- }
-}
+SignUp.propTypes = {
+ handleSubmit: PropTypes.func,
+ values: PropTypes.object,
+};
export default SignUp;
diff --git a/src/screens/SignUpScreen/index.js b/src/screens/SignUpScreen/index.js
index 19c9283..d9f3d56 100644
--- a/src/screens/SignUpScreen/index.js
+++ b/src/screens/SignUpScreen/index.js
@@ -1,32 +1,35 @@
-import React, { Component } from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
+import { Keyboard } from 'react-native';
+import FormProvider from './FormProvider';
import SignUp from './SignUp';
import { signUpAction } from '../../redux/actions';
-@connect(null, ({
- signUp: signUpAction,
-}))
-class SignUpScreen extends Component {
- static propTypes = {
- navigation: PropTypes.object,
- signUp: PropTypes.func,
+const SignUpScreen = ({ navigation, signUp }) => {
+ const handleSubmit = (data) => {
+ Keyboard.dismiss();
+ signUp(data);
};
- render() {
- const {
- navigation,
- signUp,
- } = this.props;
+ return (
+
+ {props => (
+ navigation.replace('LoginScreen')}
+ {...props}
+ />
+ )}
+
+ );
+};
- return (
- navigation.replace('LoginScreen')}
- onSubmit={signUp}
- />
- );
- }
-}
+SignUpScreen.propTypes = {
+ navigation: PropTypes.object,
+ signUp: PropTypes.func,
+};
-export default SignUpScreen;
+export default connect(null, ({
+ signUp: signUpAction,
+}))(SignUpScreen);
diff --git a/src/utils/apiProvider.js b/src/utils/apiProvider.js
new file mode 100644
index 0000000..205a6b5
--- /dev/null
+++ b/src/utils/apiProvider.js
@@ -0,0 +1,51 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import axios from './axios';
+
+export const ApiContext = React.createContext();
+
+const ApiProvider = ({ store, children }) => {
+ axios.setStore(store);
+
+ const value = {
+ /* GET */
+ async get(path, config = {}) {
+ const response = await axios.get(path, config);
+
+ return response;
+ },
+
+ /* POST */
+ async post(path, data, config = {}) {
+ const response = await axios.post(
+ path,
+ data,
+ config,
+ );
+
+ return response;
+ },
+
+ /* PUT */
+ async put(path, data, config = {}) {
+ const response = await axios.put(
+ path,
+ data,
+ config,
+ );
+
+ return response;
+ },
+ };
+
+ return (
+ {children}
+ );
+};
+
+ApiProvider.propTypes = {
+ children: PropTypes.node,
+ store: PropTypes.any,
+};
+
+export default ApiProvider;
diff --git a/src/utils/axios.js b/src/utils/axios.js
index 92025ea..c03882b 100644
--- a/src/utils/axios.js
+++ b/src/utils/axios.js
@@ -1,4 +1,6 @@
import axios from 'axios';
+import { REFRESH_ACCESS_TOKEN_ENDPOINT } from '../constants/endpoints';
+import { accessTokenUpdatedAction, signOutAction } from '../redux/actions';
const API_URL = 'YOUR_SERVER_ADDRESS';
@@ -7,6 +9,69 @@ const axiosInstance = axios.create({
timeout: 20000,
});
+let store = null;
+
+axiosInstance.setStore = (providedStore) => {
+ store = providedStore;
+};
+
+function checkForTokenError(error, onErrorCallback, paramToCheck) {
+ if (error.response) {
+ const errorIsFound = error.response.data.find(e => e.param === paramToCheck);
+
+ if (errorIsFound) {
+ return onErrorCallback(error);
+ }
+
+ throw error;
+ } else if (error.request) {
+ throw createSimpleErrorObject('Server does not respond');
+ }
+
+ throw createSimpleErrorObject('Please, check your internet connection');
+}
+
+export const refreshTokenSelector = state => state.auth.refreshToken;
+
+function onRefreshTokenError() {
+ const { dispatch } = store;
+
+
+ dispatch(signOutAction());
+}
+
+async function refreshAccessToken() {
+ try {
+ const state = store.getState();
+ const refreshToken = refreshTokenSelector(state);
+ const response = await axiosInstance.post(REFRESH_ACCESS_TOKEN_ENDPOINT, { refreshToken });
+ const { dispatch } = store;
+
+ dispatch(accessTokenUpdatedAction(response.data));
+ setAuthHeader(response.data.accessToken);
+ return response.data.accessToken;
+ } catch (error) {
+ return checkForTokenError(error, onRefreshTokenError, 'refreshToken');
+ }
+}
+
+axiosInstance.interceptors.response.use(null, async (error) => {
+ if (error.response && error.response.data.find(e => e.param === 'accessToken')) {
+ try {
+ const newToken = await refreshAccessToken();
+
+ error.config.headers.Authorization = `Bearer ${newToken}`;
+
+ return axiosInstance.request(error.config);
+ } catch (err) {
+ onRefreshTokenError();
+ throw err;
+ }
+ }
+
+ throw error;
+});
+
export const setAuthHeader = (accessToken) => {
axiosInstance.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
};
@@ -15,4 +80,22 @@ export const resetAuthHeader = () => {
delete axiosInstance.defaults.headers.common.Authorization;
};
+export const getFormErrors = (error) => {
+ const formErrors = {};
+
+ error.response.data.forEach(({ param, message }) => { formErrors[param] = message; });
+
+ return formErrors;
+};
+
+export const createSimpleErrorObject = (error) => {
+ return {
+ response: {
+ data: {
+ _error: error,
+ },
+ },
+ };
+};
+
export default axiosInstance;
diff --git a/src/utils/useApi.js b/src/utils/useApi.js
new file mode 100644
index 0000000..778320f
--- /dev/null
+++ b/src/utils/useApi.js
@@ -0,0 +1,8 @@
+import { useContext } from 'react';
+import { ApiContext } from './apiProvider';
+
+export default () => {
+ const api = useContext(ApiContext);
+
+ return api;
+};
diff --git a/src/utils/withApi.js b/src/utils/withApi.js
new file mode 100644
index 0000000..2ee6971
--- /dev/null
+++ b/src/utils/withApi.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { ApiContext } from './apiProvider';
+
+
+export const withApi = (Component) => {
+ const WithApi = props => (
+
+ {api => }
+
+ );
+
+ return WithApi;
+};
+
+export const ApiType = PropTypes.shape({
+ get: PropTypes.func.isRequired,
+ post: PropTypes.func.isRequired,
+ put: PropTypes.func.isRequired,
+});
diff --git a/src/validators/auth-validator.js b/src/validators/auth-validator.js
deleted file mode 100644
index ad39b2e..0000000
--- a/src/validators/auth-validator.js
+++ /dev/null
@@ -1,32 +0,0 @@
-export default function validate(values) {
- const errors = {};
- const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
- const passwordRegex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/;
- const nameRegex = /^(?=.{1,50}$)[a-z]+(?:['_.\s][a-z]+)*$/i;
-
- if (!values.email) {
- errors.email = 'Email field is required';
- } else if (!emailRegex.test(values.email)) {
- errors.email = 'Please, enter a valid email address';
- }
-
- if (!values.password) {
- errors.password = 'Password field is required';
- } else if (!passwordRegex.test(values.password)) {
- errors.password = 'Password must contain at least 8 characters, including an upper-case letter and a number';
- }
-
- if (!values.firstName) {
- errors.firstName = 'First name field is required';
- } else if (!nameRegex.test(values.firstName)) {
- errors.firstName = 'Please, enter a valid first name';
- }
-
- if (!values.lastName) {
- errors.lastName = 'First name field is required';
- } else if (!nameRegex.test(values.lastName)) {
- errors.lastName = 'Please, enter a valid first name';
- }
-
- return errors;
-}
diff --git a/yarn.lock b/yarn.lock
index c1ef3e0..89e582c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -680,6 +680,13 @@
dependencies:
regenerator-runtime "^0.13.2"
+"@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0":
+ version "7.6.2"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.2.tgz#c3d6e41b304ef10dcf13777a33e7694ec4a9a6dd"
+ integrity sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==
+ dependencies:
+ regenerator-runtime "^0.13.2"
+
"@babel/template@7.0.0-beta.44":
version "7.0.0-beta.44"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f"
@@ -961,49 +968,49 @@
react-native-safe-area-view "^0.14.1"
react-native-screens "^1.0.0 || ^1.0.0-alpha"
-"@redux-saga/core@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.0.2.tgz#4336a5bb4253e5ca69681c25a863fbbc03ea6d88"
- integrity sha512-AsJYcpuYfM1cmxJvfhXs9HAFSZVEG17TMsLPlXH7+Hq5a5ZP4GqcbtijEmS2AC7NR5lLJHy8csxpqz22PeW5dw==
- dependencies:
- "@babel/runtime" "^7.0.0"
- "@redux-saga/deferred" "^1.0.1"
- "@redux-saga/delay-p" "^1.0.1"
- "@redux-saga/is" "^1.0.2"
- "@redux-saga/symbols" "^1.0.1"
- "@redux-saga/types" "^1.0.2"
- redux ">=0.10 <5"
- typescript-tuple "^2.1.0"
-
-"@redux-saga/deferred@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@redux-saga/deferred/-/deferred-1.0.1.tgz#c895445e486bded90acf0b873b4e978fbfe458c2"
- integrity sha512-+gW5xQ93QXOOmRLAmX8x2Hx1HpbTG6CM6+HcdTSbJovh4uMWaGyeDECnqXSt8QqA/ja3s2nqYXLqXFKepIQ1hw==
+"@redux-saga/core@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.1.1.tgz#72432130630cca08260086ffc564c2aa5488a0a2"
+ integrity sha512-WKXfj2cYkP0eh74dE1ueMjVDoGJIkppXiMFgx0buVRkXENeZmRxIjM4lh9LEWWFqay7I/Qkw7+cMossa7xXoAQ==
+ dependencies:
+ "@babel/runtime" "^7.6.0"
+ "@redux-saga/deferred" "^1.1.0"
+ "@redux-saga/delay-p" "^1.1.0"
+ "@redux-saga/is" "^1.1.0"
+ "@redux-saga/symbols" "^1.1.0"
+ "@redux-saga/types" "^1.1.0"
+ redux "^4.0.4"
+ typescript-tuple "^2.2.1"
+
+"@redux-saga/deferred@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@redux-saga/deferred/-/deferred-1.1.0.tgz#aff018f64a936c288c18bd64ddf9ccfa143db6b4"
+ integrity sha512-wOCJCby3hx14bvrEeFLJ1JJTjJdXDJyC+B3JQ6eiqgzNghylbf969lIYmS2Arf2QuALfUtRBNPXBIMDKG9km4g==
-"@redux-saga/delay-p@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@redux-saga/delay-p/-/delay-p-1.0.1.tgz#d69fc6103c7509ae80faa144ea17bbc69e51e029"
- integrity sha512-0SnNDyDLUyB4NThtptAwiprNOnbCNhoed/Rp5JwS7SB+a/AdWynVgg/E6BmjsggLFNr07KW0bzn05tsPRBuU7Q==
+"@redux-saga/delay-p@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@redux-saga/delay-p/-/delay-p-1.1.0.tgz#4024f979d0f78763d2e90233be8c922781ae4400"
+ integrity sha512-BcRwXs20kKjgiYEwZARkpVoRIe/hHftW3iwPhdeW4/jPyR9gLv/vG8VsJMF5NDEch+/w/mJtdgSubq+wtOS47g==
dependencies:
- "@redux-saga/symbols" "^1.0.1"
+ "@redux-saga/symbols" "^1.1.0"
-"@redux-saga/is@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@redux-saga/is/-/is-1.0.2.tgz#7f4be014c97061898d7efb11d6c9de31e943ed38"
- integrity sha512-WnaUOwYvPK2waWjzebT4uhL8zY76XNkzzpJ2EQJe8bN1tByvAjvT7MuJZTSshOhdHL5PsRO0MsH224XIXBJidQ==
+"@redux-saga/is@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@redux-saga/is/-/is-1.1.0.tgz#d74358364ebde160bf1b8bd94903ff7684b12d41"
+ integrity sha512-0uFXWGSvDCfNBdROHwEVixNhFbI3S+UGBQfcPXQiYL+CjIjyR3DTg2Z+NFH9xzP+H4Oh/yGtTHDhC0GxYp7HQQ==
dependencies:
- "@redux-saga/symbols" "^1.0.1"
- "@redux-saga/types" "^1.0.2"
+ "@redux-saga/symbols" "^1.1.0"
+ "@redux-saga/types" "^1.1.0"
-"@redux-saga/symbols@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@redux-saga/symbols/-/symbols-1.0.1.tgz#46512ae1275f88df061c42168d0f600ddb170c1e"
- integrity sha512-akKkzcVnb1RzJaZV2LQFbi51abvdICMuAKwwLoCjjxLbLAGIw9EJxk5ucNnWSSCEsoEQMeol5tkAcK+Xzuv1Bg==
+"@redux-saga/symbols@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@redux-saga/symbols/-/symbols-1.1.0.tgz#676b277cb5deb48ce723b2b394cbae97f82e8319"
+ integrity sha512-Fzw1wV3j4hbac3MYmgNE18Z53URmQZeilTHZLF7Lm4SQ1jG4fcU47v2kElsEbQXUSaFqj+uJqdRzmDGNb6pRwQ==
-"@redux-saga/types@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.0.2.tgz#1d94f02800b094753f9271c206a26c2a06ca14ee"
- integrity sha512-8/qcMh15507AnXJ3lBeuhsdFwnWQqnp68EpUuHlYPixJ5vjVmls7/Jq48cnUlrZI8Jd9U1jkhfCl0gaT5KMgVw==
+"@redux-saga/types@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.1.0.tgz#0e81ce56b4883b4b2a3001ebe1ab298b84237204"
+ integrity sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg==
"@types/babel__core@^7.1.0":
version "7.1.2"
@@ -1951,6 +1958,14 @@ create-react-class@^15.6.3:
loose-envify "^1.3.1"
object-assign "^4.1.1"
+create-react-context@^0.2.2:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3"
+ integrity sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==
+ dependencies:
+ fbjs "^0.8.0"
+ gud "^1.0.0"
+
cross-spawn@^5.0.1, cross-spawn@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@@ -2040,6 +2055,11 @@ deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+deepmerge@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
+ integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
+
define-properties@^1.1.2, define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -2209,11 +2229,6 @@ es-to-primitive@^1.2.0:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
-es6-error@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
- integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
-
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -2625,7 +2640,7 @@ fbjs-scripts@^1.0.0:
semver "^5.1.0"
through2 "^2.0.0"
-fbjs@^0.8.9:
+fbjs@^0.8.0, fbjs@^0.8.9:
version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
@@ -2739,6 +2754,11 @@ flat-cache@^1.2.1:
rimraf "~2.6.2"
write "^0.2.1"
+fn-name@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7"
+ integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=
+
follow-redirects@^1.3.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76"
@@ -2772,6 +2792,21 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"
+formik@^1.5.8:
+ version "1.5.8"
+ resolved "https://registry.yarnpkg.com/formik/-/formik-1.5.8.tgz#eee8cd345effe46839bc748c7f920486f12f14b0"
+ integrity sha512-fNvPe+ddbh+7xiByT25vuso2p2hseG/Yvuj211fV1DbCjljUEG9OpgRpcb7g7O3kxHX/q31cbZDzMxJXPWSNwA==
+ dependencies:
+ create-react-context "^0.2.2"
+ deepmerge "^2.1.1"
+ hoist-non-react-statics "^3.3.0"
+ lodash "^4.17.14"
+ lodash-es "^4.17.14"
+ prop-types "^15.6.1"
+ react-fast-compare "^2.0.1"
+ tiny-warning "^1.0.2"
+ tslib "^1.9.3"
+
fragment-cache@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
@@ -2936,6 +2971,11 @@ growly@^1.3.0:
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
+gud@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0"
+ integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==
+
handlebars@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67"
@@ -3020,7 +3060,7 @@ has@^1.0.1, has@^1.0.3:
dependencies:
function-bind "^1.1.1"
-hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0, hoist-non-react-statics@^2.5.4:
+hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0:
version "2.5.5"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
@@ -3147,7 +3187,7 @@ inquirer@^3.0.6:
strip-ansi "^4.0.0"
through "^2.3.6"
-invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.2, invariant@^2.2.4:
+invariant@^2.2.0, invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
@@ -4091,10 +4131,10 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
-lodash-es@^4.17.10, lodash-es@^4.17.5:
- version "4.17.11"
- resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.11.tgz#145ab4a7ac5c5e52a3531fb4f310255a152b4be0"
- integrity sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q==
+lodash-es@^4.17.14:
+ version "4.17.15"
+ resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
+ integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
lodash.pad@^4.1.0:
version "4.5.1"
@@ -4121,11 +4161,16 @@ lodash.throttle@^4.1.1:
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
-lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.1:
+lodash@^4.17.11, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.1:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
+lodash@^4.17.14, lodash@^4.17.5:
+ version "4.17.15"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
+ integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@@ -5324,7 +5369,7 @@ prompts@^2.0.1:
kleur "^3.0.2"
sisteransi "^1.0.0"
-prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
+prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -5333,6 +5378,11 @@ prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0,
object-assign "^4.1.1"
react-is "^16.8.1"
+property-expr@^1.5.0:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f"
+ integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==
+
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@@ -5417,11 +5467,21 @@ react-devtools-core@^3.6.0:
shell-quote "^1.6.1"
ws "^3.3.1"
-react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.3, react-is@^16.8.4, react-is@^16.8.6:
+react-fast-compare@^2.0.1:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
+ integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
+
+react-is@^16.7.0, react-is@^16.8.3, react-is@^16.8.4, react-is@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
+react-is@^16.8.1, react-is@^16.9.0:
+ version "16.9.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
+ integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
+
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
@@ -5577,17 +5637,17 @@ react-proxy@^1.1.7:
lodash "^4.6.1"
react-deep-force-update "^1.0.0"
-react-redux@5.0.7:
- version "5.0.7"
- resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8"
- integrity sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==
+react-redux@7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.1.1.tgz#ce6eee1b734a7a76e0788b3309bf78ff6b34fa0a"
+ integrity sha512-QsW0vcmVVdNQzEkrgzh2W3Ksvr8cqpAv5FhEk7tNEft+5pp7rXxAudTz3VOPawRkLIepItpkEIyLcN/VVXzjTg==
dependencies:
- hoist-non-react-statics "^2.5.0"
- invariant "^2.0.0"
- lodash "^4.17.5"
- lodash-es "^4.17.5"
- loose-envify "^1.1.0"
- prop-types "^15.6.0"
+ "@babel/runtime" "^7.5.5"
+ hoist-non-react-statics "^3.3.0"
+ invariant "^2.2.4"
+ loose-envify "^1.4.0"
+ prop-types "^15.7.2"
+ react-is "^16.9.0"
react-test-renderer@16.8.3:
version "16.8.3"
@@ -5671,49 +5731,27 @@ realpath-native@^1.1.0:
dependencies:
util.promisify "^1.0.0"
-redux-act@1.7.4:
- version "1.7.4"
- resolved "https://registry.yarnpkg.com/redux-act/-/redux-act-1.7.4.tgz#0dd7c6daaca98649540a3d42c259814b048bd8e1"
- integrity sha512-gzpod7iF2sIQAxUjTn/qNmzPGenE3zrFFZlBv8X4Ee8MsvF750jZi0Gucg4Il3KvZ78fsKR2vp6SBuSmD7ex0Q==
+redux-act@1.7.7:
+ version "1.7.7"
+ resolved "https://registry.yarnpkg.com/redux-act/-/redux-act-1.7.7.tgz#0ee8140ade95921b6ebbf70be3fc61c8d6c8a4b1"
+ integrity sha512-UKa6QJkrgrQauFtEuGjnZaBa6dKwXjeu/qchY8ifbA+i/UdEEtOZ/lfowaXkgfllr9c/5EAmmlvk0C9J2wSTnw==
-redux-form@7.4.2:
- version "7.4.2"
- resolved "https://registry.yarnpkg.com/redux-form/-/redux-form-7.4.2.tgz#d6061088fb682eb9fc5fb9749bd8b102f03154b0"
- integrity sha512-QxC36s4Lelx5Cr8dbpxqvl23dwYOydeAX8c6YPmgkz/Dhj053C16S2qoyZN6LO6HJ2oUF00rKsAyE94GwOUhFA==
- dependencies:
- es6-error "^4.1.1"
- hoist-non-react-statics "^2.5.4"
- invariant "^2.2.4"
- is-promise "^2.1.0"
- lodash "^4.17.10"
- lodash-es "^4.17.10"
- prop-types "^15.6.1"
- react-lifecycles-compat "^3.0.4"
-
-redux-persist@5.10.0:
- version "5.10.0"
- resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-5.10.0.tgz#5d8d802c5571e55924efc1c3a9b23575283be62b"
- integrity sha512-sSJAzNq7zka3qVHKce1hbvqf0Vf5DuTVm7dr4GtsqQVOexnrvbV47RWFiPxQ8fscnyiuWyD2O92DOxPl0tGCRg==
+redux-persist@6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8"
+ integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==
-redux-saga@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-1.0.2.tgz#0599703f975438f1b2f9d2b9a965ec58f0fdfcd7"
- integrity sha512-dHV256by3eF2AnBPx1l3HqazQFkErZ82HDXgh4jSRpT72OrX31wyg8DA1q8+0HvENRfJAyhT/4qT5yH/vVqFfw==
- dependencies:
- "@redux-saga/core" "^1.0.2"
-
-redux@4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03"
- integrity sha512-NnnHF0h0WVE/hXyrB6OlX67LYRuaf/rJcbWvnHHEPCF/Xa/AZpwhs/20WyqzQae5x4SD2F9nPObgBh2rxAgLiA==
+redux-saga@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-1.1.1.tgz#7e02879beb02c92030b5fbe746fd70e8bda97dfb"
+ integrity sha512-guSnGJ/uEF8yL8Mn4aNa7HxRGCpVUALCkec9iTTD0fOhQqkF6bRQkBLeS+7/cAH3nFnr299bi/DOurTi1apcCA==
dependencies:
- loose-envify "^1.1.0"
- symbol-observable "^1.2.0"
+ "@redux-saga/core" "^1.1.1"
-"redux@>=0.10 <5":
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5"
- integrity sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==
+redux@4.0.4, redux@^4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.4.tgz#4ee1aeb164b63d6a1bcc57ae4aa0b6e6fa7a3796"
+ integrity sha512-vKv4WdiJxOWKxK0yRoaK3Y4pxxB0ilzVx6dszU2W8wLxlb2yikRph4iV/ymtdJ6ZxpBLFbyrxklnT5yBbQSl3Q==
dependencies:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"
@@ -6427,6 +6465,11 @@ symbol-tree@^3.2.2:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=
+synchronous-promise@^2.0.6:
+ version "2.0.10"
+ resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.10.tgz#e64c6fd3afd25f423963353043f4a68ebd397fd8"
+ integrity sha512-6PC+JRGmNjiG3kJ56ZMNWDPL8hjyghF5cMXIFOKg+NiwwEZZIvxTWd0pinWKyD227odg9ygF8xVhhz7gb8Uq7A==
+
table@4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36"
@@ -6498,6 +6541,11 @@ time-stamp@^1.0.0:
resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3"
integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=
+tiny-warning@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
+ integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
+
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -6545,6 +6593,11 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+toposort@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
+ integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
+
tough-cookie@^2.3.3, tough-cookie@^2.3.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -6573,6 +6626,11 @@ trim-right@^1.0.1:
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
+tslib@^1.9.3:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
+ integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
+
tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
@@ -6614,7 +6672,7 @@ typescript-logic@^0.0.0:
resolved "https://registry.yarnpkg.com/typescript-logic/-/typescript-logic-0.0.0.tgz#66ebd82a2548f2b444a43667bec120b496890196"
integrity sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q==
-typescript-tuple@^2.1.0:
+typescript-tuple@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/typescript-tuple/-/typescript-tuple-2.2.1.tgz#7d9813fb4b355f69ac55032e0363e8bb0f04dad2"
integrity sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==
@@ -7029,3 +7087,15 @@ yargs@^9.0.0:
which-module "^2.0.0"
y18n "^3.2.1"
yargs-parser "^7.0.0"
+
+yup@^0.27.0:
+ version "0.27.0"
+ resolved "https://registry.yarnpkg.com/yup/-/yup-0.27.0.tgz#f8cb198c8e7dd2124beddc2457571329096b06e7"
+ integrity sha512-v1yFnE4+u9za42gG/b/081E7uNW9mUj3qtkmelLbW5YPROZzSH/KUUyJu9Wt8vxFJcT9otL/eZopS0YK1L5yPQ==
+ dependencies:
+ "@babel/runtime" "^7.0.0"
+ fn-name "~2.0.1"
+ lodash "^4.17.11"
+ property-expr "^1.5.0"
+ synchronous-promise "^2.0.6"
+ toposort "^2.0.2"