From 0306bebd1916eef73085dc5f05178a2bb3a23b14 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 15 Oct 2024 11:11:34 +0530 Subject: [PATCH 01/22] add phoneNumber RHP to private details page --- src/ROUTES.ts | 1 + src/SCREENS.ts | 1 + .../API/parameters/UpdatePhoneNumberParams.ts | 5 + src/libs/API/types.ts | 2 + .../ModalStackNavigators/index.tsx | 1 + .../CENTRAL_PANE_TO_RHP_MAPPING.ts | 1 + src/libs/Navigation/linkingConfig/config.ts | 4 + src/libs/actions/PersonalDetails.ts | 17 ++++ .../PersonalDetails/PhoneNumberPage.tsx | 94 +++++++++++++++++++ src/pages/settings/Profile/ProfilePage.tsx | 6 +- 10 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/libs/API/parameters/UpdatePhoneNumberParams.ts create mode 100644 src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 07a772aa9390..d1fe33795d71 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -209,6 +209,7 @@ const ROUTES = { }, SETTINGS_LEGAL_NAME: 'settings/profile/legal-name', SETTINGS_DATE_OF_BIRTH: 'settings/profile/date-of-birth', + SETTINGS_PHONE_NUMBER: 'settings/profile/phone', SETTINGS_ADDRESS: 'settings/profile/address', SETTINGS_ADDRESS_COUNTRY: { route: 'settings/profile/address/country', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 09cfbca3de9b..df168b3cf81c 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -85,6 +85,7 @@ const SCREENS = { TIMEZONE_SELECT: 'Settings_Timezone_Select', LEGAL_NAME: 'Settings_LegalName', DATE_OF_BIRTH: 'Settings_DateOfBirth', + PHONE_NUMBER: 'Settings_PhoneNumber', ADDRESS: 'Settings_Address', ADDRESS_COUNTRY: 'Settings_Address_Country', ADDRESS_STATE: 'Settings_Address_State', diff --git a/src/libs/API/parameters/UpdatePhoneNumberParams.ts b/src/libs/API/parameters/UpdatePhoneNumberParams.ts new file mode 100644 index 000000000000..683ecb16be13 --- /dev/null +++ b/src/libs/API/parameters/UpdatePhoneNumberParams.ts @@ -0,0 +1,5 @@ +type UpdatePhoneNumberParams = { + phoneNumber?: string; +}; + +export default UpdatePhoneNumberParams; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index b6f1d7f5609e..1ca75644fa22 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -57,6 +57,8 @@ const WRITE_COMMANDS = { UPDATE_DISPLAY_NAME: 'UpdateDisplayName', UPDATE_LEGAL_NAME: 'UpdateLegalName', UPDATE_DATE_OF_BIRTH: 'UpdateDateOfBirth', + // Update the command after the exact endpoint is known + UPDATE_PHONE_NUMBER: 'SetPrivatePersonalDetails', UPDATE_HOME_ADDRESS: 'UpdateHomeAddress', UPDATE_POLICY_ADDRESS: 'SetPolicyAddress', UPDATE_AUTOMATIC_TIMEZONE: 'UpdateAutomaticTimezone', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 3d1b4e3d95b6..12312c346fc4 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -199,6 +199,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/settings/Profile/TimezoneSelectPage').default, [SCREENS.SETTINGS.PROFILE.LEGAL_NAME]: () => require('../../../../pages/settings/Profile/PersonalDetails/LegalNamePage').default, [SCREENS.SETTINGS.PROFILE.DATE_OF_BIRTH]: () => require('../../../../pages/settings/Profile/PersonalDetails/DateOfBirthPage').default, + [SCREENS.SETTINGS.PROFILE.PHONE_NUMBER]: () => require('../../../../pages/settings/Profile/PersonalDetails/PhoneNumberPage').default, [SCREENS.SETTINGS.PROFILE.ADDRESS]: () => require('../../../../pages/settings/Profile/PersonalDetails/PersonalAddressPage').default, [SCREENS.SETTINGS.PROFILE.ADDRESS_COUNTRY]: () => require('../../../../pages/settings/Profile/PersonalDetails/CountrySelectionPage').default, [SCREENS.SETTINGS.PROFILE.ADDRESS_STATE]: () => require('../../../../pages/settings/Profile/PersonalDetails/StateSelectionPage').default, diff --git a/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts b/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts index cec9e86c5be4..86847be201fd 100755 --- a/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts @@ -17,6 +17,7 @@ const CENTRAL_PANE_TO_RHP_MAPPING: Partial> = SCREENS.SETTINGS.PROFILE.TIMEZONE_SELECT, SCREENS.SETTINGS.PROFILE.LEGAL_NAME, SCREENS.SETTINGS.PROFILE.DATE_OF_BIRTH, + SCREENS.SETTINGS.PROFILE.PHONE_NUMBER, SCREENS.SETTINGS.PROFILE.ADDRESS, SCREENS.SETTINGS.PROFILE.ADDRESS_COUNTRY, SCREENS.SETTINGS.SHARE_CODE, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 45d93cd8f57d..55042404ca3f 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -268,6 +268,10 @@ const config: LinkingOptions['config'] = { path: ROUTES.SETTINGS_LEGAL_NAME, exact: true, }, + [SCREENS.SETTINGS.PROFILE.PHONE_NUMBER]: { + path: ROUTES.SETTINGS_PHONE_NUMBER, + exact: true, + }, [SCREENS.SETTINGS.PROFILE.DATE_OF_BIRTH]: { path: ROUTES.SETTINGS_DATE_OF_BIRTH, exact: true, diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index 7fb1c9a4cc7f..d2f66d9099bf 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -14,6 +14,7 @@ import type { UpdateSelectedTimezoneParams, UpdateUserAvatarParams, } from '@libs/API/parameters'; +import UpdatePhoneNumberParams from '@libs/API/parameters/UpdatePhoneNumberParams'; import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import type {CustomRNImageManipulatorResult} from '@libs/cropOrRotateImage/types'; import DateUtils from '@libs/DateUtils'; @@ -157,6 +158,21 @@ function updateDateOfBirth({dob}: DateOfBirthForm) { Navigation.goBack(); } +function updatePhoneNumber(phoneNumber: string) { + const parameters: UpdatePhoneNumberParams = {phoneNumber}; + API.write(WRITE_COMMANDS.UPDATE_PHONE_NUMBER, parameters, { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS, + value: { + phoneNumber, + }, + }, + ], + }); +} + function updateAddress(street: string, street2: string, city: string, state: string, zip: string, country: Country | '') { const parameters: UpdateHomeAddressParams = { homeAddressStreet: street, @@ -481,6 +497,7 @@ export { setDisplayName, updateDisplayName, updateLegalName, + updatePhoneNumber, updatePronouns, updateSelectedTimezone, updatePersonalDetailsAndShipExpensifyCard, diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx new file mode 100644 index 000000000000..09ff99125f3d --- /dev/null +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -0,0 +1,94 @@ +import {Str} from 'expensify-common'; +import React, {useCallback} from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; +import InputWrapper from '@components/Form/InputWrapper'; +import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; +import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import TextInput from '@components/TextInput'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as LoginUtils from '@libs/LoginUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import * as PhoneNumberUtils from '@libs/PhoneNumber'; +import * as ValidationUtils from '@libs/ValidationUtils'; +import * as PersonalDetails from '@userActions/PersonalDetails'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import INPUT_IDS from '@src/types/form/PersonalDetailsForm'; +import type {PrivatePersonalDetails} from '@src/types/onyx'; + +function PhoneNumberPage() { + const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); + const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {initialValue: true}); + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const phoneNumber = privatePersonalDetails?.phoneNumber ?? ''; + console.log('phoneNumber', phoneNumber); + + const updatePhoneNumber = (values: PrivatePersonalDetails) => { + PersonalDetails.updatePhoneNumber(values?.phoneNumber ?? ''); + Navigation.goBack(); + }; + + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors: FormInputErrors = {}; + if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.PHONE_NUMBER])) { + errors[INPUT_IDS.PHONE_NUMBER] = translate('common.error.fieldRequired'); + } + const phoneNumber = LoginUtils.appendCountryCode(values[INPUT_IDS.PHONE_NUMBER]); + const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(phoneNumber); + if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumber.slice(0))) { + errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber'); + } + return errors; + }, + [translate], + ); + + return ( + + Navigation.goBack()} + /> + {isLoadingApp ? ( + + ) : ( + + + + + + )} + + ); +} + +PhoneNumberPage.displayName = 'PhoneNumberPage'; + +export default PhoneNumberPage; diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index f42be1385ecf..4f87330f7d0d 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -55,7 +55,6 @@ function ProfilePage() { const emojiCode = currentUserPersonalDetails?.status?.emojiCode ?? ''; const privateDetails = privatePersonalDetails ?? {}; const legalName = `${privateDetails.legalFirstName ?? ''} ${privateDetails.legalLastName ?? ''}`.trim(); - const publicOptions = [ { description: translate('displayNamePage.headerTitle'), @@ -96,6 +95,11 @@ function ProfilePage() { title: privateDetails.dob ?? '', pageRoute: ROUTES.SETTINGS_DATE_OF_BIRTH, }, + { + description: translate('common.phoneNumber'), + title: privateDetails.phoneNumber ?? '', + pageRoute: ROUTES.SETTINGS_PHONE_NUMBER, + }, { description: translate('privatePersonalDetails.address'), title: PersonalDetailsUtils.getFormattedAddress(privateDetails), From f90cc5d8e12c35d21982e966290399772a5cc902 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 15 Oct 2024 11:25:55 +0530 Subject: [PATCH 02/22] fix lint and import UpdateLegalNameParams as type --- src/libs/API/parameters/index.ts | 1 + src/libs/actions/PersonalDetails.ts | 2 +- .../settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 7 +++---- src/pages/settings/Profile/PersonalDetails/test.md | 0 src/pages/settings/Profile/ProfilePage.tsx | 1 + 5 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 src/pages/settings/Profile/PersonalDetails/test.md diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index ddf10a138725..c47d46e8a950 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -72,6 +72,7 @@ export type {default as UpdateGroupChatMemberRolesParams} from './UpdateGroupCha export type {default as UpdateHomeAddressParams} from './UpdateHomeAddressParams'; export type {default as UpdatePolicyAddressParams} from './UpdatePolicyAddressParams'; export type {default as UpdateLegalNameParams} from './UpdateLegalNameParams'; +export type {default as UpdatePhoneNumberParams} from './UpdatePhoneNumberParams'; export type {default as UpdateNewsletterSubscriptionParams} from './UpdateNewsletterSubscriptionParams'; export type {default as UpdatePersonalInformationForBankAccountParams} from './UpdatePersonalInformationForBankAccountParams'; export type {default as UpdatePreferredEmojiSkinToneParams} from './UpdatePreferredEmojiSkinToneParams'; diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index d2f66d9099bf..b35d05a71e3b 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -10,11 +10,11 @@ import type { UpdateDisplayNameParams, UpdateHomeAddressParams, UpdateLegalNameParams, + UpdatePhoneNumberParams, UpdatePronounsParams, UpdateSelectedTimezoneParams, UpdateUserAvatarParams, } from '@libs/API/parameters'; -import UpdatePhoneNumberParams from '@libs/API/parameters/UpdatePhoneNumberParams'; import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import type {CustomRNImageManipulatorResult} from '@libs/cropOrRotateImage/types'; import DateUtils from '@libs/DateUtils'; diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index 09ff99125f3d..5b998795d1e3 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -27,7 +27,6 @@ function PhoneNumberPage() { const styles = useThemeStyles(); const {translate} = useLocalize(); const phoneNumber = privatePersonalDetails?.phoneNumber ?? ''; - console.log('phoneNumber', phoneNumber); const updatePhoneNumber = (values: PrivatePersonalDetails) => { PersonalDetails.updatePhoneNumber(values?.phoneNumber ?? ''); @@ -40,9 +39,9 @@ function PhoneNumberPage() { if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.PHONE_NUMBER])) { errors[INPUT_IDS.PHONE_NUMBER] = translate('common.error.fieldRequired'); } - const phoneNumber = LoginUtils.appendCountryCode(values[INPUT_IDS.PHONE_NUMBER]); - const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(phoneNumber); - if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumber.slice(0))) { + const phoneNumberWithCountryCode = LoginUtils.appendCountryCode(values[INPUT_IDS.PHONE_NUMBER]); + const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(phoneNumberWithCountryCode); + if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumberWithCountryCode.slice(0))) { errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber'); } return errors; diff --git a/src/pages/settings/Profile/PersonalDetails/test.md b/src/pages/settings/Profile/PersonalDetails/test.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 4f87330f7d0d..4835d76b1219 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -55,6 +55,7 @@ function ProfilePage() { const emojiCode = currentUserPersonalDetails?.status?.emojiCode ?? ''; const privateDetails = privatePersonalDetails ?? {}; const legalName = `${privateDetails.legalFirstName ?? ''} ${privateDetails.legalLastName ?? ''}`.trim(); + const publicOptions = [ { description: translate('displayNamePage.headerTitle'), From d017a850d827208adc42d3099448819bc2bd4853 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 15 Oct 2024 11:31:42 +0530 Subject: [PATCH 03/22] Delete src/pages/settings/Profile/PersonalDetails/test.md --- src/pages/settings/Profile/PersonalDetails/test.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/pages/settings/Profile/PersonalDetails/test.md diff --git a/src/pages/settings/Profile/PersonalDetails/test.md b/src/pages/settings/Profile/PersonalDetails/test.md deleted file mode 100644 index e69de29bb2d1..000000000000 From a33bf2d75bfd1323afe312881b3bcbf692637e03 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 15 Oct 2024 11:37:17 +0530 Subject: [PATCH 04/22] update to correct api command --- src/libs/API/types.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 1ca75644fa22..24fe0c5b828e 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -57,8 +57,7 @@ const WRITE_COMMANDS = { UPDATE_DISPLAY_NAME: 'UpdateDisplayName', UPDATE_LEGAL_NAME: 'UpdateLegalName', UPDATE_DATE_OF_BIRTH: 'UpdateDateOfBirth', - // Update the command after the exact endpoint is known - UPDATE_PHONE_NUMBER: 'SetPrivatePersonalDetails', + UPDATE_PHONE_NUMBER: 'UpdatePhoneNumber', UPDATE_HOME_ADDRESS: 'UpdateHomeAddress', UPDATE_POLICY_ADDRESS: 'SetPolicyAddress', UPDATE_AUTOMATIC_TIMEZONE: 'UpdateAutomaticTimezone', From 47b3dc94ab518ca8b5a9614c0179ec8e683c525e Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 15 Oct 2024 11:43:36 +0530 Subject: [PATCH 05/22] fix typecheck, add update phone number to write command --- src/libs/API/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 24fe0c5b828e..38c76ec446ea 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -453,6 +453,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_DISPLAY_NAME]: Parameters.UpdateDisplayNameParams; [WRITE_COMMANDS.UPDATE_LEGAL_NAME]: Parameters.UpdateLegalNameParams; [WRITE_COMMANDS.UPDATE_DATE_OF_BIRTH]: Parameters.UpdateDateOfBirthParams; + [WRITE_COMMANDS.UPDATE_PHONE_NUMBER]: Parameters.UpdatePhoneNumberParams; [WRITE_COMMANDS.UPDATE_POLICY_ADDRESS]: Parameters.UpdatePolicyAddressParams; [WRITE_COMMANDS.UPDATE_HOME_ADDRESS]: Parameters.UpdateHomeAddressParams; [WRITE_COMMANDS.UPDATE_AUTOMATIC_TIMEZONE]: Parameters.UpdateAutomaticTimezoneParams; From 9446f6a79c99745111cfe43d9b21919555a73676 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Wed, 16 Oct 2024 14:07:48 +0530 Subject: [PATCH 06/22] change the input header for phone number --- .../settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index 5b998795d1e3..d044cf6f0338 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -75,8 +75,8 @@ function PhoneNumberPage() { InputComponent={TextInput} inputID={INPUT_IDS.PHONE_NUMBER} name="lfname" - label={translate('privatePersonalDetails.enterPhoneNumber')} - aria-label={translate('privatePersonalDetails.enterPhoneNumber')} + label={translate('common.phoneNumber')} + aria-label={translate('common.phoneNumber')} role={CONST.ROLE.PRESENTATION} defaultValue={phoneNumber} spellCheck={false} From 53d430aa9cf9c6696285ec5473151dd5a14e8334 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Mon, 21 Oct 2024 21:09:49 +0530 Subject: [PATCH 07/22] add BE error RBR and error field to phone number --- src/languages/en.ts | 1 + src/languages/es.ts | 1 + src/libs/actions/PersonalDetails.ts | 24 ++++++++++++++++++- .../PersonalDetails/PhoneNumberPage.tsx | 15 +++++++++--- src/pages/settings/Profile/ProfilePage.tsx | 3 ++- src/types/onyx/PrivatePersonalDetails.ts | 4 ++++ 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 6ca1cb58f9ad..a8358c700c22 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1778,6 +1778,7 @@ const translations = { dateShouldBeAfter: ({dateString}: DateShouldBeAfterParams) => `Date should be after ${dateString}.`, hasInvalidCharacter: 'Name can only include Latin characters.', incorrectZipFormat: ({zipFormat}: IncorrectZipFormatParams = {}) => `Incorrect zip code format.${zipFormat ? ` Acceptable format: ${zipFormat}` : ''}`, + invalidPhoneNumber: `Please ensure the phone number is valid (e.g. ${CONST.EXAMPLE_PHONE_NUMBER}).`, }, }, resendValidationForm: { diff --git a/src/languages/es.ts b/src/languages/es.ts index 86a3ebe7f927..988c5d9aa25f 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1778,6 +1778,7 @@ const translations = { dateShouldBeAfter: ({dateString}: DateShouldBeAfterParams) => `La fecha debe ser posterior a ${dateString}.`, incorrectZipFormat: ({zipFormat}: IncorrectZipFormatParams = {}) => `Formato de código postal incorrecto.${zipFormat ? ` Formato aceptable: ${zipFormat}` : ''}`, hasInvalidCharacter: 'El nombre sólo puede incluir caracteres latinos.', + invalidPhoneNumber: 'Asegúrese de que el número de teléfono sean válidos (p. ej. ${CONST.EXAMPLE_PHONE_NUMBER}).', }, }, resendValidationForm: { diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index b35d05a71e3b..d828a53c0064 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -18,6 +18,7 @@ import type { import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import type {CustomRNImageManipulatorResult} from '@libs/cropOrRotateImage/types'; import DateUtils from '@libs/DateUtils'; +import * as ErrorUtils from '@libs/ErrorUtils'; import * as LoginUtils from '@libs/LoginUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; @@ -158,7 +159,7 @@ function updateDateOfBirth({dob}: DateOfBirthForm) { Navigation.goBack(); } -function updatePhoneNumber(phoneNumber: string) { +function updatePhoneNumber(phoneNumber: string, currenPhoneNumber: string) { const parameters: UpdatePhoneNumberParams = {phoneNumber}; API.write(WRITE_COMMANDS.UPDATE_PHONE_NUMBER, parameters, { optimisticData: [ @@ -170,6 +171,26 @@ function updatePhoneNumber(phoneNumber: string) { }, }, ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS, + value: { + phoneNumber: currenPhoneNumber, + errorFields: { + phoneNumber: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('privatePersonalDetails.error.invalidPhoneNumber'), + }, + }, + }, + ], + }); +} + +function clearPhoneNumberError() { + Onyx.merge(ONYXKEYS.PRIVATE_PERSONAL_DETAILS, { + errorFields: { + phoneNumber: null, + }, }); } @@ -498,6 +519,7 @@ export { updateDisplayName, updateLegalName, updatePhoneNumber, + clearPhoneNumberError, updatePronouns, updateSelectedTimezone, updatePersonalDetailsAndShipExpensifyCard, diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index d044cf6f0338..fb1cce83987b 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -7,10 +7,12 @@ import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as ErrorUtils from '@libs/ErrorUtils'; import * as LoginUtils from '@libs/LoginUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as PhoneNumberUtils from '@libs/PhoneNumber'; @@ -28,8 +30,11 @@ function PhoneNumberPage() { const {translate} = useLocalize(); const phoneNumber = privatePersonalDetails?.phoneNumber ?? ''; + const validateLoginError = ErrorUtils.getEarliestErrorField(privatePersonalDetails, 'phoneNumber'); + const currenPhoneNumber = privatePersonalDetails?.phoneNumber ?? ''; + const updatePhoneNumber = (values: PrivatePersonalDetails) => { - PersonalDetails.updatePhoneNumber(values?.phoneNumber ?? ''); + PersonalDetails.updatePhoneNumber(values?.phoneNumber ?? '', currenPhoneNumber); Navigation.goBack(); }; @@ -70,7 +75,11 @@ function PhoneNumberPage() { submitButtonText={translate('common.save')} enabledWhenOffline > - + PersonalDetails.clearPhoneNumberError()} + > - + )} diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 4835d76b1219..4983de3c6668 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -40,7 +40,6 @@ function ProfilePage() { const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP); const getPronouns = (): string => { @@ -100,6 +99,7 @@ function ProfilePage() { description: translate('common.phoneNumber'), title: privateDetails.phoneNumber ?? '', pageRoute: ROUTES.SETTINGS_PHONE_NUMBER, + brickRoadIndicator: privatePersonalDetails?.errorFields?.phoneNumber ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, { description: translate('privatePersonalDetails.address'), @@ -200,6 +200,7 @@ function ProfilePage() { description={detail.description} wrapperStyle={styles.sectionMenuItemTopDescription} onPress={() => Navigation.navigate(detail.pageRoute)} + brickRoadIndicator={detail.brickRoadIndicator} /> ))} diff --git a/src/types/onyx/PrivatePersonalDetails.ts b/src/types/onyx/PrivatePersonalDetails.ts index 1635c610badf..1d88cd3af1ff 100644 --- a/src/types/onyx/PrivatePersonalDetails.ts +++ b/src/types/onyx/PrivatePersonalDetails.ts @@ -1,4 +1,5 @@ import type {Country} from '@src/CONST'; +import type * as OnyxCommon from './OnyxCommon'; /** User address data */ type Address = { @@ -64,6 +65,9 @@ type PrivatePersonalDetails = { /** User's home address history. The most recent address is the last item in the array */ addresses?: Address[]; + + /** Error objects keyed by field name containing errors keyed by microtime */ + errorFields?: OnyxCommon.ErrorFields; }; export default PrivatePersonalDetails; From 5f274bbf609d3866d2b8d58f23aec2d332ac9e8c Mon Sep 17 00:00:00 2001 From: Gandalf Date: Mon, 21 Oct 2024 21:12:46 +0530 Subject: [PATCH 08/22] fix eslint --- src/languages/es.ts | 2 +- src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index 988c5d9aa25f..012619d47dbb 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1778,7 +1778,7 @@ const translations = { dateShouldBeAfter: ({dateString}: DateShouldBeAfterParams) => `La fecha debe ser posterior a ${dateString}.`, incorrectZipFormat: ({zipFormat}: IncorrectZipFormatParams = {}) => `Formato de código postal incorrecto.${zipFormat ? ` Formato aceptable: ${zipFormat}` : ''}`, hasInvalidCharacter: 'El nombre sólo puede incluir caracteres latinos.', - invalidPhoneNumber: 'Asegúrese de que el número de teléfono sean válidos (p. ej. ${CONST.EXAMPLE_PHONE_NUMBER}).', + invalidPhoneNumber: `Asegúrese de que el número de teléfono sean válidos (p. ej. ${CONST.EXAMPLE_PHONE_NUMBER}).`, }, }, resendValidationForm: { diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index fb1cce83987b..d358f07be0c6 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -1,6 +1,5 @@ import {Str} from 'expensify-common'; import React, {useCallback} from 'react'; -import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; From a82ee09dc28d8d8c4f4eef0933bb005d6cb05147 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 22 Oct 2024 11:28:29 +0530 Subject: [PATCH 09/22] add top padding to error message --- src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index d358f07be0c6..b2a13b1e8fbf 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -76,7 +76,7 @@ function PhoneNumberPage() { > PersonalDetails.clearPhoneNumberError()} > Date: Tue, 22 Oct 2024 12:00:22 +0530 Subject: [PATCH 10/22] add RBR for profile settings --- src/libs/UserUtils.ts | 17 ++++++++++++++++- src/pages/settings/InitialSettingsPage.tsx | 6 ++++-- .../Profile/PersonalDetails/PhoneNumberPage.tsx | 9 +-------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 3e309fc74021..2fefa4497575 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -6,7 +6,7 @@ import * as defaultAvatars from '@components/Icon/DefaultAvatars'; import {ConciergeAvatar, NotificationsAvatar} from '@components/Icon/Expensicons'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Account, LoginList, Session} from '@src/types/onyx'; +import type {Account, LoginList, PrivatePersonalDetails, Session} from '@src/types/onyx'; import type Login from '@src/types/onyx/Login'; import type IconAsset from '@src/types/utils/IconAsset'; import hashCode from './hashCode'; @@ -78,9 +78,23 @@ function getLoginListBrickRoadIndicator(loginList: OnyxEntry): LoginL if (hasLoginListInfo(loginList)) { return CONST.BRICK_ROAD_INDICATOR_STATUS.INFO; } + return undefined; } +function getProfilePageBrickRoadIndicator(loginList: OnyxEntry, privatePersoanlDetails: OnyxEntry): LoginListIndicator { + const hasPhoneNumberError = !!privatePersoanlDetails?.errorFields?.phoneNumber; + if (hasLoginListError(loginList) || hasPhoneNumberError) { + return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; + } + if (hasLoginListInfo(loginList)) { + return CONST.BRICK_ROAD_INDICATOR_STATUS.INFO; + } + + return undefined; +} + + /** * Hashes provided string and returns a value between [0, range) */ @@ -240,6 +254,7 @@ export { getDefaultAvatarURL, getFullSizeAvatar, getLoginListBrickRoadIndicator, + getProfilePageBrickRoadIndicator, getSecondaryPhoneLogin, getSmallSizeAvatar, hasLoginListError, diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 48873a342a6f..348822f0d1f0 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -79,6 +79,8 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); + const [privatePersoanlDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); + console.log("privatePersoanlDetails", privatePersoanlDetails) const network = useNetwork(); const theme = useTheme(); @@ -125,7 +127,7 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr * @returns object with translationKey, style and items for the account section */ const accountMenuItemsData: Menu = useMemo(() => { - const profileBrickRoadIndicator = UserUtils.getLoginListBrickRoadIndicator(loginList); + const profileBrickRoadIndicator = UserUtils.getProfilePageBrickRoadIndicator(loginList, privatePersoanlDetails); const paymentCardList = fundList; const defaultMenu: Menu = { sectionStyle: styles.accountSettingsSectionContainer, @@ -160,7 +162,7 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr }; return defaultMenu; - }, [loginList, fundList, styles.accountSettingsSectionContainer, bankAccountList, userWallet?.errors, walletTerms?.errors]); + }, [loginList, fundList, styles.accountSettingsSectionContainer, bankAccountList, userWallet?.errors, walletTerms?.errors, privatePersoanlDetails]); /** * Retuns a list of menu items data for workspace section diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index b2a13b1e8fbf..a81aafc2a048 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -40,14 +40,7 @@ function PhoneNumberPage() { const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { const errors: FormInputErrors = {}; - if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.PHONE_NUMBER])) { - errors[INPUT_IDS.PHONE_NUMBER] = translate('common.error.fieldRequired'); - } - const phoneNumberWithCountryCode = LoginUtils.appendCountryCode(values[INPUT_IDS.PHONE_NUMBER]); - const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(phoneNumberWithCountryCode); - if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumberWithCountryCode.slice(0))) { - errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber'); - } + return errors; }, [translate], From 23b9bc996a79102540be471e0f6156f6c5e2328f Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 22 Oct 2024 12:06:51 +0530 Subject: [PATCH 11/22] add RBR to Avatar Indicator --- src/CONST.ts | 3 ++- src/hooks/useIndicatorStatus.ts | 2 ++ src/libs/UserUtils.ts | 1 - src/pages/settings/InitialSettingsPage.tsx | 1 - 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 440f942e1244..f2eb19371a11 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5937,13 +5937,14 @@ const CONST = { HAS_POLICY_ERRORS: 'hasPolicyError', HAS_CUSTOM_UNITS_ERROR: 'hasCustomUnitsError', HAS_EMPLOYEE_LIST_ERROR: 'hasEmployeeListError', - HAS_SYNC_ERRORS: 'hasSyncError', + HASINDICATOR_STATUS_SYNC_ERRORS: 'hasSyncError', HAS_SUBSCRIPTION_ERRORS: 'hasSubscriptionError', HAS_REIMBURSEMENT_ACCOUNT_ERRORS: 'hasReimbursementAccountErrors', HAS_LOGIN_LIST_ERROR: 'hasLoginListError', HAS_WALLET_TERMS_ERRORS: 'hasWalletTermsErrors', HAS_LOGIN_LIST_INFO: 'hasLoginListInfo', HAS_SUBSCRIPTION_INFO: 'hasSubscriptionInfo', + HAS_PHONE_NUMBER_ERROR: 'hasPhoneNumberError', }, DEBUG: { diff --git a/src/hooks/useIndicatorStatus.ts b/src/hooks/useIndicatorStatus.ts index b026bc52fd7b..bba394a828d1 100644 --- a/src/hooks/useIndicatorStatus.ts +++ b/src/hooks/useIndicatorStatus.ts @@ -28,6 +28,7 @@ function useIndicatorStatus(): IndicatorStatusResult { const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET); const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); + const [privatePersoanlDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); // If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and // those should be cleaned out before doing any error checking @@ -57,6 +58,7 @@ function useIndicatorStatus(): IndicatorStatusResult { [CONST.INDICATOR_STATUS.HAS_LOGIN_LIST_ERROR]: !!loginList && UserUtils.hasLoginListError(loginList), // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead) [CONST.INDICATOR_STATUS.HAS_WALLET_TERMS_ERRORS]: Object.keys(walletTerms?.errors ?? {}).length > 0 && !walletTerms?.chatReportID, + [CONST.INDICATOR_STATUS.HAS_PHONE_NUMBER_ERROR]: !!privatePersoanlDetails?.errorFields?.phoneNumber ?? undefined, }; const infoChecking: Partial> = { diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 2fefa4497575..9648ce2426f6 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -94,7 +94,6 @@ function getProfilePageBrickRoadIndicator(loginList: OnyxEntry, priva return undefined; } - /** * Hashes provided string and returns a value between [0, range) */ diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 605d33eee94a..78268bcb931b 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -81,7 +81,6 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); const [privatePersoanlDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); - console.log("privatePersoanlDetails", privatePersoanlDetails) const network = useNetwork(); const theme = useTheme(); From 4ea40bea0294a75252bf25e52ebf69f5e7f4668b Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 22 Oct 2024 12:07:38 +0530 Subject: [PATCH 12/22] pull up validation for phone number --- .../settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index a81aafc2a048..b2a13b1e8fbf 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -40,7 +40,14 @@ function PhoneNumberPage() { const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { const errors: FormInputErrors = {}; - + if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.PHONE_NUMBER])) { + errors[INPUT_IDS.PHONE_NUMBER] = translate('common.error.fieldRequired'); + } + const phoneNumberWithCountryCode = LoginUtils.appendCountryCode(values[INPUT_IDS.PHONE_NUMBER]); + const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(phoneNumberWithCountryCode); + if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumberWithCountryCode.slice(0))) { + errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber'); + } return errors; }, [translate], From 2ff3e62291393d640b926afe2306bd2889ea17b6 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 22 Oct 2024 12:16:53 +0530 Subject: [PATCH 13/22] Apply suggestions from code review --- src/CONST.ts | 2 +- src/libs/UserUtils.ts | 4 ++++ src/pages/settings/Profile/ProfilePage.tsx | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index f2eb19371a11..be0b07d5145d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5937,7 +5937,7 @@ const CONST = { HAS_POLICY_ERRORS: 'hasPolicyError', HAS_CUSTOM_UNITS_ERROR: 'hasCustomUnitsError', HAS_EMPLOYEE_LIST_ERROR: 'hasEmployeeListError', - HASINDICATOR_STATUS_SYNC_ERRORS: 'hasSyncError', + HAS_SYNC_ERRORS: 'hasSyncError', HAS_SUBSCRIPTION_ERRORS: 'hasSubscriptionError', HAS_REIMBURSEMENT_ACCOUNT_ERRORS: 'hasReimbursementAccountErrors', HAS_LOGIN_LIST_ERROR: 'hasLoginListError', diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 9648ce2426f6..700ec2340f7e 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -82,6 +82,10 @@ function getLoginListBrickRoadIndicator(loginList: OnyxEntry): LoginL return undefined; } +/** + * Gets the appropriate brick road indicator status for the Profile section. + * Error status is higher priority, so we check for that first. + */ function getProfilePageBrickRoadIndicator(loginList: OnyxEntry, privatePersoanlDetails: OnyxEntry): LoginListIndicator { const hasPhoneNumberError = !!privatePersoanlDetails?.errorFields?.phoneNumber; if (hasLoginListError(loginList) || hasPhoneNumberError) { diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 4983de3c6668..0d57c3439835 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -40,6 +40,7 @@ function ProfilePage() { const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP); const getPronouns = (): string => { From c30c194db69cc5dded92ec814d23be95c8e82b1b Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 22 Oct 2024 12:18:45 +0530 Subject: [PATCH 14/22] fix prettier --- src/pages/settings/Profile/ProfilePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 0d57c3439835..faa399598d05 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -40,7 +40,7 @@ function ProfilePage() { const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - + const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP); const getPronouns = (): string => { From 96355c141a7a7bde7176022c5ff65e2181b06727 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Tue, 22 Oct 2024 17:49:28 +0530 Subject: [PATCH 15/22] implement suggestions --- .../Profile/PersonalDetails/PhoneNumberPage.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index b2a13b1e8fbf..c3b574404593 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -33,7 +33,16 @@ function PhoneNumberPage() { const currenPhoneNumber = privatePersonalDetails?.phoneNumber ?? ''; const updatePhoneNumber = (values: PrivatePersonalDetails) => { - PersonalDetails.updatePhoneNumber(values?.phoneNumber ?? '', currenPhoneNumber); + // Clear the error when the user tries to submit the form + if (validateLoginError) { + PersonalDetails.clearPhoneNumberError(); + } + + // Only call the API if the user has changed their phone number + if (phoneNumber !== values?.phoneNumber) { + PersonalDetails.updatePhoneNumber(values?.phoneNumber ?? '', currenPhoneNumber); + } + Navigation.goBack(); }; From 4414c13c3f23311a7c317b3b452d13f0c8fe00ab Mon Sep 17 00:00:00 2001 From: Gandalf Date: Wed, 23 Oct 2024 16:22:24 +0530 Subject: [PATCH 16/22] clear BE error on blur --- .../settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index c3b574404593..041f4c07c064 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -97,6 +97,11 @@ function PhoneNumberPage() { role={CONST.ROLE.PRESENTATION} defaultValue={phoneNumber} spellCheck={false} + onBlur={() => { + if (validateLoginError) { + PersonalDetails.clearPhoneNumberError(); + } + }} /> From 89b1f44d52d2cd408712a292a62a585dd515246e Mon Sep 17 00:00:00 2001 From: Gandalf Date: Thu, 24 Oct 2024 11:57:36 +0530 Subject: [PATCH 17/22] fix lint --- src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 1 + src/pages/workspace/accounting/reconciliation/tets.md | 0 2 files changed, 1 insertion(+) create mode 100644 src/pages/workspace/accounting/reconciliation/tets.md diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index 041f4c07c064..079c0d4b7208 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -100,6 +100,7 @@ function PhoneNumberPage() { onBlur={() => { if (validateLoginError) { PersonalDetails.clearPhoneNumberError(); + return; } }} /> diff --git a/src/pages/workspace/accounting/reconciliation/tets.md b/src/pages/workspace/accounting/reconciliation/tets.md new file mode 100644 index 000000000000..e69de29bb2d1 From 3c927e2a0cf8acdd522f148134882dcc40db2781 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Thu, 24 Oct 2024 12:40:04 +0530 Subject: [PATCH 18/22] return early if no error is present --- .../settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index 079c0d4b7208..44cafec14d3a 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -98,10 +98,10 @@ function PhoneNumberPage() { defaultValue={phoneNumber} spellCheck={false} onBlur={() => { - if (validateLoginError) { - PersonalDetails.clearPhoneNumberError(); + if (!validateLoginError) { return; } + PersonalDetails.clearPhoneNumberError(); }} /> From d0fb1b56fc318badb6a629dc1a129a3b19c1caf0 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Fri, 25 Oct 2024 12:45:33 +0530 Subject: [PATCH 19/22] delete md file --- src/pages/workspace/accounting/reconciliation/tets.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/pages/workspace/accounting/reconciliation/tets.md diff --git a/src/pages/workspace/accounting/reconciliation/tets.md b/src/pages/workspace/accounting/reconciliation/tets.md deleted file mode 100644 index e69de29bb2d1..000000000000 From f539c527b2a15acaf9c6be230a2a4d1a8192673d Mon Sep 17 00:00:00 2001 From: Gandalf Date: Fri, 25 Oct 2024 12:57:36 +0530 Subject: [PATCH 20/22] clear BE error on validation --- .../settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index 44cafec14d3a..be87fcc1991f 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -57,6 +57,11 @@ function PhoneNumberPage() { if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumberWithCountryCode.slice(0))) { errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber'); } + + // Clear the error when the user tries to validate the form and there are errors + if (validateLoginError && !!errors) { + PersonalDetails.clearPhoneNumberError(); + } return errors; }, [translate], From e532ef12a3becf621212a64b4dc177ad3fd42a63 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Sun, 27 Oct 2024 16:49:43 +0530 Subject: [PATCH 21/22] fix lint --- src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index be87fcc1991f..12c6f011c6a2 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -64,7 +64,7 @@ function PhoneNumberPage() { } return errors; }, - [translate], + [translate, validateLoginError], ); return ( From c07af88bd7bd7d54310ca03b0d573094110a8d38 Mon Sep 17 00:00:00 2001 From: Gandalf Date: Mon, 28 Oct 2024 17:48:41 +0530 Subject: [PATCH 22/22] Apply suggestions from code review Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/hooks/useIndicatorStatus.ts | 4 ++-- src/libs/UserUtils.ts | 4 ++-- src/pages/settings/InitialSettingsPage.tsx | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hooks/useIndicatorStatus.ts b/src/hooks/useIndicatorStatus.ts index bba394a828d1..7fcd81112a9b 100644 --- a/src/hooks/useIndicatorStatus.ts +++ b/src/hooks/useIndicatorStatus.ts @@ -28,7 +28,7 @@ function useIndicatorStatus(): IndicatorStatusResult { const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET); const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); - const [privatePersoanlDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); + const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); // If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and // those should be cleaned out before doing any error checking @@ -58,7 +58,7 @@ function useIndicatorStatus(): IndicatorStatusResult { [CONST.INDICATOR_STATUS.HAS_LOGIN_LIST_ERROR]: !!loginList && UserUtils.hasLoginListError(loginList), // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead) [CONST.INDICATOR_STATUS.HAS_WALLET_TERMS_ERRORS]: Object.keys(walletTerms?.errors ?? {}).length > 0 && !walletTerms?.chatReportID, - [CONST.INDICATOR_STATUS.HAS_PHONE_NUMBER_ERROR]: !!privatePersoanlDetails?.errorFields?.phoneNumber ?? undefined, + [CONST.INDICATOR_STATUS.HAS_PHONE_NUMBER_ERROR]: !!privatePersonalDetails?.errorFields?.phoneNumber ?? undefined, }; const infoChecking: Partial> = { diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 700ec2340f7e..37b69d1d5d35 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -86,8 +86,8 @@ function getLoginListBrickRoadIndicator(loginList: OnyxEntry): LoginL * Gets the appropriate brick road indicator status for the Profile section. * Error status is higher priority, so we check for that first. */ -function getProfilePageBrickRoadIndicator(loginList: OnyxEntry, privatePersoanlDetails: OnyxEntry): LoginListIndicator { - const hasPhoneNumberError = !!privatePersoanlDetails?.errorFields?.phoneNumber; +function getProfilePageBrickRoadIndicator(loginList: OnyxEntry, privatePersonalDetails: OnyxEntry): LoginListIndicator { + const hasPhoneNumberError = !!privatePersonalDetails?.errorFields?.phoneNumber; if (hasLoginListError(loginList) || hasPhoneNumberError) { return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; } diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 75f83759ebea..40d2c2ed4174 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -80,7 +80,7 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); - const [privatePersoanlDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); + const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); const network = useNetwork(); const theme = useTheme(); @@ -127,7 +127,7 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr * @returns object with translationKey, style and items for the account section */ const accountMenuItemsData: Menu = useMemo(() => { - const profileBrickRoadIndicator = UserUtils.getProfilePageBrickRoadIndicator(loginList, privatePersoanlDetails); + const profileBrickRoadIndicator = UserUtils.getProfilePageBrickRoadIndicator(loginList, privatePersonalDetails); const paymentCardList = fundList; const defaultMenu: Menu = { sectionStyle: styles.accountSettingsSectionContainer, @@ -162,7 +162,7 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr }; return defaultMenu; - }, [loginList, fundList, styles.accountSettingsSectionContainer, bankAccountList, userWallet?.errors, walletTerms?.errors, privatePersoanlDetails]); + }, [loginList, fundList, styles.accountSettingsSectionContainer, bankAccountList, userWallet?.errors, walletTerms?.errors, privatePersonalDetails]); /** * Retuns a list of menu items data for workspace section