Skip to content

Commit

Permalink
Merge pull request Expensify#18223 from dhairyasenjaliya/newContactForm
Browse files Browse the repository at this point in the history
Migrate Forms into NewContactMethodPage
  • Loading branch information
cristipaval authored May 12, 2023
2 parents 496e166 + ac18adf commit 2376b77
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 45 deletions.
1 change: 1 addition & 0 deletions src/ONYXKEYS.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export default {
NEW_TASK_FORM: 'newTaskForm',
EDIT_TASK_FORM: 'editTaskForm',
MONEY_REQUEST_DESCRIPTION_FORM: 'moneyRequestDescriptionForm',
NEW_CONTACT_METHOD_FORM: 'newContactMethodForm',
},

// Whether we should show the compose input or not
Expand Down
4 changes: 4 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,10 @@ export default {
deleteContactMethod: 'Failed to delete contact method. Please reach out to Concierge for help.',
setDefaultContactMethod: 'Failed to set a new default contact method. Please reach out to Concierge for help.',
addContactMethod: 'Failed to add this contact method. Please reach out to Concierge for help.',
enteredMethodIsAlreadySubmited: 'The Entered Contact Method already exists.',
passwordRequired: 'password required.',
contactMethodRequired: 'Contact method is required.',
invalidContactMethod: 'Invalid contact method.',
},
newContactMethod: 'New contact method',
},
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,10 @@ export default {
deleteContactMethod: 'No se ha podido eliminar este método de contacto. Por favor, contacta con Concierge para obtener ayuda.',
setDefaultContactMethod: 'No se pudo establecer un nuevo método de contacto predeterminado. Por favor contacta con Concierge para obtener ayuda.',
addContactMethod: 'Hubo un error al añadir este método de contacto. Por favor, contacta con Concierge para obtener ayuda.',
enteredMethodIsAlreadySubmited: 'El método de contacto ingresado ya existe.',
passwordRequired: 'Se requiere contraseña',
contactMethodRequired: 'Se requiere método de contacto.',
invalidContactMethod: 'Método de contacto no válido.',
},
newContactMethod: 'Nuevo método de contacto',
},
Expand Down
109 changes: 64 additions & 45 deletions src/pages/settings/Profile/Contacts/NewContactMethodPage.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React, {useCallback, useMemo, useRef, useState} from 'react';
import React, {useRef} from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import {ScrollView} from 'react-native-gesture-handler';
import {withOnyx} from 'react-native-onyx';
import {compose} from 'underscore';
import _ from 'underscore';
import lodashGet from 'lodash/get';
import Str from 'expensify-common/lib/str';
import {parsePhoneNumber} from 'awesome-phonenumber';
import Button from '../../../../components/Button';
import FixedFooter from '../../../../components/FixedFooter';
import compose from '../../../../libs/compose';
import HeaderWithCloseButton from '../../../../components/HeaderWithCloseButton';
import ScreenWrapper from '../../../../components/ScreenWrapper';
import Text from '../../../../components/Text';
Expand All @@ -21,6 +19,8 @@ import ROUTES from '../../../../ROUTES';
import styles from '../../../../styles/styles';
import * as User from '../../../../libs/actions/User';
import * as LoginUtils from '../../../../libs/LoginUtils';
import * as ErrorUtils from '../../../../libs/ErrorUtils';
import Form from '../../../../components/Form';
import CONST from '../../../../CONST';

const propTypes = {
Expand Down Expand Up @@ -55,86 +55,105 @@ const defaultProps = {
};

function NewContactMethodPage(props) {
const [login, setLogin] = useState('');
const [password, setPassword] = useState('');
const loginInputRef = useRef(null);

const handleLoginChange = useCallback((value) => {
setLogin(value.trim());
}, []);
const getPhoneLogin = (phoneOrEmail) => {
if (_.isEmpty(phoneOrEmail)) {
return '';
}

return LoginUtils.appendCountryCode(LoginUtils.getPhoneNumberWithoutSpecialChars(phoneOrEmail));
};

const handlePasswordChange = useCallback((value) => {
setPassword(value.trim());
}, []);
const validateNumber = (values) => {
const parsedPhoneNumber = parsePhoneNumber(values);

if (parsedPhoneNumber.possible) {
return parsedPhoneNumber.number.e164 + CONST.SMS.DOMAIN;
}

const isFormValid = useMemo(() => {
const phoneLogin = LoginUtils.appendCountryCode(LoginUtils.getPhoneNumberWithoutSpecialChars(login));
return '';
};

return (Permissions.canUsePasswordlessLogins(props.betas) || password) && (Str.isValidEmail(login) || parsePhoneNumber(phoneLogin).possible);
}, [login, password, props.betas]);
const validate = (values) => {
const phoneLogin = getPhoneLogin(values.phoneOrEmail);
const validateIfnumber = validateNumber(phoneLogin);

const submitForm = useCallback(() => {
const phoneLogin = LoginUtils.appendCountryCode(LoginUtils.getPhoneNumberWithoutSpecialChars(login));
const parsedPhoneNumber = parsePhoneNumber(phoneLogin);
const userLogin = parsedPhoneNumber.possible ? `${parsedPhoneNumber.number.e164}${CONST.SMS.DOMAIN}` : login;
const errors = {};

// If this login already exists, just go back.
if (lodashGet(props.loginList, userLogin)) {
Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS);
return;
if (_.isEmpty(values.phoneOrEmail)) {
ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', props.translate('contacts.genericFailureMessages.contactMethodRequired'));
}

User.addNewContactMethodAndNavigate(userLogin, password);
}, [login, props.loginList, password]);
if (!_.isEmpty(values.phoneOrEmail) && !(parsePhoneNumber(phoneLogin).possible || Str.isValidEmail(values.phoneOrEmail))) {
ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', props.translate('contacts.genericFailureMessages.invalidContactMethod'));
}

if (!_.isEmpty(values.phoneOrEmail) && lodashGet(props.loginList, validateIfnumber || values.phoneOrEmail.toLowerCase())) {
ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', props.translate('contacts.genericFailureMessages.enteredMethodIsAlreadySubmited'));
}

if (!Permissions.canUsePasswordlessLogins(props.betas) && _.isEmpty(values.password)) {
errors.password = props.translate('contacts.genericFailureMessages.passwordRequired');
}

return errors;
};

const addNewContactMethod = (values) => {
const phoneLogin = getPhoneLogin(values.phoneOrEmail);
const validateIfnumber = validateNumber(phoneLogin);
const submitDetail = (validateIfnumber || values.phoneOrEmail).trim();

User.addNewContactMethodAndNavigate(submitDetail, values.password);
};

return (
<ScreenWrapper
onEntryTransitionEnd={() => {
if (!loginInputRef.current) {
return;
}

loginInputRef.current.focus();
}}
includeSafeAreaPaddingBottom={false}
>
<HeaderWithCloseButton
title={props.translate('contacts.newContactMethod')}
shouldShowBackButton
onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS)}
onCloseButtonPress={() => Navigation.dismissModal(true)}
/>
<ScrollView>
<Text style={[styles.ph5, styles.mb5]}>{props.translate('common.pleaseEnterEmailOrPhoneNumber')}</Text>
<View style={[styles.ph5, styles.mb6]}>
<Form
formID={ONYXKEYS.FORMS.NEW_CONTACT_METHOD_FORM}
validate={validate}
onSubmit={addNewContactMethod}
submitButtonText={props.translate('common.add')}
style={[styles.flexGrow1, styles.mh5]}
enabledWhenOffline
>
<Text style={[styles.mb5]}>{props.translate('common.pleaseEnterEmailOrPhoneNumber')}</Text>
<View style={[styles.mb6]}>
<TextInput
label={`${props.translate('common.email')}/${props.translate('common.phoneNumber')}`}
keyboardType={CONST.KEYBOARD_TYPE.EMAIL_ADDRESS}
ref={(el) => (loginInputRef.current = el)}
value={login}
onChangeText={handleLoginChange}
inputID="phoneOrEmail"
autoCapitalize="none"
returnKeyType={Permissions.canUsePasswordlessLogins(props.betas) ? 'done' : 'next'}
/>
</View>
{!Permissions.canUsePasswordlessLogins(props.betas) && (
<View style={[styles.ph5, styles.mb6]}>
<View style={[styles.mb6]}>
<TextInput
label={props.translate('common.password')}
value={password}
onChangeText={handlePasswordChange}
inputID="password"
returnKeyType="done"
/>
</View>
)}
</ScrollView>
<FixedFooter style={[styles.flexGrow0]}>
<Button
success
isDisabled={!isFormValid}
text={props.translate('common.add')}
onPress={submitForm}
pressOnEnter
/>
</FixedFooter>
</Form>
</ScreenWrapper>
);
}
Expand Down

0 comments on commit 2376b77

Please sign in to comment.