mirror of
https://bitbucket.org/tagfer_team/tagfer-app.git
synced 2025-12-25 03:37:41 +00:00
Signup Screen One
This commit is contained in:
parent
ef9210fab0
commit
b55af52e94
@ -7,6 +7,10 @@ const endpoints = {
|
||||
passwordReset: {
|
||||
method: 'POST',
|
||||
url: `${baseurl}/auth/passwordReset`
|
||||
},
|
||||
emailExists: {
|
||||
method: 'GET',
|
||||
url: `${baseurl}/auth/email/:email/exists`
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { createStackNavigator, createAppContainer } from 'react-navigation';
|
||||
import WelcomeScreen from '../screens/onboaring/WelcomeScreen';
|
||||
import LoginScreen from '../screens/auth/LoginScreen';
|
||||
import SignupScreenOne from '../screens/auth/SignScreenOne';
|
||||
import ForgotPasswordScreen from '../screens/auth/ForgotPasswordScreen';
|
||||
|
||||
const StackNavigator = createStackNavigator({
|
||||
welcome: WelcomeScreen,
|
||||
login: LoginScreen,
|
||||
forgotPassword: ForgotPasswordScreen
|
||||
forgotPassword: ForgotPasswordScreen,
|
||||
signupOne: SignupScreenOne
|
||||
});
|
||||
|
||||
const AppNavigator = createAppContainer(StackNavigator);
|
||||
|
||||
@ -25,7 +25,8 @@
|
||||
"share": "Share Now",
|
||||
"skip": "Skip",
|
||||
"uploadImage": "Upload Image",
|
||||
"takePhoto": "Take Photo"
|
||||
"takePhoto": "Take Photo",
|
||||
"saveAndContinue": "Save and Continue"
|
||||
},
|
||||
"contactFields": {
|
||||
"about_labelText": "About",
|
||||
@ -559,7 +560,7 @@
|
||||
"title": "Verify SMS Code"
|
||||
},
|
||||
"signUp": {
|
||||
"minPassword": "Must be at least 8 characters.",
|
||||
"minPassword": "6+ characters",
|
||||
"password": "Password",
|
||||
"password2": "Confirm Password",
|
||||
"title": "Sign Up",
|
||||
|
||||
@ -6,7 +6,8 @@ import { showMessage } from 'react-native-flash-message';
|
||||
import { FormLabel, Spacer } from '../../components/common';
|
||||
import { fetchAuth } from '../../utils/fetch';
|
||||
import { strings } from '../../locales/i18n';
|
||||
import { getErrorDescription } from '../../utils/errorHandler';
|
||||
import { showAuthErrorMessage } from '../../utils/errorHandler';
|
||||
import { isEmail } from '../../utils/aux';
|
||||
|
||||
import endpoints from '../../config/apiEndpoints';
|
||||
import colors from '../../config/colors.json';
|
||||
@ -32,41 +33,17 @@ export default class ForgotPasswordScreen extends React.Component {
|
||||
Keyboard.dismiss();
|
||||
this.setState({ loading: true });
|
||||
const body = { email: this.state.email };
|
||||
console.log(body);
|
||||
|
||||
fetchAuth(endpoints.passwordReset, body).then(res => {
|
||||
this.setState({ loading: false });
|
||||
console.log(res);
|
||||
if (res.error) {
|
||||
this.showErrorMessage(res.error);
|
||||
showAuthErrorMessage(res.error);
|
||||
} else {
|
||||
this.showSuccessMessage();
|
||||
}
|
||||
}).catch(error => {
|
||||
this.setState({ loading: false });
|
||||
this.showErrorMessage(error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple regex to check if the input is an email.
|
||||
*/
|
||||
isNotEmail() {
|
||||
const regex = /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/;
|
||||
return !regex.test(this.state.email);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a flash message at the top of the screen.
|
||||
* @param {String} error one of the error codes in {@see config.error.js}
|
||||
*/
|
||||
showErrorMessage(error) {
|
||||
showMessage({
|
||||
message: 'Authentication Error',
|
||||
description: getErrorDescription(error),
|
||||
type: 'danger',
|
||||
icon: 'auto',
|
||||
duration: 4000
|
||||
showAuthErrorMessage(error);
|
||||
});
|
||||
}
|
||||
|
||||
@ -127,7 +104,7 @@ export default class ForgotPasswordScreen extends React.Component {
|
||||
onPress={this.onRequestResetPress.bind(this)}
|
||||
title={strings('settings.forgotPasswordScreen.submitButton')}
|
||||
buttonStyle={styles.buttonStyle}
|
||||
disabled={this.isNotEmail()}
|
||||
disabled={!isEmail(this.state.email)}
|
||||
loading={this.state.loading}
|
||||
fontSize={20}
|
||||
/>
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import React from 'react';
|
||||
import { Image, KeyboardAvoidingView, Platform, Dimensions, View, Text, Keyboard, TouchableWithoutFeedback } from 'react-native';
|
||||
import { Button, FormInput } from 'react-native-elements';
|
||||
import { showMessage } from 'react-native-flash-message';
|
||||
|
||||
import { FormLabel, Spacer, TextButton } from '../../components/common';
|
||||
import { strings } from '../../locales/i18n';
|
||||
import { fetchAuth } from '../../utils/fetch';
|
||||
import { getErrorDescription } from '../../utils/errorHandler';
|
||||
import { showAuthErrorMessage } from '../../utils/errorHandler';
|
||||
|
||||
import endpoints from '../../config/apiEndpoints';
|
||||
import colors from '../../config/colors.json';
|
||||
@ -38,14 +37,14 @@ export default class LoginScreen extends React.Component {
|
||||
fetchAuth(endpoints.login, body).then(res => {
|
||||
if (res.error) {
|
||||
this.setState({ loading: false, password: '' });
|
||||
this.showErrorMessage(res.error);
|
||||
showAuthErrorMessage(res.error);
|
||||
} else {
|
||||
this.setState({ loading: false });
|
||||
console.log(res.sessionId);
|
||||
}
|
||||
}).catch(error => {
|
||||
this.setState({ loading: false, password: '' });
|
||||
this.showErrorMessage(error);
|
||||
showAuthErrorMessage(error);
|
||||
});
|
||||
}
|
||||
|
||||
@ -69,20 +68,6 @@ export default class LoginScreen extends React.Component {
|
||||
return this.state.id.length < 1 || this.state.password.length < 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a flash message at the top of the screen.
|
||||
* @param {String} error one of the error codes in {@see config.error.js}
|
||||
*/
|
||||
showErrorMessage(error) {
|
||||
showMessage({
|
||||
message: 'Authentication Error',
|
||||
description: getErrorDescription(error),
|
||||
type: 'danger',
|
||||
icon: 'auto',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
|
||||
@ -140,7 +125,7 @@ export default class LoginScreen extends React.Component {
|
||||
<TextButton
|
||||
leftText={strings('userLoginScreen.userCreateText')}
|
||||
rightText={strings('userLoginScreen.userCreateButton')}
|
||||
onPress={() => this.props.navigation.navigate('signup1')}
|
||||
onPress={() => this.props.navigation.navigate('signupOne')}
|
||||
disabled={this.state.loading}
|
||||
/>
|
||||
</View>
|
||||
|
||||
245
src/screens/auth/SignScreenOne.js
Normal file
245
src/screens/auth/SignScreenOne.js
Normal file
@ -0,0 +1,245 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Dimensions, Image, KeyboardAvoidingView, Platform, Text, View, ScrollView, Keyboard } from 'react-native';
|
||||
import { Button, FormInput } from 'react-native-elements';
|
||||
|
||||
import { FormLabel, Spacer } from '../../components/common';
|
||||
import { strings } from '../../locales/i18n';
|
||||
import { fetchAuth } from '../../utils/fetch';
|
||||
import { showAuthErrorMessage } from '../../utils/errorHandler';
|
||||
import { isEmail, isEmpty } from '../../utils/aux';
|
||||
|
||||
import logo from '../../../assets/logo-round.png';
|
||||
import colors from '../../config/colors.json';
|
||||
import endpoints from '../../config/apiEndpoints';
|
||||
import errors from '../../config/errors';
|
||||
|
||||
export default class SignupScreenOne extends Component {
|
||||
static navigationOptions = {
|
||||
header: null
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
email: '',
|
||||
password: '',
|
||||
loading: false
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Handles the button press by sending the request, based on the response received either navigates the user
|
||||
* to SignupScreenTwo or displays an error message.
|
||||
*/
|
||||
onSaveButtonPress() {
|
||||
Keyboard.dismiss();
|
||||
this.setState({ loading: true });
|
||||
|
||||
const endpoint = this.addParamsToEndpoint(endpoints.emailExists, this.state.email);
|
||||
|
||||
fetchAuth(endpoint).then(res => {
|
||||
this.toggleLoadingSpinner();
|
||||
|
||||
if (res.error) {
|
||||
showAuthErrorMessage(res.error);
|
||||
} else if (res.result === true) {
|
||||
this.setState({ email: '' });
|
||||
showAuthErrorMessage(errors.AUTH_EMAIL_ALREADY_EXISTS);
|
||||
} else {
|
||||
console.log(res.result);
|
||||
}
|
||||
}).catch(error => {
|
||||
this.toggleLoadingSpinner();
|
||||
showAuthErrorMessage(error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the default express `:email` parameter with the actual value.
|
||||
* @param {Object} endpoint takes an endpoint object @see config/endpoints
|
||||
* @param {String} email
|
||||
*/
|
||||
addParamsToEndpoint(endpoint, email) {
|
||||
const endpointWithParams = { ...endpoint };
|
||||
endpointWithParams.url = endpoint.url.replace(':email', email);
|
||||
return endpointWithParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolen function that says if the button is disabled based on if the fields are empty.
|
||||
*/
|
||||
isButtonDisabled() {
|
||||
const { firstName, lastName, email, password } = this.state;
|
||||
return isEmpty(firstName) || isEmpty(lastName) || !isEmail(email) || password.length < 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function that toggles the state of the loading variable, true to false and false to true.
|
||||
*/
|
||||
toggleLoadingSpinner() {
|
||||
this.setState({ loading: !this.state.loading });
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
return (
|
||||
<ScrollView contentContainerStyle={{ flexGrow: 1, backgroundColor: colors.white }} keyboardShouldPersistTaps="handled" >
|
||||
<View style={{ flex: 1 }}>
|
||||
{/* LOGO */}
|
||||
<View style={styles.logoContainerStyle}>
|
||||
<Image source={logo} />
|
||||
</View>
|
||||
|
||||
{/* HEADER */}
|
||||
<View>
|
||||
<Text style={styles.headerStyle} >Signup</Text>
|
||||
</View>
|
||||
|
||||
{/* TEXT INPUTS */}
|
||||
<View style={{ flex: 3 }}>
|
||||
<Spacer />
|
||||
<FormLabel
|
||||
required
|
||||
labelText={strings('common.contactFields.firstName_labelText').toUpperCase()}
|
||||
textStyle={styles.labelStyle}
|
||||
/>
|
||||
<FormInput
|
||||
value={this.state.firstName}
|
||||
onChangeText={firstName => this.setState({ firstName })}
|
||||
placeholder={strings('common.contactFields.firstName_placeholder')}
|
||||
autoCorrect={false}
|
||||
autoCapitalize='words'
|
||||
inputStyle={styles.inputTextStyle}
|
||||
/>
|
||||
<Spacer />
|
||||
|
||||
<FormLabel
|
||||
required
|
||||
labelText={strings('common.contactFields.lastName_labelText').toUpperCase()}
|
||||
textStyle={styles.labelStyle}
|
||||
/>
|
||||
<FormInput
|
||||
value={this.state.lastName}
|
||||
onChangeText={lastName => this.setState({ lastName })}
|
||||
placeholder={strings('common.contactFields.lastName_placeholder')}
|
||||
autoCorrect={false}
|
||||
autoCapitalize='words'
|
||||
inputStyle={styles.inputTextStyle}
|
||||
/>
|
||||
<Spacer />
|
||||
|
||||
<FormLabel
|
||||
required
|
||||
labelText={strings('common.contactFields.email_labelText').toUpperCase()}
|
||||
textStyle={styles.labelStyle}
|
||||
/>
|
||||
<FormInput
|
||||
value={this.state.email}
|
||||
onChangeText={email => this.setState({ email })}
|
||||
placeholder={strings('common.contactFields.email_or_tagferid_placeholder')}
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
inputStyle={styles.inputTextStyle}
|
||||
/>
|
||||
<Spacer />
|
||||
|
||||
<FormLabel
|
||||
required
|
||||
labelText={strings('userCreateFlow.signUp.password').toUpperCase()}
|
||||
textStyle={styles.labelStyle}
|
||||
/>
|
||||
<FormInput
|
||||
secureTextEntry
|
||||
value={this.state.password}
|
||||
onChangeText={password => this.setState({ password })}
|
||||
placeholder={strings('userCreateFlow.signUp.minPassword')}
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
inputStyle={styles.inputTextStyle}
|
||||
/>
|
||||
<Spacer />
|
||||
|
||||
<View style={{ marginTop: 20 }}>
|
||||
<Text style={styles.freeTextStyle}>
|
||||
{strings('userCreateFlow.termsLeft')}
|
||||
</Text>
|
||||
<Text style={styles.termsButtonStyle} onPress={() => this.props.navigation.navigate('termsAndConditions')}>
|
||||
{strings('userCreateFlow.termsRight')}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<Button
|
||||
onPress={this.onSaveButtonPress.bind(this)}
|
||||
title={strings('common.buttons.saveAndContinue')}
|
||||
buttonStyle={styles.buttonStyle}
|
||||
disabled={this.isButtonDisabled()}
|
||||
loading={this.state.loading}
|
||||
fontSize={20}
|
||||
iconRight={{ name: 'chevron-right', color: colors.white, size: 30, style: { marginLeft: 0 } }}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (Platform.OS === 'android') {
|
||||
return this.renderContent();
|
||||
}
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView style={{ flex: 1 }} behavior="padding" >
|
||||
{this.renderContent()}
|
||||
</KeyboardAvoidingView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const SCREEN_WIDTH = Dimensions.get('window').width;
|
||||
|
||||
const styles = {
|
||||
headerStyle: {
|
||||
color: colors.headerBlue,
|
||||
fontWeight: 'bold',
|
||||
marginLeft: 20,
|
||||
fontSize: 24
|
||||
},
|
||||
logoContainerStyle: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
marginTop: 50
|
||||
},
|
||||
logoStyle: {
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
},
|
||||
buttonStyle: {
|
||||
width: SCREEN_WIDTH * 0.9,
|
||||
marginTop: 15,
|
||||
marginBottom: 30,
|
||||
borderRadius: 5,
|
||||
backgroundColor: colors.buttonBlue
|
||||
},
|
||||
inputTextStyle: {
|
||||
marginLeft: 15,
|
||||
color: colors.black
|
||||
},
|
||||
freeTextStyle: {
|
||||
marginLeft: 20,
|
||||
fontSize: 18,
|
||||
color: '#111111'
|
||||
},
|
||||
termsButtonStyle: {
|
||||
fontSize: 18,
|
||||
color: colors.grey,
|
||||
marginLeft: 20,
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
labelStyle: {
|
||||
color: colors.labelBlue
|
||||
}
|
||||
};
|
||||
8
src/utils/aux.js
Normal file
8
src/utils/aux.js
Normal file
@ -0,0 +1,8 @@
|
||||
export function isEmail(email) {
|
||||
const regex = /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/;
|
||||
return regex.test(email);
|
||||
}
|
||||
|
||||
export function isEmpty(value) {
|
||||
return !value;
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
import { showMessage } from 'react-native-flash-message';
|
||||
|
||||
import errors from '../config/errors';
|
||||
|
||||
export function getErrorDescription(error) {
|
||||
@ -18,3 +20,16 @@ export function getErrorDescription(error) {
|
||||
default: return 'Oops, an error occured! Please try again.';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Display a flash message at the top of the screen.
|
||||
* @param {String} error one of the error codes in @see config/error.js
|
||||
*/
|
||||
export function showAuthErrorMessage(error) {
|
||||
showMessage({
|
||||
message: 'Authentication Error',
|
||||
description: getErrorDescription(error),
|
||||
type: 'danger',
|
||||
icon: 'auto',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
|
||||
@ -11,4 +11,4 @@ export function fetchAuth(endpoint, body) {
|
||||
};
|
||||
|
||||
return fetch(endpoint.url, request).then(res => res.json());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user