diff --git a/src/languages/en.js b/src/languages/en.js index e9e23ca91e49..cbcbfeed3e1c 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,8 @@ 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.', + 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: { @@ -736,7 +737,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 9c74b29e8a09..a4cbb8c1cb16 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,8 @@ 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.', + 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: { @@ -738,7 +739,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/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 c175859a3e70..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({ @@ -141,7 +142,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: isNumericWithSpecialChars(login) + ? translateLocal('messages.errorMessageInvalidPhone') + : translateLocal('loginForm.error.invalidFormatEmailLogin'), + }); } else { Onyx.merge(ONYXKEYS.ACCOUNT, {error: response.message}); } 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 434b41b878f4..4ef3f1f5f24d 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'; @@ -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 {isNumericWithSpecialChars} from '../../libs/ValidationUtils'; const propTypes = { /* Onyx Props */ @@ -63,6 +64,10 @@ class LoginForm extends React.Component { login: text, formError: null, }); + + if (this.props.account.error) { + Onyx.merge(ONYXKEYS.ACCOUNT, {error: ''}); + } } /** @@ -75,7 +80,11 @@ class LoginForm extends React.Component { } if (!Str.isValidEmail(this.state.login) && !Str.isValidPhone(this.state.login)) { - this.setState({formError: 'loginForm.error.invalidFormatLogin'}); + if (isNumericWithSpecialChars(this.state.login)) { + this.setState({formError: 'messages.errorMessageInvalidPhone'}); + } else { + this.setState({formError: 'loginForm.error.invalidFormatEmailLogin'}); + } return; }