From f4e4c2400138f56d15f5f147da27d2ef7ac45d1f Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Fri, 15 Oct 2021 00:30:08 +0530 Subject: [PATCH 1/4] fix: login page error --- src/languages/en.js | 4 ++-- src/languages/es.js | 4 ++-- src/libs/actions/Session.js | 6 +++++- src/pages/signin/LoginForm.js | 8 +++++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 18f6d317f719..42468668d78c 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -373,7 +373,7 @@ export default { loginForm: { phoneOrEmail: 'Phone or email', error: { - invalidFormatLogin: 'The email or phone number entered is invalid. Please fix the format and try again.', + invalidFormatEmailLogin: 'The email entered is invalid. Please fix the format and try again.', }, }, resendValidationForm: { @@ -465,7 +465,7 @@ export default { }, cameraPermissionsNotGranted: 'Camera permissions not granted', messages: { - noPhoneNumber: 'Please enter a phone number including the country code e.g +447814266907', + noPhoneNumber: 'Please enter a phone number including the country code e.g +447814266907.', maxParticipantsReached: 'You\'ve reached the maximum number of participants for a group chat.', }, onfidoStep: { diff --git a/src/languages/es.js b/src/languages/es.js index 95476967924a..f0e299a979fa 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -373,7 +373,7 @@ export default { loginForm: { phoneOrEmail: 'Número de teléfono o email', error: { - invalidFormatLogin: 'El email o número de teléfono que has introducido no es válido. Corrígelo e inténtalo de nuevo.', + invalidFormatEmailLogin: 'El email introducido no es válido. Corrígelo e inténtalo de nuevo.', }, }, resendValidationForm: { @@ -465,7 +465,7 @@ export default { }, cameraPermissionsNotGranted: 'No has habilitado los permisos para acceder a la cámara', messages: { - noPhoneNumber: 'Por favor escribe un número de teléfono que incluya el código de país e.g +447814266907', + noPhoneNumber: 'Por favor escribe un número de teléfono que incluya el código de país e.g +447814266907.', maxParticipantsReached: 'Has llegado al número máximo de participantes para un grupo.', }, onfidoStep: { diff --git a/src/libs/actions/Session.js b/src/libs/actions/Session.js index a70ec279d3b3..bcb1225cca48 100644 --- a/src/libs/actions/Session.js +++ b/src/libs/actions/Session.js @@ -141,7 +141,11 @@ function fetchAccountDetails(login) { resendValidationLink(login); } } else if (response.jsonCode === 402) { - Onyx.merge(ONYXKEYS.ACCOUNT, {error: translateLocal('loginForm.error.invalidFormatLogin')}); + Onyx.merge(ONYXKEYS.ACCOUNT, { + error: CONST.REGEX.DIGITS_AND_PLUS.test(login) + ? translateLocal('messages.noPhoneNumber') + : translateLocal('loginForm.error.invalidFormatEmailLogin'), + }); } else { Onyx.merge(ONYXKEYS.ACCOUNT, {error: response.message}); } diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index 434b41b878f4..468ac72e3ee8 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -15,6 +15,7 @@ import canFocusInputOnScreenFocus from '../../libs/canFocusInputOnScreenFocus'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import getEmailKeyboardType from '../../libs/getEmailKeyboardType'; import ExpensiTextInput from '../../components/ExpensiTextInput'; +import CONST from '../../CONST'; const propTypes = { /* Onyx Props */ @@ -75,7 +76,12 @@ class LoginForm extends React.Component { } if (!Str.isValidEmail(this.state.login) && !Str.isValidPhone(this.state.login)) { - this.setState({formError: 'loginForm.error.invalidFormatLogin'}); + console.debug(CONST.REGEX.DIGITS_AND_PLUS.test(this.state.login)); + if (CONST.REGEX.DIGITS_AND_PLUS.test(this.state.login)) { + this.setState({formError: 'messages.noPhoneNumber'}); + } else { + this.setState({formError: 'loginForm.error.invalidFormatEmailLogin'}); + } return; } From 0e1b829443327708ce70fa911aaefc587f777016 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Fri, 15 Oct 2021 03:05:11 +0530 Subject: [PATCH 2/4] improve message --- src/languages/en.js | 2 +- src/languages/es.js | 2 +- src/libs/actions/Session.js | 2 +- src/pages/RequestCallPage.js | 2 +- src/pages/signin/LoginForm.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 42468668d78c..c9aff5e8fdd8 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -466,6 +466,7 @@ export default { cameraPermissionsNotGranted: 'Camera permissions not granted', messages: { noPhoneNumber: 'Please enter a phone number including the country code e.g +447814266907.', + errorMessageInvalidPhone: 'That doesn’t look like a valid phone number. Try again with the country code. e.g. +15005550006', maxParticipantsReached: 'You\'ve reached the maximum number of participants for a group chat.', }, onfidoStep: { @@ -741,7 +742,6 @@ export default { description: 'Our team of guides are on hand to help you each step of the way. Type in your name and phone number, and we’ll give you a call back.', callMe: 'Call me', growlMessageOnSave: 'Call requested.', - errorMessageInvalidPhone: 'That doesn’t look like a valid phone number. Try again with the country code. e.g. +15005550006', growlMessageEmptyName: 'Please provide both a first and last name so our guides know how to address you!', growlMessageNoPersonalPolicy: 'I wasn’t able to find a personal policy to associate this Guides call with, please check your connection and try again.', callButton: 'Call', diff --git a/src/languages/es.js b/src/languages/es.js index f0e299a979fa..21c0fabba8b6 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -466,6 +466,7 @@ export default { cameraPermissionsNotGranted: 'No has habilitado los permisos para acceder a la cámara', messages: { noPhoneNumber: 'Por favor escribe un número de teléfono que incluya el código de país e.g +447814266907.', + errorMessageInvalidPhone: 'El teléfono no es valido. Inténtalo de nuevo agregando el código de país. P. ej.: +15005550006', maxParticipantsReached: 'Has llegado al número máximo de participantes para un grupo.', }, onfidoStep: { @@ -743,7 +744,6 @@ export default { description: '¿Necesitas ayuda configurando tu cuenta? Nuestro equipo de guías puede ayudarte. Escribe tu nombre y número de teléfono y te llamaremos.', callMe: 'Llámame', growlMessageOnSave: 'Llamada solicitada.', - errorMessageInvalidPhone: 'El teléfono no es valido. Inténtalo de nuevo agregando el código de país. P. ej.: +15005550006', growlMessageEmptyName: 'Por favor ingresa tu nombre completo', growlMessageNoPersonalPolicy: 'No he podido encontrar una póliza personal con la que asociar esta llamada a las Guías, compruebe su conexión e inténtelo de nuevo.', callButton: 'Llamar', diff --git a/src/libs/actions/Session.js b/src/libs/actions/Session.js index bcb1225cca48..7cfd8e2f0f2b 100644 --- a/src/libs/actions/Session.js +++ b/src/libs/actions/Session.js @@ -143,7 +143,7 @@ function fetchAccountDetails(login) { } else if (response.jsonCode === 402) { Onyx.merge(ONYXKEYS.ACCOUNT, { error: CONST.REGEX.DIGITS_AND_PLUS.test(login) - ? translateLocal('messages.noPhoneNumber') + ? translateLocal('messages.errorMessageInvalidPhone') : translateLocal('loginForm.error.invalidFormatEmailLogin'), }); } else { diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js index 7462706410ba..b4153f930d63 100644 --- a/src/pages/RequestCallPage.js +++ b/src/pages/RequestCallPage.js @@ -165,7 +165,7 @@ class RequestCallPage extends Component { if (_.isEmpty(this.state.phoneNumber.trim())) { this.setState({phoneNumberError: this.props.translate('messages.noPhoneNumber')}); } else if (!Str.isValidPhone(this.state.phoneNumber)) { - this.setState({phoneNumberError: this.props.translate('requestCallPage.errorMessageInvalidPhone')}); + this.setState({phoneNumberError: this.props.translate('messages.errorMessageInvalidPhone')}); } else { this.setState({phoneNumberError: ''}); } diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index 468ac72e3ee8..65d3738feeee 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -78,7 +78,7 @@ class LoginForm extends React.Component { if (!Str.isValidEmail(this.state.login) && !Str.isValidPhone(this.state.login)) { console.debug(CONST.REGEX.DIGITS_AND_PLUS.test(this.state.login)); if (CONST.REGEX.DIGITS_AND_PLUS.test(this.state.login)) { - this.setState({formError: 'messages.noPhoneNumber'}); + this.setState({formError: 'messages.errorMessageInvalidPhone'}); } else { this.setState({formError: 'loginForm.error.invalidFormatEmailLogin'}); } From 9918542ab26eca1f6f64f9f20eae415e3a7f242d Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Fri, 15 Oct 2021 04:16:14 +0530 Subject: [PATCH 3/4] fix: error swap --- src/pages/signin/LoginForm.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index 65d3738feeee..08b20ef86e3e 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -1,6 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; +import Onyx, {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import _ from 'underscore'; import Str from 'expensify-common/lib/str'; @@ -64,6 +64,10 @@ class LoginForm extends React.Component { login: text, formError: null, }); + + if (this.props.account.error) { + Onyx.merge(ONYXKEYS.ACCOUNT, {error: ''}); + } } /** @@ -76,7 +80,6 @@ class LoginForm extends React.Component { } if (!Str.isValidEmail(this.state.login) && !Str.isValidPhone(this.state.login)) { - console.debug(CONST.REGEX.DIGITS_AND_PLUS.test(this.state.login)); if (CONST.REGEX.DIGITS_AND_PLUS.test(this.state.login)) { this.setState({formError: 'messages.errorMessageInvalidPhone'}); } else { From 500ba78f4e31c346e731dd64cc29001249a3dcfb Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Tue, 19 Oct 2021 21:53:31 +0530 Subject: [PATCH 4/4] improve Login page error handling --- src/libs/ValidationUtils.js | 10 ++++++++++ src/libs/actions/Session.js | 3 ++- src/pages/signin/LoginForm.js | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libs/ValidationUtils.js b/src/libs/ValidationUtils.js index 4b1223e25b78..b45c5a27b307 100644 --- a/src/libs/ValidationUtils.js +++ b/src/libs/ValidationUtils.js @@ -212,6 +212,15 @@ function isValidUSPhone(phoneNumber) { return CONST.REGEX.PHONE_E164_PLUS.test(phoneNumber.replace(CONST.REGEX.NON_ALPHA_NUMERIC, '')) && CONST.REGEX.US_PHONE.test(phoneNumber); } +/** + * Checks whether a value is a numeric string including `(`, `)`, `-` and optional leading `+` + * @param {String} input + * @returns {Boolean} + */ +function isNumericWithSpecialChars(input) { + return /^\+?\d*$/.test(input.replace(/[()-]/g, '')); +} + export { meetsAgeRequirements, isValidAddress, @@ -226,4 +235,5 @@ export { isValidUSPhone, isValidURL, validateIdentity, + isNumericWithSpecialChars, }; diff --git a/src/libs/actions/Session.js b/src/libs/actions/Session.js index 34054af0f235..2982e61f3d1f 100644 --- a/src/libs/actions/Session.js +++ b/src/libs/actions/Session.js @@ -19,6 +19,7 @@ import Timers from '../Timers'; import * as Pusher from '../Pusher/pusher'; import NetworkConnection from '../NetworkConnection'; import {getUserDetails} from './User'; +import {isNumericWithSpecialChars} from '../ValidationUtils'; let credentials = {}; Onyx.connect({ @@ -142,7 +143,7 @@ function fetchAccountDetails(login) { } } else if (response.jsonCode === 402) { Onyx.merge(ONYXKEYS.ACCOUNT, { - error: CONST.REGEX.DIGITS_AND_PLUS.test(login) + error: isNumericWithSpecialChars(login) ? translateLocal('messages.errorMessageInvalidPhone') : translateLocal('loginForm.error.invalidFormatEmailLogin'), }); diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index 08b20ef86e3e..4ef3f1f5f24d 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -15,7 +15,7 @@ import canFocusInputOnScreenFocus from '../../libs/canFocusInputOnScreenFocus'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import getEmailKeyboardType from '../../libs/getEmailKeyboardType'; import ExpensiTextInput from '../../components/ExpensiTextInput'; -import CONST from '../../CONST'; +import {isNumericWithSpecialChars} from '../../libs/ValidationUtils'; const propTypes = { /* Onyx Props */ @@ -80,7 +80,7 @@ class LoginForm extends React.Component { } if (!Str.isValidEmail(this.state.login) && !Str.isValidPhone(this.state.login)) { - if (CONST.REGEX.DIGITS_AND_PLUS.test(this.state.login)) { + if (isNumericWithSpecialChars(this.state.login)) { this.setState({formError: 'messages.errorMessageInvalidPhone'}); } else { this.setState({formError: 'loginForm.error.invalidFormatEmailLogin'});