application-amicale/src/screens/Amicale/LoginScreen.js

311 lines
10 KiB
JavaScript

// @flow
import * as React from 'react';
import {Animated, KeyboardAvoidingView, Linking, StyleSheet, View} from "react-native";
import {Avatar, Button, Card, HelperText, Paragraph, TextInput, withTheme} from 'react-native-paper';
import ConnectionManager from "../../managers/ConnectionManager";
import i18n from 'i18n-js';
import ErrorDialog from "../../components/Dialogs/ErrorDialog";
import {withCollapsible} from "../../utils/withCollapsible";
import {Collapsible} from "react-navigation-collapsible";
import CustomTabBar from "../../components/Tabbar/CustomTabBar";
import type {CustomTheme} from "../../managers/ThemeManager";
type Props = {
navigation: Object,
route: Object,
collapsibleStack: Collapsible,
theme: CustomTheme
}
type State = {
email: string,
password: string,
isEmailValidated: boolean,
isPasswordValidated: boolean,
loading: boolean,
dialogVisible: boolean,
dialogError: number,
}
const ICON_AMICALE = require('../../../assets/amicale.png');
const RESET_PASSWORD_PATH = "https://www.amicale-insat.fr//password/reset";
const emailRegex = /^.+@.+\..+$/;
class LoginScreen extends React.Component<Props, State> {
state = {
email: '',
password: '',
isEmailValidated: false,
isPasswordValidated: false,
loading: false,
dialogVisible: false,
dialogError: 0,
};
onEmailChange: Function;
onPasswordChange: Function;
passwordInputRef: Object;
nextScreen: string | null;
constructor(props) {
super(props);
this.onEmailChange = this.onInputChange.bind(this, true);
this.onPasswordChange = this.onInputChange.bind(this, false);
this.props.navigation.addListener('focus', this.onScreenFocus);
}
onScreenFocus = () => {
this.handleNavigationParams();
};
handleNavigationParams () {
if (this.props.route.params != null) {
if (this.props.route.params.nextScreen != null)
this.nextScreen = this.props.route.params.nextScreen;
else
this.nextScreen = null;
}
console.log(this.nextScreen);
}
showErrorDialog = (error: number) =>
this.setState({
dialogVisible: true,
dialogError: error,
});
hideErrorDialog = () => this.setState({dialogVisible: false});
handleSuccess = () => {
if (this.nextScreen == null)
this.props.navigation.goBack();
else
this.props.navigation.replace(this.nextScreen);
};
onResetPasswordClick = () => Linking.openURL(RESET_PASSWORD_PATH);
validateEmail = () => this.setState({isEmailValidated: true});
isEmailValid() {
return emailRegex.test(this.state.email);
}
shouldShowEmailError() {
return this.state.isEmailValidated && !this.isEmailValid();
}
validatePassword = () => this.setState({isPasswordValidated: true});
isPasswordValid() {
return this.state.password !== '';
}
shouldShowPasswordError() {
return this.state.isPasswordValidated && !this.isPasswordValid();
}
shouldEnableLogin() {
return this.isEmailValid() && this.isPasswordValid() && !this.state.loading;
}
onInputChange(isEmail: boolean, value: string) {
if (isEmail) {
this.setState({
email: value,
isEmailValidated: false,
});
} else {
this.setState({
password: value,
isPasswordValidated: false,
});
}
}
onEmailSubmit = () => this.passwordInputRef.focus();
onSubmit = () => {
if (this.shouldEnableLogin()) {
this.setState({loading: true});
ConnectionManager.getInstance().connect(this.state.email, this.state.password)
.then(this.handleSuccess)
.catch(this.showErrorDialog)
.finally(() => {
this.setState({loading: false});
});
}
};
getFormInput() {
return (
<View>
<TextInput
label={i18n.t("loginScreen.email")}
mode='outlined'
value={this.state.email}
onChangeText={this.onEmailChange}
onBlur={this.validateEmail}
onSubmitEditing={this.onEmailSubmit}
error={this.shouldShowEmailError()}
textContentType={'emailAddress'}
autoCapitalize={'none'}
autoCompleteType={'email'}
autoCorrect={false}
keyboardType={'email-address'}
returnKeyType={'next'}
secureTextEntry={false}
/>
<HelperText
type="error"
visible={this.shouldShowEmailError()}
>
{i18n.t("loginScreen.emailError")}
</HelperText>
<TextInput
ref={(ref) => {
this.passwordInputRef = ref;
}}
label={i18n.t("loginScreen.password")}
mode='outlined'
value={this.state.password}
onChangeText={this.onPasswordChange}
onBlur={this.validatePassword}
onSubmitEditing={this.onSubmit}
error={this.shouldShowPasswordError()}
textContentType={'password'}
autoCapitalize={'none'}
autoCompleteType={'password'}
autoCorrect={false}
keyboardType={'default'}
returnKeyType={'done'}
secureTextEntry={true}
/>
<HelperText
type="error"
visible={this.shouldShowPasswordError()}
>
{i18n.t("loginScreen.passwordError")}
</HelperText>
</View>
);
}
getMainCard() {
return (
<Card style={styles.card}>
<Card.Title
title={i18n.t("loginScreen.title")}
subtitle={i18n.t("loginScreen.subtitle")}
left={(props) => <Avatar.Image
{...props}
source={ICON_AMICALE}
style={{backgroundColor: 'transparent'}}/>}
/>
<Card.Content>
{this.getFormInput()}
<Card.Actions>
<Button
icon="send"
mode="contained"
disabled={!this.shouldEnableLogin()}
loading={this.state.loading}
onPress={this.onSubmit}
style={{marginLeft: 'auto'}}>
{i18n.t("loginScreen.login")}
</Button>
</Card.Actions>
<Card.Actions>
<Button
icon="help-circle"
mode="contained"
onPress={this.onResetPasswordClick}
style={{marginLeft: 'auto'}}>
{i18n.t("loginScreen.resetPassword")}
</Button>
</Card.Actions>
</Card.Content>
</Card>
);
}
getSecondaryCard() {
return (
<Card style={styles.card}>
<Card.Title
title={i18n.t("loginScreen.whyAccountTitle")}
subtitle={i18n.t("loginScreen.whyAccountSub")}
left={(props) => <Avatar.Icon
{...props}
icon={"help"}
color={this.props.theme.colors.primary}
style={{backgroundColor: 'transparent'}}/>}
/>
<Card.Content>
<Paragraph>{i18n.t("loginScreen.whyAccountParagraph")}</Paragraph>
<Paragraph>{i18n.t("loginScreen.whyAccountParagraph2")}</Paragraph>
<Paragraph>{i18n.t("loginScreen.noAccount")}</Paragraph>
</Card.Content>
</Card>
);
}
render() {
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
return (
<KeyboardAvoidingView
behavior={"height"}
contentContainerStyle={styles.container}
style={styles.container}
enabled
keyboardVerticalOffset={100}
>
<Animated.ScrollView
onScroll={onScroll}
contentContainerStyle={{
paddingTop: containerPaddingTop,
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
}}
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
>
<View>
{this.getMainCard()}
{this.getSecondaryCard()}
</View>
<ErrorDialog
visible={this.state.dialogVisible}
onDismiss={this.hideErrorDialog}
errorCode={this.state.dialogError}
/>
</Animated.ScrollView>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
},
card: {
margin: 10,
},
header: {
fontSize: 36,
marginBottom: 48
},
textInput: {},
btnContainer: {
marginTop: 5,
marginBottom: 10,
}
});
export default withCollapsible(withTheme(LoginScreen));