From 947b6bb21ca0b3bbf9fe7741de51157f073346b7 Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Tue, 19 Aug 2025 19:22:36 +0530 Subject: [PATCH 01/35] Handle 404 exception and add translation key --- src/languages/en.ts | 1 + src/libs/actions/Card.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/languages/en.ts b/src/languages/en.ts index 917877ab51914..9554cefce518d 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2143,6 +2143,7 @@ const translations = { pleaseFillMagicCode: 'Please enter your magic code', incorrectMagicCode: 'Incorrect or invalid magic code. Please try again or request a new code.', pleaseFillTwoFactorAuth: 'Please enter your two-factor authentication code', + missingPrivateDetails: 'Please update your private personal details under Settings > Profile, then try again.', }, }, passwordForm: { diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 758b05e08ebfd..6e7f9622dc790 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -260,6 +260,12 @@ function revealVirtualCardDetails(cardID: number, validateCode: string): Promise return; } + if (response?.jsonCode === 404) { + // eslint-disable-next-line prefer-promise-reject-errors + reject('validateCodeForm.error.missingPrivateDetails'); + return; + } + // eslint-disable-next-line prefer-promise-reject-errors reject('cardPage.cardDetailsLoadingFailure'); return; From c20ea86aa531251bce65a15176d69e5501770734 Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Tue, 19 Aug 2025 23:05:58 +0530 Subject: [PATCH 02/35] Add translations and update path --- src/languages/de.ts | 1 + src/languages/en.ts | 2 +- src/languages/es.ts | 1 + src/languages/fr.ts | 1 + src/languages/it.ts | 1 + src/languages/ja.ts | 1 + src/languages/nl.ts | 1 + src/languages/pl.ts | 1 + src/languages/pt-BR.ts | 1 + src/languages/zh-hans.ts | 1 + src/libs/actions/Card.ts | 2 +- 11 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/languages/de.ts b/src/languages/de.ts index 752170ba678ab..b864f2bffe1de 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -1925,6 +1925,7 @@ const translations = { validateCardTitle: 'Lassen Sie uns sicherstellen, dass Sie es sind', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Bitte geben Sie den magischen Code ein, der an ${contactMethod} gesendet wurde, um Ihre Kartendetails anzuzeigen. Er sollte in ein bis zwei Minuten ankommen.`, + missingPrivateDetails: 'Bitte aktualisieren Sie Ihre privaten persönlichen Daten unter Einstellungen > Profil und versuchen Sie es erneut', }, workflowsPage: { workflowTitle: 'Ausgaben', diff --git a/src/languages/en.ts b/src/languages/en.ts index 9554cefce518d..8dac2ed3d2d3b 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1905,6 +1905,7 @@ const translations = { cardDetailsLoadingFailure: 'An error occurred while loading the card details. Please check your internet connection and try again.', validateCardTitle: "Let's make sure it's you", enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Please enter the magic code sent to ${contactMethod} to view your card details. It should arrive within a minute or two.`, + missingPrivateDetails: 'Please update your private personal details under Settings > Profile, then try again.', }, workflowsPage: { workflowTitle: 'Spend', @@ -2143,7 +2144,6 @@ const translations = { pleaseFillMagicCode: 'Please enter your magic code', incorrectMagicCode: 'Incorrect or invalid magic code. Please try again or request a new code.', pleaseFillTwoFactorAuth: 'Please enter your two-factor authentication code', - missingPrivateDetails: 'Please update your private personal details under Settings > Profile, then try again.', }, }, passwordForm: { diff --git a/src/languages/es.ts b/src/languages/es.ts index ea35a8ecb40d4..0882083324e79 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1900,6 +1900,7 @@ const translations = { validateCardTitle: 'Asegurémonos de que eres tú', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Introduzca el código mágico enviado a ${contactMethod} para ver los datos de su tarjeta. Debería llegar en un par de minutos.`, + missingPrivateDetails: 'Actualiza tus datos personales privados en Configuración > Perfil y vuelve a intentarlo', }, workflowsPage: { workflowTitle: 'Gasto', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index e7044633bb12c..a3a73df1f1c97 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -1928,6 +1928,7 @@ const translations = { validateCardTitle: "Assurons-nous que c'est bien vous", enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Veuillez entrer le code magique envoyé à ${contactMethod} pour voir les détails de votre carte. Il devrait arriver dans une minute ou deux.`, + missingPrivateDetails: 'Veuillez mettre à jour vos informations personnelles privées dans Paramètres > Profil, puis réessayez', }, workflowsPage: { workflowTitle: 'Dépenser', diff --git a/src/languages/it.ts b/src/languages/it.ts index 659febb37c783..a5d147ff36b43 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -1919,6 +1919,7 @@ const translations = { validateCardTitle: 'Verifichiamo che sei tu', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Inserisci il codice magico inviato a ${contactMethod} per visualizzare i dettagli della tua carta. Dovrebbe arrivare entro un minuto o due.`, + missingPrivateDetails: 'Aggiorna i tuoi dati personali privati in Impostazioni > Profilo e riprova', }, workflowsPage: { workflowTitle: 'Spendere', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index eb6dc42bbb242..4413405d2065f 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -1913,6 +1913,7 @@ const translations = { cardDetailsLoadingFailure: 'カードの詳細を読み込む際にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。', validateCardTitle: 'あなたであることを確認しましょう', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `カードの詳細を表示するには、${contactMethod} に送信されたマジックコードを入力してください。1~2分以内に届くはずです。`, + missingPrivateDetails: '設定 > プロフィール から個人のプライベート情報を更新して、もう一度お試しください', }, workflowsPage: { workflowTitle: '支出', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index d0f3d810d2593..2fbcc9cfd8365 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -1919,6 +1919,7 @@ const translations = { validateCardTitle: 'Laten we ervoor zorgen dat jij het bent', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Voer de magische code in die naar ${contactMethod} is gestuurd om uw kaartgegevens te bekijken. Het zou binnen een minuut of twee moeten aankomen.`, + missingPrivateDetails: 'Werk uw privé-persoonlijke gegevens bij onder Instellingen > Profiel en probeer het opnieuw', }, workflowsPage: { workflowTitle: 'Uitgaven', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 74ced0c3316c9..75e9c62263dbe 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -1915,6 +1915,7 @@ const translations = { validateCardTitle: 'Upewnijmy się, że to Ty', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Proszę wprowadzić magiczny kod wysłany na ${contactMethod}, aby zobaczyć szczegóły swojej karty. Powinien dotrzeć w ciągu minuty lub dwóch.`, + missingPrivateDetails: 'Zaktualizuj swoje prywatne dane osobowe w Ustawienia > Profil, a następnie spróbuj ponownie', }, workflowsPage: { workflowTitle: 'Wydatki', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 1c273852c5338..1ad97a217b5ab 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -1919,6 +1919,7 @@ const translations = { validateCardTitle: 'Vamos garantir que é você', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Por favor, insira o código mágico enviado para ${contactMethod} para visualizar os detalhes do seu cartão. Ele deve chegar dentro de um ou dois minutos.`, + missingPrivateDetails: 'Atualize seus dados pessoais privados em Configurações > Perfil e tente novamente', }, workflowsPage: { workflowTitle: 'Gastar', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 80e852e878fc0..27961f102a39d 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -1895,6 +1895,7 @@ const translations = { cardDetailsLoadingFailure: '加载卡片详情时发生错误。请检查您的互联网连接并重试。', validateCardTitle: '让我们确认一下身份', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `请输入发送到${contactMethod}的验证码以查看您的卡详细信息。验证码应在一两分钟内到达。`, + missingPrivateDetails: '请在 设置 > 个人资料 中更新您的私人个人信息,然后重试', }, workflowsPage: { workflowTitle: '花费', diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 6e7f9622dc790..2f650becb29b7 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -262,7 +262,7 @@ function revealVirtualCardDetails(cardID: number, validateCode: string): Promise if (response?.jsonCode === 404) { // eslint-disable-next-line prefer-promise-reject-errors - reject('validateCodeForm.error.missingPrivateDetails'); + reject('cardPage.missingPrivateDetails'); return; } From 3cbb3d609c39108cad8c2c57e225167e47cf30cf Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Sat, 23 Aug 2025 19:06:28 +0530 Subject: [PATCH 03/35] Updates to RBR workflow --- src/components/AddressForm.tsx | 55 ++++++++++++------- src/libs/actions/Card.ts | 2 +- src/libs/actions/PersonalDetails.ts | 18 ++++++ src/pages/AddressPage.tsx | 6 +- .../PersonalDetails/DateOfBirthPage.tsx | 38 +++++++++---- .../PersonalDetails/PersonalAddressPage.tsx | 9 ++- .../PersonalDetails/PhoneNumberPage.tsx | 8 +-- src/pages/settings/Profile/ProfilePage.tsx | 2 + 8 files changed, 97 insertions(+), 41 deletions(-) diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index 1f75370a82aa9..1afecda1c49b7 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -5,7 +5,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {isRequiredFulfilled} from '@libs/ValidationUtils'; import type {Country} from '@src/CONST'; import CONST from '@src/CONST'; -import type ONYXKEYS from '@src/ONYXKEYS'; +import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/HomeAddressForm'; import type {Errors} from '@src/types/onyx/OnyxCommon'; import AddressSearch from './AddressSearch'; @@ -16,6 +16,8 @@ import type {FormOnyxValues} from './Form/types'; import type {State} from './StateSelector'; import StateSelector from './StateSelector'; import TextInput from './TextInput'; +import {useOnyx} from "react-native-onyx"; +import OfflineWithFeedback from "@components/OfflineWithFeedback"; type CountryZipRegex = { regex?: RegExp; @@ -55,6 +57,9 @@ type AddressFormProps = { /** A unique Onyx key identifying the form */ formID: typeof ONYXKEYS.FORMS.HOME_ADDRESS_FORM; + + /** Function to clear address street error */ + onClearAddressStreetError?: () => void; }; function AddressForm({ @@ -69,6 +74,7 @@ function AddressForm({ street2 = '', submitButtonText = '', zip = '', + onClearAddressStreetError = () => {} }: AddressFormProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -79,6 +85,9 @@ function AddressForm({ const isUSAForm = country === CONST.COUNTRY.US; + const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS, {canBeMissing: true}); + let addressStreetError = privatePersonalDetails?.errorFields?.addressStreet; + /** * @param translate - translate function * @param isUSAForm - selected country ISO code is US @@ -164,25 +173,31 @@ function AddressForm({ addBottomSafeAreaPadding > - { - onAddressChanged(data, key); - }} - defaultValue={street1} - renamedInputKeys={{ - street: INPUT_IDS.ADDRESS_LINE_1, - street2: INPUT_IDS.ADDRESS_LINE_2, - city: INPUT_IDS.CITY, - state: INPUT_IDS.STATE, - zipCode: INPUT_IDS.ZIP_POST_CODE, - country: INPUT_IDS.COUNTRY as Country, - }} - maxInputLength={CONST.FORM_CHARACTER_LIMIT} - shouldSaveDraft={shouldSaveDraft} - /> + + { + onAddressChanged(data, key); + }} + defaultValue={street1} + renamedInputKeys={{ + street: INPUT_IDS.ADDRESS_LINE_1, + street2: INPUT_IDS.ADDRESS_LINE_2, + city: INPUT_IDS.CITY, + state: INPUT_IDS.STATE, + zipCode: INPUT_IDS.ZIP_POST_CODE, + country: INPUT_IDS.COUNTRY as Country, + }} + maxInputLength={CONST.FORM_CHARACTER_LIMIT} + shouldSaveDraft={shouldSaveDraft} + /> + void; } & BackToParams; -function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo, defaultCountry}: AddressPageProps) { +function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo, defaultCountry, onClearAddressStreetError}: AddressPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -108,6 +111,7 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo street1={street1} street2={street2} zip={zipcode} + onClearAddressStreetError={onClearAddressStreetError} /> )} diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx index eab021b7648ea..b620c01885bc2 100644 --- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx @@ -13,16 +13,20 @@ import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import {getAgeRequirementError, getFieldRequiredErrors} from '@libs/ValidationUtils'; -import {updateDateOfBirth} from '@userActions/PersonalDetails'; +import {clearDateOfBirthError, updateDateOfBirth} from '@userActions/PersonalDetails'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/DateOfBirthForm'; +import {getEarliestErrorField} from "@libs/ErrorUtils"; +import OfflineWithFeedback from "@components/OfflineWithFeedback"; function DateOfBirthPage() { const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP); const {translate} = useLocalize(); const styles = useThemeStyles(); + const validateLoginError = getEarliestErrorField(privatePersonalDetails, 'dob'); + /** * @returns An object containing the errors for each inputID */ @@ -58,20 +62,32 @@ function DateOfBirthPage() { style={[styles.flexGrow1, styles.ph5]} formID={ONYXKEYS.FORMS.DATE_OF_BIRTH_FORM} validate={validate} - onSubmit={updateDateOfBirth} + onSubmit={(values: FormOnyxValues) => { + // Clear the error when the user tries to submit the form + if (validateLoginError) { + clearDateOfBirthError(); + } + updateDateOfBirth(values); + }} submitButtonText={translate('common.save')} enabledWhenOffline shouldHideFixErrorsAlert > - + clearDateOfBirthError()} + > + + )} diff --git a/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx b/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx index 4b6e89f065eb4..f2b1cd68e6299 100644 --- a/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx @@ -6,9 +6,13 @@ import {getCurrentAddress} from '@libs/PersonalDetailsUtils'; import AddressPage from '@pages/AddressPage'; import type {FormOnyxValues} from '@src/components/Form/types'; import type {Country} from '@src/CONST'; -import {updateAddress as updateAddressPersonalDetails} from '@src/libs/actions/PersonalDetails'; +import { + clearAddressStreetError, + updateAddress as updateAddressPersonalDetails +} from '@src/libs/actions/PersonalDetails'; import ONYXKEYS from '@src/ONYXKEYS'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; +import {getEarliestErrorField} from "@libs/ErrorUtils"; /** * Submit form to update user's first and last legal name @@ -35,6 +39,8 @@ function PersonalAddressPage() { if (isLoading) { return ; } + const addressStreetError = getEarliestErrorField(privatePersonalDetails, 'addressStreet'); + return ( ); } diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index e0a848422286d..53df456de8139 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -105,18 +105,12 @@ function PhoneNumberPage() { InputComponent={TextInput} ref={inputCallbackRef} inputID={INPUT_IDS.PHONE_NUMBER} - name="legalFirstName" + name="phoneNumber" label={translate('common.phoneNumber')} aria-label={translate('common.phoneNumber')} role={CONST.ROLE.PRESENTATION} defaultValue={phoneNumber} spellCheck={false} - onBlur={() => { - if (!validateLoginError) { - return; - } - clearPhoneNumberError(); - }} /> diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 739ac0da2a274..bde5781077810 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -117,6 +117,7 @@ function ProfilePage() { } Navigation.navigate(ROUTES.SETTINGS_DATE_OF_BIRTH); }, + brickRoadIndicator: privatePersonalDetails?.errorFields?.dob ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, { description: translate('common.phoneNumber'), @@ -140,6 +141,7 @@ function ProfilePage() { } Navigation.navigate(ROUTES.SETTINGS_ADDRESS); }, + brickRoadIndicator: (privatePersonalDetails?.errorFields?.addressStreet || privatePersonalDetails?.errorFields?.addressCity || privatePersonalDetails?.errorFields?.addressState || privatePersonalDetails?.errorFields?.addressZipCode) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, ]; From ade0d80e95f29d283d86019407109f7359c01936 Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Sat, 23 Aug 2025 19:17:42 +0530 Subject: [PATCH 04/35] Update translation --- src/languages/de.ts | 2 +- src/languages/en.ts | 2 +- src/languages/es.ts | 2 +- src/languages/fr.ts | 2 +- src/languages/it.ts | 2 +- src/languages/ja.ts | 2 +- src/languages/nl.ts | 2 +- src/languages/pl.ts | 2 +- src/languages/pt-BR.ts | 2 +- src/languages/zh-hans.ts | 2 +- src/libs/actions/Card.ts | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/languages/de.ts b/src/languages/de.ts index b864f2bffe1de..1ce327f4c5611 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -1925,7 +1925,7 @@ const translations = { validateCardTitle: 'Lassen Sie uns sicherstellen, dass Sie es sind', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Bitte geben Sie den magischen Code ein, der an ${contactMethod} gesendet wurde, um Ihre Kartendetails anzuzeigen. Er sollte in ein bis zwei Minuten ankommen.`, - missingPrivateDetails: 'Bitte aktualisieren Sie Ihre privaten persönlichen Daten unter Einstellungen > Profil und versuchen Sie es erneut', + missingPrivateDetails: 'Bitte fügen Sie Ihre persönlichen Daten unter Konto > Profil > Privat hinzu und versuchen Sie es erneut.', }, workflowsPage: { workflowTitle: 'Ausgaben', diff --git a/src/languages/en.ts b/src/languages/en.ts index 8dac2ed3d2d3b..77ed105b37d17 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1905,7 +1905,7 @@ const translations = { cardDetailsLoadingFailure: 'An error occurred while loading the card details. Please check your internet connection and try again.', validateCardTitle: "Let's make sure it's you", enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Please enter the magic code sent to ${contactMethod} to view your card details. It should arrive within a minute or two.`, - missingPrivateDetails: 'Please update your private personal details under Settings > Profile, then try again.', + missingPrivateDetails: 'Please add your personal details under Account > Profile > Private, then try again.', }, workflowsPage: { workflowTitle: 'Spend', diff --git a/src/languages/es.ts b/src/languages/es.ts index 0882083324e79..d1c8a84ffc2bb 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1900,7 +1900,7 @@ const translations = { validateCardTitle: 'Asegurémonos de que eres tú', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Introduzca el código mágico enviado a ${contactMethod} para ver los datos de su tarjeta. Debería llegar en un par de minutos.`, - missingPrivateDetails: 'Actualiza tus datos personales privados en Configuración > Perfil y vuelve a intentarlo', + missingPrivateDetails: 'Agrega tus datos personales en Cuenta > Perfil > Privado y vuelve a intentarlo.', }, workflowsPage: { workflowTitle: 'Gasto', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index a3a73df1f1c97..50f7ad16ea909 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -1928,7 +1928,7 @@ const translations = { validateCardTitle: "Assurons-nous que c'est bien vous", enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Veuillez entrer le code magique envoyé à ${contactMethod} pour voir les détails de votre carte. Il devrait arriver dans une minute ou deux.`, - missingPrivateDetails: 'Veuillez mettre à jour vos informations personnelles privées dans Paramètres > Profil, puis réessayez', + missingPrivateDetails: 'Veuillez ajouter vos informations personnelles dans Compte > Profil > Privé, puis réessayez.', }, workflowsPage: { workflowTitle: 'Dépenser', diff --git a/src/languages/it.ts b/src/languages/it.ts index a5d147ff36b43..c70d6853c2eeb 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -1919,7 +1919,7 @@ const translations = { validateCardTitle: 'Verifichiamo che sei tu', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Inserisci il codice magico inviato a ${contactMethod} per visualizzare i dettagli della tua carta. Dovrebbe arrivare entro un minuto o due.`, - missingPrivateDetails: 'Aggiorna i tuoi dati personali privati in Impostazioni > Profilo e riprova', + missingPrivateDetails: 'Aggiungi i tuoi dati personali in Account > Profilo > Privato e riprova.', }, workflowsPage: { workflowTitle: 'Spendere', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 4413405d2065f..faf98cd812157 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -1913,7 +1913,7 @@ const translations = { cardDetailsLoadingFailure: 'カードの詳細を読み込む際にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。', validateCardTitle: 'あなたであることを確認しましょう', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `カードの詳細を表示するには、${contactMethod} に送信されたマジックコードを入力してください。1~2分以内に届くはずです。`, - missingPrivateDetails: '設定 > プロフィール から個人のプライベート情報を更新して、もう一度お試しください', + missingPrivateDetails: 'アカウント > プロフィール > プライベート で個人情報を追加して、もう一度お試しください。', }, workflowsPage: { workflowTitle: '支出', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 2fbcc9cfd8365..9098103487690 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -1919,7 +1919,7 @@ const translations = { validateCardTitle: 'Laten we ervoor zorgen dat jij het bent', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Voer de magische code in die naar ${contactMethod} is gestuurd om uw kaartgegevens te bekijken. Het zou binnen een minuut of twee moeten aankomen.`, - missingPrivateDetails: 'Werk uw privé-persoonlijke gegevens bij onder Instellingen > Profiel en probeer het opnieuw', + missingPrivateDetails: 'Voeg uw persoonlijke gegevens toe onder Account > Profiel > Privé en probeer het opnieuw.', }, workflowsPage: { workflowTitle: 'Uitgaven', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 75e9c62263dbe..afb914e0871e5 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -1915,7 +1915,7 @@ const translations = { validateCardTitle: 'Upewnijmy się, że to Ty', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Proszę wprowadzić magiczny kod wysłany na ${contactMethod}, aby zobaczyć szczegóły swojej karty. Powinien dotrzeć w ciągu minuty lub dwóch.`, - missingPrivateDetails: 'Zaktualizuj swoje prywatne dane osobowe w Ustawienia > Profil, a następnie spróbuj ponownie', + missingPrivateDetails: 'Dodaj swoje dane osobowe w Konto > Profil > Prywatne, a następnie spróbuj ponownie.', }, workflowsPage: { workflowTitle: 'Wydatki', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 1ad97a217b5ab..f8d5457b212cc 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -1919,7 +1919,7 @@ const translations = { validateCardTitle: 'Vamos garantir que é você', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Por favor, insira o código mágico enviado para ${contactMethod} para visualizar os detalhes do seu cartão. Ele deve chegar dentro de um ou dois minutos.`, - missingPrivateDetails: 'Atualize seus dados pessoais privados em Configurações > Perfil e tente novamente', + missingPrivateDetails: 'Adicione seus dados pessoais em Conta > Perfil > Privado e tente novamente.', }, workflowsPage: { workflowTitle: 'Gastar', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 27961f102a39d..f30f0667b4107 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -1895,7 +1895,7 @@ const translations = { cardDetailsLoadingFailure: '加载卡片详情时发生错误。请检查您的互联网连接并重试。', validateCardTitle: '让我们确认一下身份', enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `请输入发送到${contactMethod}的验证码以查看您的卡详细信息。验证码应在一两分钟内到达。`, - missingPrivateDetails: '请在 设置 > 个人资料 中更新您的私人个人信息,然后重试', + missingPrivateDetails: '请在 账户 > 个人资料 > 私密 中添加您的个人信息,然后重试。', }, workflowsPage: { workflowTitle: '花费', diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index a55636a5898c7..2f650becb29b7 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -262,7 +262,7 @@ function revealVirtualCardDetails(cardID: number, validateCode: string): Promise if (response?.jsonCode === 404) { // eslint-disable-next-line prefer-promise-reject-errors - reject(); + reject('cardPage.missingPrivateDetails'); return; } From bd48da09d9ca2b206a14cffb5b3b1a588a89b95a Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Sat, 23 Aug 2025 19:32:30 +0530 Subject: [PATCH 05/35] Run prettier --- src/components/AddressForm.tsx | 6 +++--- .../settings/Profile/PersonalDetails/DateOfBirthPage.tsx | 4 ++-- .../Profile/PersonalDetails/PersonalAddressPage.tsx | 7 ++----- src/pages/settings/Profile/ProfilePage.tsx | 8 +++++++- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index 1afecda1c49b7..dae5b79d23f73 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -1,5 +1,7 @@ import React, {useCallback} from 'react'; import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {isRequiredFulfilled} from '@libs/ValidationUtils'; @@ -16,8 +18,6 @@ import type {FormOnyxValues} from './Form/types'; import type {State} from './StateSelector'; import StateSelector from './StateSelector'; import TextInput from './TextInput'; -import {useOnyx} from "react-native-onyx"; -import OfflineWithFeedback from "@components/OfflineWithFeedback"; type CountryZipRegex = { regex?: RegExp; @@ -74,7 +74,7 @@ function AddressForm({ street2 = '', submitButtonText = '', zip = '', - onClearAddressStreetError = () => {} + onClearAddressStreetError = () => {}, }: AddressFormProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx index b620c01885bc2..7c0380b6a1826 100644 --- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx @@ -7,18 +7,18 @@ import InputWrapper from '@components/Form/InputWrapper'; import type {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 useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; +import {getEarliestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {getAgeRequirementError, getFieldRequiredErrors} from '@libs/ValidationUtils'; import {clearDateOfBirthError, updateDateOfBirth} from '@userActions/PersonalDetails'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/DateOfBirthForm'; -import {getEarliestErrorField} from "@libs/ErrorUtils"; -import OfflineWithFeedback from "@components/OfflineWithFeedback"; function DateOfBirthPage() { const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); diff --git a/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx b/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx index f2b1cd68e6299..f0a38e3a90a21 100644 --- a/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx @@ -2,17 +2,14 @@ import React, {useMemo} from 'react'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import {getEarliestErrorField} from '@libs/ErrorUtils'; import {getCurrentAddress} from '@libs/PersonalDetailsUtils'; import AddressPage from '@pages/AddressPage'; import type {FormOnyxValues} from '@src/components/Form/types'; import type {Country} from '@src/CONST'; -import { - clearAddressStreetError, - updateAddress as updateAddressPersonalDetails -} from '@src/libs/actions/PersonalDetails'; +import {clearAddressStreetError, updateAddress as updateAddressPersonalDetails} from '@src/libs/actions/PersonalDetails'; import ONYXKEYS from '@src/ONYXKEYS'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; -import {getEarliestErrorField} from "@libs/ErrorUtils"; /** * Submit form to update user's first and last legal name diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index bde5781077810..a14986ca69fc4 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -141,7 +141,13 @@ function ProfilePage() { } Navigation.navigate(ROUTES.SETTINGS_ADDRESS); }, - brickRoadIndicator: (privatePersonalDetails?.errorFields?.addressStreet || privatePersonalDetails?.errorFields?.addressCity || privatePersonalDetails?.errorFields?.addressState || privatePersonalDetails?.errorFields?.addressZipCode) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + brickRoadIndicator: + privatePersonalDetails?.errorFields?.addressStreet || + privatePersonalDetails?.errorFields?.addressCity || + privatePersonalDetails?.errorFields?.addressState || + privatePersonalDetails?.errorFields?.addressZipCode + ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + : undefined, }, ]; From 7f3ec029937bbe3b5cb7b6812123a4695a0f55c7 Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Mon, 25 Aug 2025 15:38:06 +0530 Subject: [PATCH 06/35] Fix lint and prettier --- src/components/AddressForm.tsx | 7 ++++--- .../Profile/PersonalDetails/PersonalAddressPage.tsx | 2 -- src/pages/settings/Profile/ProfilePage.tsx | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index dae5b79d23f73..e3c7c1798cdbc 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -1,8 +1,7 @@ import React, {useCallback} from 'react'; import {View} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; import {isRequiredFulfilled} from '@libs/ValidationUtils'; import type {Country} from '@src/CONST'; @@ -15,6 +14,7 @@ import CountrySelector from './CountrySelector'; import FormProvider from './Form/FormProvider'; import InputWrapper from './Form/InputWrapper'; import type {FormOnyxValues} from './Form/types'; +import OfflineWithFeedback from './OfflineWithFeedback'; import type {State} from './StateSelector'; import StateSelector from './StateSelector'; import TextInput from './TextInput'; @@ -86,7 +86,8 @@ function AddressForm({ const isUSAForm = country === CONST.COUNTRY.US; const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS, {canBeMissing: true}); - let addressStreetError = privatePersonalDetails?.errorFields?.addressStreet; + const isPersonalDetailsForm = !!onClearAddressStreetError; + const addressStreetError = isPersonalDetailsForm ? privatePersonalDetails?.errorFields?.addressStreet : undefined; /** * @param translate - translate function diff --git a/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx b/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx index f0a38e3a90a21..289e3f3ae7d03 100644 --- a/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PersonalAddressPage.tsx @@ -2,7 +2,6 @@ import React, {useMemo} from 'react'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; -import {getEarliestErrorField} from '@libs/ErrorUtils'; import {getCurrentAddress} from '@libs/PersonalDetailsUtils'; import AddressPage from '@pages/AddressPage'; import type {FormOnyxValues} from '@src/components/Form/types'; @@ -36,7 +35,6 @@ function PersonalAddressPage() { if (isLoading) { return ; } - const addressStreetError = getEarliestErrorField(privatePersonalDetails, 'addressStreet'); return ( Date: Mon, 25 Aug 2025 16:18:01 +0530 Subject: [PATCH 07/35] Fix style bugs and lint --- .../settings/Profile/PersonalDetails/DateOfBirthPage.tsx | 4 ++-- .../settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 4 ++-- src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx | 2 +- src/pages/settings/Wallet/ExpensifyCardPage.tsx | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx index 7c0380b6a1826..90b376bf296f1 100644 --- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx @@ -21,8 +21,8 @@ import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/DateOfBirthForm'; function DateOfBirthPage() { - const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); - const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP); + const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS, {canBeMissing: true}); + const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP, {canBeMissing: true}); const {translate} = useLocalize(); const styles = useThemeStyles(); const validateLoginError = getEarliestErrorField(privatePersonalDetails, 'dob'); diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx index 53df456de8139..93496e1e681c1 100644 --- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx @@ -23,8 +23,8 @@ 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 = true] = useOnyx(ONYXKEYS.IS_LOADING_APP); + const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS, {canBeMissing: true}); + const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP, {canBeMissing: true}); const styles = useThemeStyles(); const {translate} = useLocalize(); const {inputCallbackRef} = useAutoFocusInput(); diff --git a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx index 0757707b4e85b..c6d4c906ff8f7 100644 --- a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx +++ b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx @@ -130,7 +130,7 @@ function ActivatePhysicalCardPage({ testID={ActivatePhysicalCardPage.displayName} > {translate('activateCardPage.pleaseEnterLastFour')} - + )} From af7811a0d0647abff40f21c5e0100fe0d5ff0ab2 Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Tue, 26 Aug 2025 17:00:39 +0530 Subject: [PATCH 08/35] Fix style and remove numpad --- src/pages/settings/Profile/ProfilePage.tsx | 8 +------- src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx | 6 +----- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 622da5d8c61c5..0f28e0f0df0e6 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -141,13 +141,7 @@ function ProfilePage() { } Navigation.navigate(ROUTES.SETTINGS_ADDRESS); }, - brickRoadIndicator: - (privatePersonalDetails?.errorFields?.addressStreet ?? - privatePersonalDetails?.errorFields?.addressCity ?? - privatePersonalDetails?.errorFields?.addressState ?? - privatePersonalDetails?.errorFields?.addressZipCode) - ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR - : undefined, + brickRoadIndicator: privatePersonalDetails?.errorFields?.addressStreet ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, ]; diff --git a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx index c6d4c906ff8f7..21b0749560b90 100644 --- a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx +++ b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx @@ -130,9 +130,8 @@ function ActivatePhysicalCardPage({ testID={ActivatePhysicalCardPage.displayName} > {translate('activateCardPage.pleaseEnterLastFour')} - + - - {DeviceCapabilities.canUseTouchScreen() && } -