diff --git a/src/ROUTES.js b/src/ROUTES.js
index 016c636f5bd2..74f3ba233bdf 100644
--- a/src/ROUTES.js
+++ b/src/ROUTES.js
@@ -14,6 +14,7 @@ const IOU_REQUEST_CURRENCY = `${IOU_REQUEST}/currency`;
const IOU_BILL_CURRENCY = `${IOU_BILL}/currency`;
const IOU_SEND_CURRENCY = `${IOU_SEND}/currency`;
const SETTINGS_PERSONAL_DETAILS = 'settings/profile/personal-details';
+const SETTINGS_CONTACT_METHODS = 'settings/profile/contact-methods';
export default {
BANK_ACCOUNT: 'bank-account',
@@ -49,6 +50,7 @@ export default {
SETTINGS_PERSONAL_DETAILS_LEGAL_NAME: `${SETTINGS_PERSONAL_DETAILS}/legal-name`,
SETTINGS_PERSONAL_DETAILS_DATE_OF_BIRTH: `${SETTINGS_PERSONAL_DETAILS}/date-of-birth`,
SETTINGS_PERSONAL_DETAILS_ADDRESS: `${SETTINGS_PERSONAL_DETAILS}/address`,
+ SETTINGS_CONTACT_METHODS,
NEW_GROUP: 'new/group',
NEW_CHAT: 'new/chat',
REPORT,
diff --git a/src/languages/en.js b/src/languages/en.js
index ad9310d9dcd1..1e254c64f53e 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -339,6 +339,10 @@ export default {
pronouns: 'Pronouns',
isShownOnProfile: 'Your pronouns are shown on your profile.',
},
+ contacts: {
+ contactMethod: 'Contact method',
+ contactMethods: 'Contact methods',
+ },
pronouns: {
coCos: 'Co / Cos',
eEyEmEir: 'E / Ey / Em / Eir',
diff --git a/src/languages/es.js b/src/languages/es.js
index e299f3a7db0f..0ecabf17c462 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -339,6 +339,10 @@ export default {
pronouns: 'Pronombres',
isShownOnProfile: 'Tus pronombres se muestran en tu perfil.',
},
+ contacts: {
+ contactMethod: 'Método de contacto',
+ contactMethods: 'Métodos de contacto',
+ },
pronouns: {
coCos: 'Co / Cos',
eEyEmEir: 'E / Ey / Em / Eir',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
index 607ee566c6cd..07c67bec110e 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
@@ -275,7 +275,14 @@ const SettingsModalStackNavigator = createModalStackNavigator([
},
{
getComponent: () => {
- const SettingsAddSecondaryLoginPage = require('../../../pages/settings/AddSecondaryLoginPage').default;
+ const SettingsContactMethodsPage = require('../../../pages/settings/Profile/Contacts/ContactMethodsPage').default;
+ return SettingsContactMethodsPage;
+ },
+ name: 'Settings_ContactMethods',
+ },
+ {
+ getComponent: () => {
+ const SettingsAddSecondaryLoginPage = require('../../../pages/settings/Profile/Contacts/AddSecondaryLoginPage').default;
return SettingsAddSecondaryLoginPage;
},
name: 'Settings_Add_Secondary_Login',
diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js
index 12b31245caf0..361655c31439 100644
--- a/src/libs/Navigation/linkingConfig.js
+++ b/src/libs/Navigation/linkingConfig.js
@@ -120,6 +120,10 @@ export default {
path: ROUTES.SETTINGS_APP_DOWNLOAD_LINKS,
exact: true,
},
+ Settings_ContactMethods: {
+ path: ROUTES.SETTINGS_CONTACT_METHODS,
+ exact: true,
+ },
Settings_Add_Secondary_Login: {
path: ROUTES.SETTINGS_ADD_LOGIN,
},
diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js
index a74a7350e06a..e9f4bcf6cb24 100644
--- a/src/libs/actions/User.js
+++ b/src/libs/actions/User.js
@@ -141,7 +141,7 @@ function setSecondaryLoginAndNavigate(login, password) {
}).then((response) => {
if (response.jsonCode === 200) {
Onyx.set(ONYXKEYS.LOGIN_LIST, response.loginList);
- Navigation.navigate(ROUTES.SETTINGS_PROFILE);
+ Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS);
return;
}
diff --git a/src/pages/settings/AddSecondaryLoginPage.js b/src/pages/settings/Profile/Contacts/AddSecondaryLoginPage.js
similarity index 86%
rename from src/pages/settings/AddSecondaryLoginPage.js
rename to src/pages/settings/Profile/Contacts/AddSecondaryLoginPage.js
index 982736ea1186..db375e6ba80e 100755
--- a/src/pages/settings/AddSecondaryLoginPage.js
+++ b/src/pages/settings/Profile/Contacts/AddSecondaryLoginPage.js
@@ -4,22 +4,22 @@ import PropTypes from 'prop-types';
import {View, ScrollView} from 'react-native';
import _ from 'underscore';
import Str from 'expensify-common/lib/str';
-import HeaderWithCloseButton from '../../components/HeaderWithCloseButton';
-import Navigation from '../../libs/Navigation/Navigation';
-import ScreenWrapper from '../../components/ScreenWrapper';
-import Text from '../../components/Text';
-import styles from '../../styles/styles';
-import * as User from '../../libs/actions/User';
-import ONYXKEYS from '../../ONYXKEYS';
-import Button from '../../components/Button';
-import ROUTES from '../../ROUTES';
-import CONST from '../../CONST';
-import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
-import compose from '../../libs/compose';
-import FixedFooter from '../../components/FixedFooter';
-import TextInput from '../../components/TextInput';
-import userPropTypes from './userPropTypes';
-import * as LoginUtils from '../../libs/LoginUtils';
+import HeaderWithCloseButton from '../../../../components/HeaderWithCloseButton';
+import Navigation from '../../../../libs/Navigation/Navigation';
+import ScreenWrapper from '../../../../components/ScreenWrapper';
+import Text from '../../../../components/Text';
+import styles from '../../../../styles/styles';
+import * as User from '../../../../libs/actions/User';
+import ONYXKEYS from '../../../../ONYXKEYS';
+import Button from '../../../../components/Button';
+import ROUTES from '../../../../ROUTES';
+import CONST from '../../../../CONST';
+import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize';
+import compose from '../../../../libs/compose';
+import FixedFooter from '../../../../components/FixedFooter';
+import TextInput from '../../../../components/TextInput';
+import userPropTypes from '../../userPropTypes';
+import * as LoginUtils from '../../../../libs/LoginUtils';
const propTypes = {
/* Onyx Props */
@@ -104,7 +104,7 @@ class AddSecondaryLoginPage extends Component {
? 'addSecondaryLoginPage.addPhoneNumber'
: 'addSecondaryLoginPage.addEmailAddress')}
shouldShowBackButton
- onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_PROFILE)}
+ onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS)}
onCloseButtonPress={() => Navigation.dismissModal()}
/>
{/* We use keyboardShouldPersistTaps="handled" to prevent the keyboard from being hidden when switching focus on input fields */}
diff --git a/src/pages/settings/Profile/Contacts/ContactMethodsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodsPage.js
new file mode 100644
index 000000000000..edb998047c11
--- /dev/null
+++ b/src/pages/settings/Profile/Contacts/ContactMethodsPage.js
@@ -0,0 +1,138 @@
+import Str from 'expensify-common/lib/str';
+import lodashGet from 'lodash/get';
+import PropTypes from 'prop-types';
+import React, {Component} from 'react';
+import {ScrollView} from 'react-native-gesture-handler';
+import {withOnyx} from 'react-native-onyx';
+import _ from 'underscore';
+import HeaderWithCloseButton from '../../../../components/HeaderWithCloseButton';
+import ScreenWrapper from '../../../../components/ScreenWrapper';
+import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '../../../../components/withCurrentUserPersonalDetails';
+import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize';
+import CONST from '../../../../CONST';
+import compose from '../../../../libs/compose';
+import Navigation from '../../../../libs/Navigation/Navigation';
+import ONYXKEYS from '../../../../ONYXKEYS';
+import ROUTES from '../../../../ROUTES';
+import LoginField from './LoginField';
+
+const propTypes = {
+ /* Onyx Props */
+
+ /** Login list for the user that is signed in */
+ loginList: PropTypes.shape({
+ /** Value of partner name */
+ partnerName: PropTypes.string,
+
+ /** Phone/Email associated with user */
+ partnerUserID: PropTypes.string,
+
+ /** Date of when login was validated */
+ validatedDate: PropTypes.string,
+ }),
+
+ ...withLocalizePropTypes,
+ ...withCurrentUserPersonalDetailsPropTypes,
+};
+
+const defaultProps = {
+ loginList: {},
+ ...withCurrentUserPersonalDetailsDefaultProps,
+};
+
+class ContactMethodsPage extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ logins: this.getLogins(),
+ };
+
+ this.getLogins = this.getLogins.bind(this);
+ }
+
+ componentDidUpdate(prevProps) {
+ let stateToUpdate = {};
+
+ // Recalculate logins if loginList has changed
+ if (_.keys(this.props.loginList).length !== _.keys(prevProps.loginList).length) {
+ stateToUpdate = {logins: this.getLogins()};
+ }
+
+ if (_.isEmpty(stateToUpdate)) {
+ return;
+ }
+
+ // eslint-disable-next-line react/no-did-update-set-state
+ this.setState(stateToUpdate);
+ }
+
+ /**
+ * Get the most validated login of each type
+ *
+ * @returns {Object}
+ */
+ getLogins() {
+ return _.reduce(_.values(this.props.loginList), (logins, currentLogin) => {
+ const type = Str.isSMSLogin(currentLogin.partnerUserID) ? CONST.LOGIN_TYPE.PHONE : CONST.LOGIN_TYPE.EMAIL;
+ const login = Str.removeSMSDomain(currentLogin.partnerUserID);
+
+ // If there's already a login type that's validated and/or currentLogin isn't valid then return early
+ if ((login !== lodashGet(this.props.currentUserPersonalDetails, 'login')) && !_.isEmpty(logins[type])
+ && (logins[type].validatedDate || !currentLogin.validatedDate)) {
+ return logins;
+ }
+ return {
+ ...logins,
+ [type]: {
+ ...currentLogin,
+ type,
+ partnerUserID: Str.removeSMSDomain(currentLogin.partnerUserID),
+ },
+ };
+ }, {
+ phone: {},
+ email: {},
+ });
+ }
+
+ render() {
+ return (
+
+ Navigation.navigate(ROUTES.SETTINGS_PROFILE)}
+ onCloseButtonPress={() => Navigation.dismissModal(true)}
+ />
+
+
+
+
+
+ );
+ }
+}
+
+ContactMethodsPage.propTypes = propTypes;
+ContactMethodsPage.defaultProps = defaultProps;
+
+export default compose(
+ withLocalize,
+ withCurrentUserPersonalDetails,
+ withOnyx({
+ loginList: {
+ key: ONYXKEYS.LOGIN_LIST,
+ },
+ }),
+)(ContactMethodsPage);
diff --git a/src/pages/settings/Profile/LoginField.js b/src/pages/settings/Profile/Contacts/LoginField.js
similarity index 87%
rename from src/pages/settings/Profile/LoginField.js
rename to src/pages/settings/Profile/Contacts/LoginField.js
index 055000a045b9..1fff1838ba9c 100755
--- a/src/pages/settings/Profile/LoginField.js
+++ b/src/pages/settings/Profile/Contacts/LoginField.js
@@ -1,18 +1,18 @@
import React, {Component} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
-import Text from '../../../components/Text';
-import styles from '../../../styles/styles';
-import themeColors from '../../../styles/themes/default';
-import * as Expensicons from '../../../components/Icon/Expensicons';
-import Icon from '../../../components/Icon';
-import ROUTES from '../../../ROUTES';
-import CONST from '../../../CONST';
-import Navigation from '../../../libs/Navigation/Navigation';
-import * as User from '../../../libs/actions/User';
-import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
-import Button from '../../../components/Button';
-import MenuItemWithTopDescription from '../../../components/MenuItemWithTopDescription';
+import Text from '../../../../components/Text';
+import styles from '../../../../styles/styles';
+import themeColors from '../../../../styles/themes/default';
+import * as Expensicons from '../../../../components/Icon/Expensicons';
+import Icon from '../../../../components/Icon';
+import ROUTES from '../../../../ROUTES';
+import CONST from '../../../../CONST';
+import Navigation from '../../../../libs/Navigation/Navigation';
+import * as User from '../../../../libs/actions/User';
+import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize';
+import Button from '../../../../components/Button';
+import MenuItemWithTopDescription from '../../../../components/MenuItemWithTopDescription';
const propTypes = {
/** Label to display on login form */
diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js
index 3af2527a7b3f..6672198dc7db 100755
--- a/src/pages/settings/Profile/ProfilePage.js
+++ b/src/pages/settings/Profile/ProfilePage.js
@@ -1,10 +1,8 @@
import Str from 'expensify-common/lib/str';
import lodashGet from 'lodash/get';
-import PropTypes from 'prop-types';
-import React, {Component} from 'react';
+import React from 'react';
import {View} from 'react-native';
import {ScrollView} from 'react-native-gesture-handler';
-import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import AvatarWithImagePicker from '../../../components/AvatarWithImagePicker';
import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton';
@@ -19,189 +17,102 @@ import * as PersonalDetails from '../../../libs/actions/PersonalDetails';
import compose from '../../../libs/compose';
import Navigation from '../../../libs/Navigation/Navigation';
import * as ReportUtils from '../../../libs/ReportUtils';
-import ONYXKEYS from '../../../ONYXKEYS';
import ROUTES from '../../../ROUTES';
import styles from '../../../styles/styles';
-import LoginField from './LoginField';
import * as Expensicons from '../../../components/Icon/Expensicons';
const propTypes = {
- /* Onyx Props */
-
- /** Login list for the user that is signed in */
- loginList: PropTypes.shape({
- /** Value of partner name */
- partnerName: PropTypes.string,
-
- /** Phone/Email associated with user */
- partnerUserID: PropTypes.string,
-
- /** Date of when login was validated */
- validatedDate: PropTypes.string,
- }),
-
...withLocalizePropTypes,
...withCurrentUserPersonalDetailsPropTypes,
};
const defaultProps = {
- loginList: {},
...withCurrentUserPersonalDetailsDefaultProps,
};
-class ProfilePage extends Component {
- constructor(props) {
- super(props);
-
- this.defaultAvatar = ReportUtils.getDefaultAvatar(this.props.currentUserPersonalDetails.login);
- this.avatar = {uri: lodashGet(this.props.currentUserPersonalDetails, 'avatar') || this.defaultAvatar};
- this.state = {
- logins: this.getLogins(),
- };
-
- this.getLogins = this.getLogins.bind(this);
- }
-
- componentDidUpdate(prevProps) {
- let stateToUpdate = {};
-
- // Recalculate logins if loginList has changed
- if (_.keys(this.props.loginList).length !== _.keys(prevProps.loginList).length) {
- stateToUpdate = {...stateToUpdate, logins: this.getLogins()};
- }
-
- if (_.isEmpty(stateToUpdate)) {
- return;
- }
-
- // eslint-disable-next-line react/no-did-update-set-state
- this.setState(stateToUpdate);
- }
-
- getPronouns() {
- let pronounsKey = lodashGet(this.props.currentUserPersonalDetails, 'pronouns', '');
+const ProfilePage = (props) => {
+ const getPronouns = () => {
+ let pronounsKey = lodashGet(props.currentUserPersonalDetails, 'pronouns', '');
if (pronounsKey.startsWith(CONST.PRONOUNS.PREFIX)) {
pronounsKey = pronounsKey.slice(CONST.PRONOUNS.PREFIX.length);
}
- return lodashGet(this.props.translate('pronouns'), pronounsKey, this.props.translate('profilePage.selectYourPronouns'));
- }
-
- /**
- * Get the most validated login of each type
- *
- * @returns {Object}
- */
- getLogins() {
- return _.reduce(_.values(this.props.loginList), (logins, currentLogin) => {
- const type = Str.isSMSLogin(currentLogin.partnerUserID) ? CONST.LOGIN_TYPE.PHONE : CONST.LOGIN_TYPE.EMAIL;
- const login = Str.removeSMSDomain(currentLogin.partnerUserID);
-
- // If there's already a login type that's validated and/or currentLogin isn't valid then return early
- if ((login !== lodashGet(this.props.currentUserPersonalDetails, 'login')) && !_.isEmpty(logins[type])
- && (logins[type].validatedDate || !currentLogin.validatedDate)) {
- return logins;
- }
- return {
- ...logins,
- [type]: {
- ...currentLogin,
- type,
- partnerUserID: Str.removeSMSDomain(currentLogin.partnerUserID),
- },
- };
- }, {
- phone: {},
- email: {},
- });
- }
-
- render() {
- const currentUserDetails = this.props.currentUserPersonalDetails || {};
- const profileSettingsOptions = [
- {
- description: this.props.translate('displayNamePage.headerTitle'),
- title: lodashGet(currentUserDetails, 'displayName', ''),
- pageRoute: ROUTES.SETTINGS_DISPLAY_NAME,
- },
- {
- description: this.props.translate('pronounsPage.pronouns'),
- title: this.getPronouns(),
- pageRoute: ROUTES.SETTINGS_PRONOUNS,
- },
- {
- description: this.props.translate('timezonePage.timezone'),
- title: `${lodashGet(currentUserDetails, 'timezone.selected', '')}`,
- pageRoute: ROUTES.SETTINGS_TIMEZONE,
- },
- ];
- return (
-
- Navigation.navigate(ROUTES.SETTINGS)}
- onCloseButtonPress={() => Navigation.dismissModal(true)}
- />
-
-
-
-
-
- {_.map(profileSettingsOptions, (detail, index) => (
- Navigation.navigate(detail.pageRoute)}
- />
- ))}
-
-
-
-
+
+ );
+};
ProfilePage.propTypes = propTypes;
ProfilePage.defaultProps = defaultProps;
+ProfilePage.displayName = 'ProfilePage';
export default compose(
withLocalize,
withCurrentUserPersonalDetails,
- withOnyx({
- loginList: {
- key: ONYXKEYS.LOGIN_LIST,
- },
- }),
)(ProfilePage);