Added sign in errors and logos.
This commit is contained in:
12
app.json
12
app.json
@@ -3,24 +3,22 @@
|
|||||||
"name": "imexmobile",
|
"name": "imexmobile",
|
||||||
"slug": "imexmobile",
|
"slug": "imexmobile",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "both",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon240.png",
|
||||||
"splash": {
|
"splash": {
|
||||||
"image": "./assets/splash.png",
|
"image": "./assets/logo1024.png",
|
||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"updates": {
|
"updates": {
|
||||||
"fallbackToCacheTimeout": 0
|
"fallbackToCacheTimeout": 0
|
||||||
},
|
},
|
||||||
"assetBundlePatterns": [
|
"assetBundlePatterns": ["**/*"],
|
||||||
"**/*"
|
|
||||||
],
|
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true
|
"supportsTablet": true
|
||||||
},
|
},
|
||||||
"web": {
|
"web": {
|
||||||
"favicon": "./assets/favicon.png"
|
"favicon": "./assets/logo240.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/logo1024.png
Normal file
BIN
assets/logo1024.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
assets/logo240.png
Normal file
BIN
assets/logo240.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
@@ -21,6 +21,32 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>translation</name>
|
<name>translation</name>
|
||||||
<children>
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>app</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>title</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>general</name>
|
<name>general</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -200,6 +226,74 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>errors</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>emailformat</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>usernotfound</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>wrongpassword</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>fields</name>
|
<name>fields</name>
|
||||||
<children>
|
<children>
|
||||||
|
|||||||
@@ -1,26 +1,34 @@
|
|||||||
import { Formik } from "formik";
|
import { Formik } from "formik";
|
||||||
import {
|
import {
|
||||||
Input,
|
|
||||||
Header,
|
|
||||||
Item,
|
|
||||||
Label,
|
|
||||||
Form,
|
|
||||||
Button,
|
Button,
|
||||||
Text,
|
|
||||||
Container,
|
Container,
|
||||||
Content,
|
Content,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Item,
|
||||||
|
H1,
|
||||||
|
Label,
|
||||||
|
Text,
|
||||||
} from "native-base";
|
} from "native-base";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { SafeAreaView, TextInput, View } from "react-native";
|
import { StyleSheet, View, ActivityIndicator, Image } from "react-native";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { emailSignInStart, signOutStart } from "../../redux/user/user.actions";
|
import { emailSignInStart } from "../../redux/user/user.actions";
|
||||||
import { selectCurrentUser } from "../../redux/user/user.selectors";
|
import {
|
||||||
import { StyleSheet } from "react-native";
|
selectCurrentUser,
|
||||||
|
selectSignInError,
|
||||||
|
selectSigningIn,
|
||||||
|
} from "../../redux/user/user.selectors";
|
||||||
|
import SignInErrorAlertComponent from "../sign-in-error-alert/sign-in-error-alert.component";
|
||||||
|
import styles from "../styles";
|
||||||
|
import Logo from "../../assets/logo240.png";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
|
signInError: selectSignInError,
|
||||||
|
signingIn: selectSigningIn,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
@@ -28,7 +36,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
dispatch(emailSignInStart({ email, password })),
|
dispatch(emailSignInStart({ email, password })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function SignIn({ emailSignInStart }) {
|
export function SignIn({ emailSignInStart, signInError, signingIn }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const formSubmit = (values) => {
|
const formSubmit = (values) => {
|
||||||
@@ -39,42 +47,45 @@ export function SignIn({ emailSignInStart }) {
|
|||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Content
|
<Content
|
||||||
|
scrollEnabled={false}
|
||||||
padder
|
padder
|
||||||
contentContainerStyle={styles.contentContainer}
|
contentContainerStyle={styles.contentContainer__centered}
|
||||||
style={styles.content}
|
style={localStyles.content}
|
||||||
>
|
>
|
||||||
|
<View style={styles.evenlySpacedRow}>
|
||||||
|
<Image style={localStyles.logo} source={Logo} />
|
||||||
|
<H1>{t("app.title")}</H1>
|
||||||
|
</View>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{ email: "", password: "" }}
|
initialValues={{ email: "", password: "" }}
|
||||||
onSubmit={formSubmit}
|
onSubmit={formSubmit}
|
||||||
>
|
>
|
||||||
{({ handleChange, handleBlur, handleSubmit, values }) => (
|
{({ handleChange, handleBlur, handleSubmit, values }) => (
|
||||||
<View>
|
<View>
|
||||||
<Form>
|
<Item>
|
||||||
<Item>
|
<Label>{t("signin.fields.email")}</Label>
|
||||||
<Label>{t("signin.fields.email")}</Label>
|
<Input
|
||||||
<Input
|
autoCapitalize="none"
|
||||||
autoCapitalize="none"
|
keyboardType="email-address"
|
||||||
keyboardType="email-address"
|
onChangeText={handleChange("email")}
|
||||||
onChangeText={handleChange("email")}
|
onBlur={handleBlur("email")}
|
||||||
onBlur={handleBlur("email")}
|
value={values.email}
|
||||||
value={values.email}
|
/>
|
||||||
/>
|
</Item>
|
||||||
</Item>
|
<Item>
|
||||||
|
<Label>{t("signin.fields.password")}</Label>
|
||||||
<Item>
|
<Input
|
||||||
<Label>{t("signin.fields.password")}</Label>
|
secureTextEntry={true}
|
||||||
<Input
|
onChangeText={handleChange("password")}
|
||||||
secureTextEntry={true}
|
onBlur={handleBlur("password")}
|
||||||
onChangeText={handleChange("password")}
|
value={values.password}
|
||||||
onBlur={handleBlur("password")}
|
/>
|
||||||
value={values.password}
|
</Item>
|
||||||
/>
|
<SignInErrorAlertComponent />
|
||||||
</Item>
|
<Button full onPress={handleSubmit}>
|
||||||
|
<Text>{t("signin.actions.signin")}</Text>
|
||||||
<Button full onPress={handleSubmit}>
|
{signingIn ? <ActivityIndicator size="large" /> : null}
|
||||||
<Text>{t("signin.actions.signin")}</Text>
|
</Button>
|
||||||
</Button>
|
|
||||||
</Form>
|
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</Formik>
|
</Formik>
|
||||||
@@ -83,19 +94,11 @@ export function SignIn({ emailSignInStart }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const localStyles = StyleSheet.create({
|
||||||
contentContainer: {
|
|
||||||
justifyContent: "center",
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
content: {
|
content: {
|
||||||
paddingBottom: 150,
|
paddingBottom: 150,
|
||||||
// flex: 1,
|
|
||||||
// backgroundColor: "#fff",
|
|
||||||
// alignItems: "center",
|
|
||||||
//justifyContent: "space-between",
|
|
||||||
// //justifyContent: "center",
|
|
||||||
},
|
},
|
||||||
|
logo: { width: 100, height: 100 },
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(SignIn);
|
export default connect(mapStateToProps, mapDispatchToProps)(SignIn);
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Container, Content, Text } from "native-base";
|
||||||
|
import { View, StyleSheet } from "react-native";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectSignInError } from "../../redux/user/user.selectors";
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
signInError: selectSignInError,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function SignInErrorAlertComponent({ signInError }) {
|
||||||
|
const [errorText, setErrorText] = useState("");
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let text;
|
||||||
|
if (signInError && signInError.code)
|
||||||
|
switch (signInError.code) {
|
||||||
|
case "auth/user-not-found":
|
||||||
|
text = t("signin.errors.usernotfound");
|
||||||
|
break;
|
||||||
|
case "auth/invalid-email":
|
||||||
|
text = t("signin.errors.emailformat");
|
||||||
|
break;
|
||||||
|
case "auth/wrong-password":
|
||||||
|
text = t("signin.errors.wrongpassword");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
text = signInError.code + " " + signInError.message;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setErrorText(text);
|
||||||
|
}, [signInError, setErrorText]);
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
{errorText ? <Text style={localStyles.alert}>{errorText}</Text> : null}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, null)(SignInErrorAlertComponent);
|
||||||
|
|
||||||
|
const localStyles = StyleSheet.create({
|
||||||
|
alert: {
|
||||||
|
color: "red",
|
||||||
|
textAlign: "center",
|
||||||
|
margin: 15,
|
||||||
|
padding: 15,
|
||||||
|
},
|
||||||
|
});
|
||||||
15
components/styles.js
Normal file
15
components/styles.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
import { Row } from "native-base";
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
contentContainer__centered: {
|
||||||
|
justifyContent: "center",
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
evenlySpacedRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-evenly",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -6,39 +6,23 @@ const INITIAL_STATE = {
|
|||||||
},
|
},
|
||||||
bodyshop: null,
|
bodyshop: null,
|
||||||
fingerprint: null,
|
fingerprint: null,
|
||||||
|
signingIn: false,
|
||||||
error: null,
|
error: null,
|
||||||
conflict: false,
|
conflict: false,
|
||||||
passwordreset: {
|
|
||||||
email: null,
|
|
||||||
error: null,
|
|
||||||
success: false,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const userReducer = (state = INITIAL_STATE, action) => {
|
const userReducer = (state = INITIAL_STATE, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
// case UserActionTypes.VALIDATE_PASSWORD_RESET_START:
|
case UserActionTypes.EMAIL_SIGN_IN_START:
|
||||||
// case UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START:
|
return {
|
||||||
// return {
|
...state,
|
||||||
// ...state,
|
signingIn: true,
|
||||||
// passwordreset: {
|
error: null,
|
||||||
// email: action.payload,
|
};
|
||||||
// error: null,
|
|
||||||
// success: false,
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
// case UserActionTypes.VALIDATE_PASSWORD_RESET_FAILURE:
|
|
||||||
// case UserActionTypes.SEND_PASSWORD_RESET_EMAIL_FAILURE:
|
|
||||||
// return { ...state, passwordreset: { error: action.payload } };
|
|
||||||
// case UserActionTypes.VALIDATE_PASSWORD_RESET_SUCCESS:
|
|
||||||
// case UserActionTypes.SEND_PASSWORD_RESET_EMAIL_SUCCESS:
|
|
||||||
// return {
|
|
||||||
// ...state,
|
|
||||||
// passwordreset: { ...state.passwordreset, success: true },
|
|
||||||
// };
|
|
||||||
case UserActionTypes.SIGN_IN_SUCCESS:
|
case UserActionTypes.SIGN_IN_SUCCESS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
signingIn: false,
|
||||||
currentUser: action.payload,
|
currentUser: action.payload,
|
||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
@@ -54,11 +38,7 @@ const userReducer = (state = INITIAL_STATE, action) => {
|
|||||||
error: null,
|
error: null,
|
||||||
currentUser: { authorized: false },
|
currentUser: { authorized: false },
|
||||||
};
|
};
|
||||||
// case UserActionTypes.SET_USER_LANGUAGE:
|
|
||||||
// return {
|
|
||||||
// ...state,
|
|
||||||
// language: action.payload,
|
|
||||||
// };
|
|
||||||
case UserActionTypes.UPDATE_USER_DETAILS_SUCCESS:
|
case UserActionTypes.UPDATE_USER_DETAILS_SUCCESS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@@ -75,6 +55,7 @@ const userReducer = (state = INITIAL_STATE, action) => {
|
|||||||
case UserActionTypes.EMAIL_SIGN_UP_FAILURE:
|
case UserActionTypes.EMAIL_SIGN_UP_FAILURE:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
signingIn: false,
|
||||||
error: action.payload,
|
error: action.payload,
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -26,3 +26,8 @@ export const selectPasswordReset = createSelector(
|
|||||||
[selectUser],
|
[selectUser],
|
||||||
(user) => user.passwordreset
|
(user) => user.passwordreset
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const selectSigningIn = createSelector(
|
||||||
|
[selectUser],
|
||||||
|
(user) => user.signingIn
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const UserActionTypes = {
|
const UserActionTypes = {
|
||||||
SET_CURRENT_USER: "SET_CURRENT_USER",
|
SET_CURRENT_USER: "SET_CURRENT_USER",
|
||||||
GOOGLE_SIGN_IN_START: "GOOGLE_SIGN_IN_START",
|
|
||||||
SIGN_IN_SUCCESS: "SIGN_IN_SUCCESS",
|
SIGN_IN_SUCCESS: "SIGN_IN_SUCCESS",
|
||||||
SIGN_IN_FAILURE: "SIGN_IN_FAILURE",
|
SIGN_IN_FAILURE: "SIGN_IN_FAILURE",
|
||||||
EMAIL_SIGN_IN_START: "EMAIL_SIGN_IN_START",
|
EMAIL_SIGN_IN_START: "EMAIL_SIGN_IN_START",
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"translation": {
|
"translation": {
|
||||||
|
"app": {
|
||||||
|
"title": "ImEX Mobile"
|
||||||
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"signout": "Sign Out"
|
"signout": "Sign Out"
|
||||||
@@ -27,6 +30,11 @@
|
|||||||
"actions": {
|
"actions": {
|
||||||
"signin": "Sign In"
|
"signin": "Sign In"
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"emailformat": "The email you have entered is not formatted correctly. ",
|
||||||
|
"usernotfound": "No user found.",
|
||||||
|
"wrongpassword": "The password you entered is not correct."
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"password": "Password"
|
"password": "Password"
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"translation": {
|
"translation": {
|
||||||
|
"app": {
|
||||||
|
"title": ""
|
||||||
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"signout": ""
|
"signout": ""
|
||||||
@@ -27,6 +30,11 @@
|
|||||||
"actions": {
|
"actions": {
|
||||||
"signin": ""
|
"signin": ""
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"emailformat": "",
|
||||||
|
"usernotfound": "",
|
||||||
|
"wrongpassword": ""
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"password": ""
|
"password": ""
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"translation": {
|
"translation": {
|
||||||
|
"app": {
|
||||||
|
"title": ""
|
||||||
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"signout": ""
|
"signout": ""
|
||||||
@@ -27,6 +30,11 @@
|
|||||||
"actions": {
|
"actions": {
|
||||||
"signin": ""
|
"signin": ""
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"emailformat": "",
|
||||||
|
"usernotfound": "",
|
||||||
|
"wrongpassword": ""
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"password": ""
|
"password": ""
|
||||||
|
|||||||
Reference in New Issue
Block a user