Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forgot Password flow #27

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions components/login/ForgotPasswordScreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import React from 'react';
import {
Alert,
BackHandler,
Image,
Keyboard,
KeyboardAvoidingView,
StatusBar,
StyleSheet,
Text,
TextInput,
TouchableWithoutFeedback,
View,
} from 'react-native';

import LoadingButton from '../common/LoadingButton';

import {
StackRouter
} from 'react-navigation';

import IconInput from '../common/IconInput';

import UIConstants from '../../constants/UIConstants'
import ComponentStyles from '../../constants/ComponentStyles'
import Colors from '../../constants/Colors'
import LoginRequester from '../../requesters/LoginRequester'
import LocalStorage from '../../helpers/LocalStorage'

class ForgotPasswordScreen extends React.Component {

constructor(props) {
super(props);
this.state = {
email: '[email protected]',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂

isLoading: false,
}
}

componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this._handleBackButton);
}

componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this._handleBackButton);
}

_handleBackButton() {
return true;
}

_confirmEmail = () => {
success = () => {
Alert.alert(
'Email Sent',
'Instructions to reset your password have been sent to your email.',
[{text: 'Close', onPress: () => this.props.navigation.goBack()},]
)
};

failure = (error) => {
window.showBanner('error', error.message);
this.setState({
isLoading: false,
});
};

this.setState({
isLoading: true,
});

LoginRequester.sendEmail(this.state.email).then(success).catch(failure);
}

render() {
return (
<View>
<StatusBar barStyle='light-content' />
<KeyboardAvoidingView behavior='padding' style={styles.screen}>
<TouchableWithoutFeedback
onPress={Keyboard.dismiss}
>
<View style={styles.contentWrapper}>
<Image style={styles.logo} source={require('../../assets/logo-white.png')} />
<View><Text
style={styles.subtitle}
>
Please enter the email address {"\n"}
associated with your Replate account.
</Text></View>
<IconInput
iconName={'person'}
iconColor={Colors.white}
textColor={Colors.white}
containerStyle={styles.inputContainer}
style={styles.inputText}
placeholder='Enter Email'
onChangeText={(text) => this.setState({email: text})}
/>
<LoadingButton
containerStyle={[ComponentStyles.buttonContainer, styles.buttonContainer]}
style={[ComponentStyles.buttonText, styles.buttonText]}
onPress={() => this.props.navigation.goBack()}
title="Cancel" />
<LoadingButton
containerStyle={[ComponentStyles.buttonContainer, styles.buttonContainer]}
style={[ComponentStyles.buttonText, styles.buttonText]}
onPress={this._confirmEmail}
isLoading={this.state.isLoading}
title="Confirm Email" />
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</View>
);
}
}

const styles = StyleSheet.create({

screen: {
backgroundColor: Colors.main,
width: '100%',
height: '100%',
},

keyboardAvoiding: {
flex: 1,
},

contentWrapper: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},

logo: {
width: 40,
height: 40,
marginBottom: 14,
},

subtitle: {
fontSize: UIConstants.fontSizes.title,
fontWeight: UIConstants.fontWeights.normal,
color: Colors.white,
textAlign: 'center',
marginBottom: 14,
},

inputContainer: {
width: 280,
marginBottom: UIConstants.margins.standard,
padding: 10,
borderBottomColor: Colors.alphaColor(Colors.white, 0.5),
borderBottomWidth: 1,
},

inputText: {
fontSize: UIConstants.fontSizes.title,
},

buttonContainer: {
width: 280,
backgroundColor: Colors.alphaColor(Colors.white, 0.3),
marginBottom: UIConstants.margins.standard,
},

buttonText: {
color: Colors.white,
}
});

export default ForgotPasswordScreen;
5 changes: 5 additions & 0 deletions components/login/LoginNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
import LoginScreen from './LoginScreen';
import MainNavigator from '../MainNavigator';
import ResetPasswordScreen from './ResetPasswordScreen'
import ForgotPasswordScreen from './ForgotPasswordScreen'


import NavigationHelper from '../../helpers/NavigationHelper'

Expand All @@ -17,6 +19,9 @@ const LoginNavigator = StackNavigator({
ResetPassword: {
screen: NavigationHelper.paramsToProps(ResetPasswordScreen)
},
ForgotPassword: {
screen: ForgotPasswordScreen
},
Main: {
screen: MainNavigator
}
Expand Down
16 changes: 16 additions & 0 deletions components/login/LoginScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ class LoginScreen extends React.Component {
LoginRequester.signIn(this.state.email, this.state.password).then(success).catch(failure);
}

_forgotPassword = () => {
this.props.navigation.navigate('ForgotPassword')
}

render() {
return (
<View>
Expand Down Expand Up @@ -110,6 +114,11 @@ class LoginScreen extends React.Component {
onPress={this._attemptLogin}
isLoading={this.state.isLoading}
title="Log In" />
<Text
style={styles.linkText}
onPress={this._forgotPassword}>
Forgot your password?
</Text>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
Expand Down Expand Up @@ -165,6 +174,13 @@ const styles = StyleSheet.create({

buttonText: {
color: Colors.white,
},

linkText: {
fontSize: UIConstants.fontSizes.normal,
color: Colors.white,
marginTop: UIConstants.margins.standard,
textDecorationLine: 'underline',
}
});

Expand Down
1 change: 1 addition & 0 deletions requesters/APIConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class APIConstants {
return {
signIn: this.BASE_URL + '/marketplace_users/sign_in',
changePassword: (user_id) => this.BASE_URL + `/marketplace_users/${user_id}/update_password`,
forgotPassword: this.BASE_URL + '/marketplace_users/forgot_password',
}
}

Expand Down
14 changes: 14 additions & 0 deletions requesters/LoginRequester.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ class LoginRequester extends BaseRequester {
return Promise.reject(error);
}
}

static async sendEmail(user_email) {
params = {
marketplace_user: {
email: user_email,
}
}

try {
await BaseRequester.post(APIConstants.login.forgotPassword, params);
} catch (error) {
return Promise.reject(error);
}
}
}

export default LoginRequester;