From 7dae918fa165f583e5818f1dc4fa690bf54b99c1 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 00:07:57 +0700 Subject: [PATCH 01/24] get rid of missing translation FormHelpMessage --- src/components/AddressForm.tsx | 6 ++-- src/components/AmountPicker/types.ts | 3 +- src/components/CheckboxWithLabel.tsx | 3 +- src/components/CountrySelector.tsx | 3 +- src/components/DotIndicatorMessage.tsx | 2 +- src/components/FormAlertWithSubmitButton.tsx | 3 +- src/components/FormAlertWrapper.tsx | 3 +- src/components/FormHelpMessage.tsx | 7 ++-- src/components/MagicCodeInput.tsx | 3 +- src/components/MenuItem.tsx | 5 ++- src/components/MessagesRow.tsx | 4 +-- .../MoneyRequestConfirmationList.tsx | 31 ++++------------ src/components/PDFView/PDFPasswordForm.tsx | 2 +- src/components/Picker/types.ts | 3 +- src/components/RadioButtonWithLabel.tsx | 3 +- src/components/RadioButtons.tsx | 3 +- src/components/SingleChoiceQuestion.tsx | 3 +- src/components/StateSelector.tsx | 3 +- .../TextInput/BaseTextInput/types.ts | 5 ++- src/components/TextPicker/types.ts | 3 +- src/components/TimePicker/TimePicker.tsx | 6 ++-- src/components/ValuePicker/types.ts | 3 +- src/libs/DateUtils.ts | 4 +-- src/libs/ErrorUtils.ts | 21 ++++++----- src/libs/ValidationUtils.ts | 10 +++--- src/libs/actions/TaxRate.ts | 5 +-- src/pages/EditReportFieldDate.tsx | 4 +-- .../EnablePayments/AdditionalDetailsStep.tsx | 14 ++++---- .../FeesAndTerms/substeps/TermsStep.tsx | 2 +- .../PersonalInfo/substeps/DateOfBirthStep.tsx | 28 +++++++-------- src/pages/EnablePayments/TermsStep.tsx | 2 +- .../BaseOnboardingPurpose.tsx | 10 +++--- .../AddressFormFields.tsx | 6 ++-- .../DateOfBirthUBO.tsx | 4 +-- .../substeps/ConfirmationBusiness.tsx | 20 +++++------ .../substeps/IncorporationDateBusiness.tsx | 24 ++++++------- .../substeps/ConfirmAgreements.tsx | 35 +++++++++---------- .../PersonalInfo/substeps/DateOfBirth.tsx | 28 +++++++-------- src/pages/Travel/TravelTerms.tsx | 2 +- src/pages/iou/MoneyRequestAmountForm.tsx | 9 +++-- .../MoneyRequestParticipantsSelector.tsx | 2 +- .../TwoFactorAuth/Steps/CodesStep.tsx | 2 +- .../Wallet/ActivatePhysicalCardPage.tsx | 2 +- .../settings/Wallet/AddDebitCardPage.tsx | 14 ++++---- .../settings/Wallet/ReportCardLostPage.tsx | 4 +-- src/pages/signin/LoginForm/BaseLoginForm.tsx | 11 +++--- .../ValidateCodeForm/BaseValidateCodeForm.tsx | 4 +-- src/pages/tasks/NewTaskPage.tsx | 6 ++-- src/pages/workspace/WorkspaceInvitePage.tsx | 2 +- src/pages/workspace/WorkspaceMembersPage.tsx | 2 +- src/pages/workspace/WorkspaceNewRoomPage.tsx | 10 +++--- src/stories/Form.stories.tsx | 5 ++- src/types/onyx/OnyxCommon.ts | 4 +-- 53 files changed, 181 insertions(+), 222 deletions(-) diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index 9ad4643e834a..bd3ad7ea0888 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -96,7 +96,7 @@ function AddressForm({ // Check "State" dropdown is a valid state if selected Country is USA if (values.country === CONST.COUNTRY.US && !values.state) { - errors.state = 'common.error.fieldRequired'; + errors.state = translate('common.error.fieldRequired'); } // Add "Field required" errors if any required field is empty @@ -106,7 +106,7 @@ function AddressForm({ return; } - errors[fieldKey] = 'common.error.fieldRequired'; + errors[fieldKey] = translate('common.error.fieldRequired'); }); // If no country is selected, default value is an empty string and there's no related regex data so we default to an empty object @@ -131,7 +131,7 @@ function AddressForm({ } return errors; - }, []); + }, [translate]); return ( string); /** Form Error description */ - errorText?: MaybePhraseKey; + errorText?: string; /** Callback to call when the input changes */ onInputChange?: (value: string | undefined) => void; diff --git a/src/components/CheckboxWithLabel.tsx b/src/components/CheckboxWithLabel.tsx index dd169576186e..db62aa9e1441 100644 --- a/src/components/CheckboxWithLabel.tsx +++ b/src/components/CheckboxWithLabel.tsx @@ -3,7 +3,6 @@ import React, {useState} from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import variables from '@styles/variables'; import Checkbox from './Checkbox'; import FormHelpMessage from './FormHelpMessage'; @@ -41,7 +40,7 @@ type CheckboxWithLabelProps = RequiredLabelProps & { style?: StyleProp; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Value for checkbox. This prop is intended to be set by FormProvider only */ value?: boolean; diff --git a/src/components/CountrySelector.tsx b/src/components/CountrySelector.tsx index 002c0c6d4b0a..62fdc85687e1 100644 --- a/src/components/CountrySelector.tsx +++ b/src/components/CountrySelector.tsx @@ -4,7 +4,6 @@ import type {ForwardedRef} from 'react'; import type {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; @@ -13,7 +12,7 @@ import MenuItemWithTopDescription from './MenuItemWithTopDescription'; type CountrySelectorProps = { /** Form error text. e.g when no country is selected */ - errorText?: MaybePhraseKey; + errorText?: string; /** Callback called when the country changes. */ onInputChange?: (value?: string) => void; diff --git a/src/components/DotIndicatorMessage.tsx b/src/components/DotIndicatorMessage.tsx index 3f72bbf429aa..f1aa8243b327 100644 --- a/src/components/DotIndicatorMessage.tsx +++ b/src/components/DotIndicatorMessage.tsx @@ -23,7 +23,7 @@ type DotIndicatorMessageProps = { * timestamp: 'message', * } */ - messages: Record; + messages: Record; /** The type of message, 'error' shows a red dot, 'success' shows a green dot */ type: 'error' | 'success'; diff --git a/src/components/FormAlertWithSubmitButton.tsx b/src/components/FormAlertWithSubmitButton.tsx index 137012478549..cd177a1d77a3 100644 --- a/src/components/FormAlertWithSubmitButton.tsx +++ b/src/components/FormAlertWithSubmitButton.tsx @@ -2,13 +2,12 @@ import React from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import Button from './Button'; import FormAlertWrapper from './FormAlertWrapper'; type FormAlertWithSubmitButtonProps = { /** Error message to display above button */ - message?: MaybePhraseKey; + message?: string; /** Whether the button is disabled */ isDisabled?: boolean; diff --git a/src/components/FormAlertWrapper.tsx b/src/components/FormAlertWrapper.tsx index d8b379208a29..525182070095 100644 --- a/src/components/FormAlertWrapper.tsx +++ b/src/components/FormAlertWrapper.tsx @@ -4,7 +4,6 @@ import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import type Network from '@src/types/onyx/Network'; import FormHelpMessage from './FormHelpMessage'; import {withNetwork} from './OnyxProvider'; @@ -29,7 +28,7 @@ type FormAlertWrapperProps = { isMessageHtml?: boolean; /** Error message to display above button */ - message?: MaybePhraseKey; + message?: string; /** Props to detect online status */ network: Network; diff --git a/src/components/FormHelpMessage.tsx b/src/components/FormHelpMessage.tsx index 4f1d784788bf..01a5a1eaf3a8 100644 --- a/src/components/FormHelpMessage.tsx +++ b/src/components/FormHelpMessage.tsx @@ -4,14 +4,13 @@ import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as Localize from '@libs/Localize'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import Text from './Text'; type FormHelpMessageProps = { /** Error or hint text. Ignored when children is not empty */ - message?: Localize.MaybePhraseKey; + message?: string; /** Children to render next to dot indicator */ children?: React.ReactNode; @@ -33,8 +32,6 @@ function FormHelpMessage({message = '', children, isError = true, style, shouldS return null; } - const translatedMessage = Localize.translateIfPhraseKey(message); - return ( {isError && shouldShowRedDotIndicator && ( @@ -44,7 +41,7 @@ function FormHelpMessage({message = '', children, isError = true, style, shouldS /> )} - {children ?? {translatedMessage}} + {children ?? {message}} ); diff --git a/src/components/MagicCodeInput.tsx b/src/components/MagicCodeInput.tsx index deff56a534ee..6239243cb5ab 100644 --- a/src/components/MagicCodeInput.tsx +++ b/src/components/MagicCodeInput.tsx @@ -7,7 +7,6 @@ import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Browser from '@libs/Browser'; -import type {MaybePhraseKey} from '@libs/Localize'; import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import FormHelpMessage from './FormHelpMessage'; @@ -33,7 +32,7 @@ type MagicCodeInputProps = { shouldDelayFocus?: boolean; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Specifies autocomplete hints for the system, so it can provide autofill */ autoComplete: AutoCompleteVariant; diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index b6f378763659..dd3cf462f89e 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -14,7 +14,6 @@ import ControlSelection from '@libs/ControlSelection'; import convertToLTR from '@libs/convertToLTR'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import getButtonState from '@libs/getButtonState'; -import type {MaybePhraseKey} from '@libs/Localize'; import type {AvatarSource} from '@libs/UserUtils'; import variables from '@styles/variables'; import * as Session from '@userActions/Session'; @@ -151,13 +150,13 @@ type MenuItemBaseProps = { shouldShowDescriptionOnTop?: boolean; /** Error to display at the bottom of the component */ - errorText?: MaybePhraseKey; + errorText?: string; /** Any additional styles to pass to error text. */ errorTextStyle?: StyleProp; /** Hint to display at the bottom of the component */ - hintText?: MaybePhraseKey; + hintText?: string; /** Should the error text red dot indicator be shown */ shouldShowRedDotIndicator?: boolean; diff --git a/src/components/MessagesRow.tsx b/src/components/MessagesRow.tsx index 7c764ec94fcd..2aead5da334c 100644 --- a/src/components/MessagesRow.tsx +++ b/src/components/MessagesRow.tsx @@ -4,9 +4,7 @@ import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import type * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; -import type {ReceiptError} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import DotIndicatorMessage from './DotIndicatorMessage'; import Icon from './Icon'; @@ -16,7 +14,7 @@ import Tooltip from './Tooltip'; type MessagesRowProps = { /** The messages to display */ - messages: Record; + messages: Record; /** The type of message, 'error' shows a red dot, 'success' shows a green dot */ type: 'error' | 'success'; diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index b18a98b13304..31fcdaa4843e 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -347,11 +347,11 @@ function MoneyRequestConfirmationList({ useEffect(() => { if (shouldDisplayFieldError && hasSmartScanFailed) { - setFormError('iou.receiptScanningFailed'); + setFormError(translate('iou.receiptScanningFailed')); return; } if (shouldDisplayFieldError && didConfirmSplit) { - setFormError('iou.error.genericSmartscanFailureMessage'); + setFormError(translate('iou.error.genericSmartscanFailureMessage')); return; } // reset the form error whenever the screen gains or loses focus @@ -431,7 +431,7 @@ function MoneyRequestConfirmationList({ const shares: number[] = Object.values(splitSharesMap).map((splitShare) => splitShare?.amount ?? 0); const sumOfShares = shares?.reduce((prev, current): number => prev + current, 0); if (sumOfShares !== iouAmount) { - setFormError('iou.error.invalidSplit'); + setFormError(translate('iou.error.invalidSplit')); return; } @@ -441,7 +441,7 @@ function MoneyRequestConfirmationList({ // A split must have at least two participants with amounts bigger than 0 if (participantsWithAmount.length === 1) { - setFormError('iou.error.invalidSplitParticipants'); + setFormError(translate('iou.error.invalidSplitParticipants')); return; } @@ -698,11 +698,11 @@ function MoneyRequestConfirmationList({ return; } if (!isEditingSplitBill && isMerchantRequired && (isMerchantEmpty || (shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction ?? null)))) { - setFormError('iou.error.invalidMerchant'); + setFormError(translate('iou.error.invalidMerchant')); return; } if (iouCategory.length > CONST.API_TRANSACTION_CATEGORY_MAX_LENGTH) { - setFormError('iou.error.invalidCategoryLength'); + setFormError(translate('iou.error.invalidCategoryLength')); return; } @@ -738,24 +738,7 @@ function MoneyRequestConfirmationList({ onConfirm?.(selectedParticipants); } }, - [ - selectedParticipants, - isMerchantRequired, - isMerchantEmpty, - shouldDisplayFieldError, - transaction, - iouType, - onSendMoney, - iouCurrencyCode, - isDistanceRequest, - iouCategory, - isDistanceRequestWithPendingRoute, - iouAmount, - isEditingSplitBill, - formError, - setFormError, - onConfirm, - ], + [selectedParticipants, isEditingSplitBill, isMerchantRequired, isMerchantEmpty, shouldDisplayFieldError, transaction, iouCategory.length, formError, iouType, setFormError, translate, onSendMoney, iouCurrencyCode, isDistanceRequest, isDistanceRequestWithPendingRoute, iouAmount, onConfirm], ); const footerContent = useMemo(() => { diff --git a/src/components/PDFView/PDFPasswordForm.tsx b/src/components/PDFView/PDFPasswordForm.tsx index e1ef83c9b60d..e571c2830b3c 100644 --- a/src/components/PDFView/PDFPasswordForm.tsx +++ b/src/components/PDFView/PDFPasswordForm.tsx @@ -47,7 +47,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid = false, shouldShowLoadin const errorText = useMemo(() => { if (isPasswordInvalid) { - return 'attachmentView.passwordIncorrect'; + return translate('attachmentView.passwordIncorrect'); } if (validationErrorText) { return validationErrorText; diff --git a/src/components/Picker/types.ts b/src/components/Picker/types.ts index d935ebe8fdc5..a6a942f41f26 100644 --- a/src/components/Picker/types.ts +++ b/src/components/Picker/types.ts @@ -1,6 +1,5 @@ import type {ChangeEvent, Component, ReactElement} from 'react'; import type {MeasureLayoutOnSuccessCallback, NativeMethods, StyleProp, ViewStyle} from 'react-native'; -import type {MaybePhraseKey} from '@libs/Localize'; type MeasureLayoutOnFailCallback = () => void; @@ -59,7 +58,7 @@ type BasePickerProps = { placeholder?: PickerPlaceholder; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Customize the BasePicker container */ containerStyles?: StyleProp; diff --git a/src/components/RadioButtonWithLabel.tsx b/src/components/RadioButtonWithLabel.tsx index 9b93d7900772..94265c19645d 100644 --- a/src/components/RadioButtonWithLabel.tsx +++ b/src/components/RadioButtonWithLabel.tsx @@ -3,7 +3,6 @@ import React from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import FormHelpMessage from './FormHelpMessage'; import * as Pressables from './Pressable'; import RadioButton from './RadioButton'; @@ -29,7 +28,7 @@ type RadioButtonWithLabelProps = { hasError?: boolean; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; }; const PressableWithFeedback = Pressables.PressableWithFeedback; diff --git a/src/components/RadioButtons.tsx b/src/components/RadioButtons.tsx index 2030ce8f0bfd..07e8fe38f772 100644 --- a/src/components/RadioButtons.tsx +++ b/src/components/RadioButtons.tsx @@ -3,7 +3,6 @@ import type {ForwardedRef} from 'react'; import {View} from 'react-native'; import type {StyleProp, ViewStyle} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import FormHelpMessage from './FormHelpMessage'; import RadioButtonWithLabel from './RadioButtonWithLabel'; @@ -24,7 +23,7 @@ type RadioButtonsProps = { onPress: (value: string) => void; /** Potential error text provided by a form InputWrapper */ - errorText?: MaybePhraseKey; + errorText?: string; /** Style for radio button */ radioButtonStyle?: StyleProp; diff --git a/src/components/SingleChoiceQuestion.tsx b/src/components/SingleChoiceQuestion.tsx index 3ff844dd80e9..c2dc72438e43 100644 --- a/src/components/SingleChoiceQuestion.tsx +++ b/src/components/SingleChoiceQuestion.tsx @@ -3,14 +3,13 @@ import React, {forwardRef} from 'react'; // eslint-disable-next-line no-restricted-imports import type {Text as RNText} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import type {Choice} from './RadioButtons'; import RadioButtons from './RadioButtons'; import Text from './Text'; type SingleChoiceQuestionProps = { prompt: string; - errorText?: MaybePhraseKey; + errorText?: string; possibleAnswers: Choice[]; currentQuestionIndex: number; onInputChange: (value: string) => void; diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 8cae007679ff..0733cb519f2c 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -6,7 +6,6 @@ import type {View} from 'react-native'; import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -17,7 +16,7 @@ type State = keyof typeof COMMON_CONST.STATES; type StateSelectorProps = { /** Form error text. e.g when no state is selected */ - errorText?: MaybePhraseKey; + errorText?: string; /** Current selected state */ value?: State | ''; diff --git a/src/components/TextInput/BaseTextInput/types.ts b/src/components/TextInput/BaseTextInput/types.ts index e8e2d5ab352d..7a46cca693e3 100644 --- a/src/components/TextInput/BaseTextInput/types.ts +++ b/src/components/TextInput/BaseTextInput/types.ts @@ -1,6 +1,5 @@ import type {GestureResponderEvent, StyleProp, TextInputProps, TextStyle, ViewStyle} from 'react-native'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; -import type {MaybePhraseKey} from '@libs/Localize'; import type IconAsset from '@src/types/utils/IconAsset'; type CustomBaseTextInputProps = { @@ -20,7 +19,7 @@ type CustomBaseTextInputProps = { placeholder?: string; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Icon to display in right side of text input */ icon?: IconAsset | null; @@ -68,7 +67,7 @@ type CustomBaseTextInputProps = { hideFocusedState?: boolean; /** Hint text to display below the TextInput */ - hint?: MaybePhraseKey; + hint?: string; /** Prefix character */ prefixCharacter?: string; diff --git a/src/components/TextPicker/types.ts b/src/components/TextPicker/types.ts index 179d16a07262..cbdc1ed21efe 100644 --- a/src/components/TextPicker/types.ts +++ b/src/components/TextPicker/types.ts @@ -1,6 +1,5 @@ import type {MenuItemBaseProps} from '@components/MenuItem'; import type {BaseTextInputProps} from '@components/TextInput/BaseTextInput/types'; -import type {MaybePhraseKey} from '@libs/Localize'; type TextProps = Exclude; @@ -30,7 +29,7 @@ type TextPickerProps = { placeholder?: string; /** Form Error description */ - errorText?: MaybePhraseKey; + errorText?: string; /** Callback to call when the input changes */ onInputChange?: (value: string | undefined) => void; diff --git a/src/components/TimePicker/TimePicker.tsx b/src/components/TimePicker/TimePicker.tsx index aecaf74dc4a3..8905abd370fe 100644 --- a/src/components/TimePicker/TimePicker.tsx +++ b/src/components/TimePicker/TimePicker.tsx @@ -135,15 +135,15 @@ function TimePicker({defaultValue = '', onSubmit, onInputChange = () => {}}: Tim const hour = parseInt(hourStr, 10); if (hour === 0) { setError(true); - setErrorMessage('common.error.invalidTimeRange'); + setErrorMessage(translate('common.error.invalidTimeRange')); return false; } const isValid = DateUtils.isTimeAtLeastOneMinuteInFuture({timeString, dateTimeString: defaultValue}); setError(!isValid); - setErrorMessage('common.error.invalidTimeShouldBeFuture'); + setErrorMessage(translate('common.error.invalidTimeShouldBeFuture')); return isValid; }, - [hours, minutes, amPmValue, defaultValue], + [hours, minutes, amPmValue, defaultValue, translate], ); const resetHours = () => { diff --git a/src/components/ValuePicker/types.ts b/src/components/ValuePicker/types.ts index b9c2c89948d9..b57c9d32061a 100644 --- a/src/components/ValuePicker/types.ts +++ b/src/components/ValuePicker/types.ts @@ -1,5 +1,4 @@ import type {ListItem} from '@components/SelectionList/types'; -import type {MaybePhraseKey} from '@libs/Localize'; type ValuePickerListItem = ListItem & { value?: string; @@ -51,7 +50,7 @@ type ValuePickerProps = { placeholder?: string; /** Form Error description */ - errorText?: MaybePhraseKey; + errorText?: string; /** Callback to call when the input changes */ onInputChange?: (value: string | undefined) => void; diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 8bd37ddd698d..75ae7ae3f043 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -648,7 +648,7 @@ const getDayValidationErrorKey = (inputDate: Date): string => { } if (isAfter(startOfDay(new Date()), startOfDay(inputDate))) { - return 'common.error.invalidDateShouldBeFuture'; + return Localize.translateLocal('common.error.invalidDateShouldBeFuture'); } return ''; }; @@ -662,7 +662,7 @@ const getDayValidationErrorKey = (inputDate: Date): string => { const getTimeValidationErrorKey = (inputTime: Date): string => { const timeNowPlusOneMinute = addMinutes(new Date(), 1); if (isBefore(inputTime, timeNowPlusOneMinute)) { - return 'common.error.invalidTimeShouldBeFuture'; + return Localize.translateLocal('common.error.invalidTimeShouldBeFuture'); } return ''; }; diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index 3487f05b9c05..af27dd5801f3 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -1,11 +1,11 @@ import mapValues from 'lodash/mapValues'; import CONST from '@src/CONST'; -import type {TranslationFlatObject, TranslationPaths} from '@src/languages/types'; +import type {TranslationFlatObject} from '@src/languages/types'; import type {ErrorFields, Errors} from '@src/types/onyx/OnyxCommon'; import type Response from '@src/types/onyx/Response'; import type {ReceiptError} from '@src/types/onyx/Transaction'; import DateUtils from './DateUtils'; -import * as Localize from './Localize'; +import type * as Localize from './Localize'; function getAuthenticateErrorMessage(response: Response): keyof TranslationFlatObject { switch (response.jsonCode) { @@ -53,15 +53,15 @@ function getMicroSecondOnyxErrorObject(error: Errors, errorKey?: number): ErrorF } // We can assume that if error is a string, it has already been translated because it is server error -function getErrorMessageWithTranslationData(error: Localize.MaybePhraseKey): Localize.MaybePhraseKey { - return typeof error === 'string' ? [error, {isTranslated: true}] : error; +function getErrorMessageWithTranslationData(error: string): string { + return error; } type OnyxDataWithErrors = { errors?: Errors | null; }; -function getLatestErrorMessage(onyxData: TOnyxData | null): Localize.MaybePhraseKey { +function getLatestErrorMessage(onyxData: TOnyxData | null): string { const errors = onyxData?.errors ?? {}; if (Object.keys(errors).length === 0) { @@ -69,7 +69,7 @@ function getLatestErrorMessage(onyxData: T } const key = Object.keys(errors).sort().reverse()[0]; - return getErrorMessageWithTranslationData(errors[key]); + return getErrorMessageWithTranslationData(errors[key] ?? ''); } function getLatestErrorMessageField(onyxData: TOnyxData): Errors { @@ -148,21 +148,20 @@ function getErrorsWithTranslationData(errors: Localize.MaybePhraseKey | Errors): * @param errors - An object containing current errors in the form * @param message - Message to assign to the inputID errors */ -function addErrorMessage(errors: Errors, inputID?: string | null, message?: TKey | Localize.MaybePhraseKey) { +function addErrorMessage(errors: Errors, inputID?: string | null, message?: string) { if (!message || !inputID) { return; } const errorList = errors; const error = errorList[inputID]; - const translatedMessage = Localize.translateIfPhraseKey(message); if (!error) { - errorList[inputID] = [translatedMessage, {isTranslated: true}]; + errorList[inputID] = [message]; } else if (typeof error === 'string') { - errorList[inputID] = [`${error}\n${translatedMessage}`, {isTranslated: true}]; + errorList[inputID] = [`${error}\n${message}`]; } else if (Array.isArray(error)) { - error[0] = `${error[0]}\n${translatedMessage}`; + error[0] = `${error[0]}\n${message}`; } } diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts index 13fe326c2c1c..7fe73526a1a5 100644 --- a/src/libs/ValidationUtils.ts +++ b/src/libs/ValidationUtils.ts @@ -11,7 +11,7 @@ import type {OnyxFormKey} from '@src/ONYXKEYS'; import type {Report, TaxRates} from '@src/types/onyx'; import * as CardUtils from './CardUtils'; import DateUtils from './DateUtils'; -import type {MaybePhraseKey} from './Localize'; +import * as Localize from './Localize'; import * as LoginUtils from './LoginUtils'; import {parsePhoneNumber} from './PhoneNumber'; import StringUtils from './StringUtils'; @@ -112,7 +112,7 @@ function getFieldRequiredErrors(values: FormOnyxVal return; } - errors[fieldKey] = 'common.error.fieldRequired'; + errors[fieldKey] = Localize.translateLocal('common.error.fieldRequired'); }); return errors; @@ -191,7 +191,7 @@ function meetsMaximumAgeRequirement(date: string): boolean { /** * Validate that given date is in a specified range of years before now. */ -function getAgeRequirementError(date: string, minimumAge: number, maximumAge: number): MaybePhraseKey { +function getAgeRequirementError(date: string, minimumAge: number, maximumAge: number): Localize.MaybePhraseKey { const currentDate = startOfDay(new Date()); const testDate = parse(date, CONST.DATE.FNS_FORMAT_STRING, currentDate); @@ -222,14 +222,14 @@ function getDatePassedError(inputDate: string): string { // If input date is not valid, return an error if (!isValid(parsedDate)) { - return 'common.error.dateInvalid'; + return Localize.translateLocal('common.error.dateInvalid'); } // Clear time for currentDate so comparison is based solely on the date currentDate.setHours(0, 0, 0, 0); if (parsedDate < currentDate) { - return 'common.error.dateInvalid'; + return Localize.translateLocal('common.error.dateInvalid'); } return ''; diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index f8425cd0c40c..fd7fbe4e7d86 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -12,6 +12,7 @@ import INPUT_IDS from '@src/types/form/WorkspaceNewTaxForm'; import type {Policy, TaxRate, TaxRates} from '@src/types/onyx'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {OnyxData} from '@src/types/onyx/Request'; +import { translateLocal } from '@libs/Localize'; let allPolicies: OnyxCollection; Onyx.connect({ @@ -39,7 +40,7 @@ const validateTaxName = (policy: Policy, values: FormOnyxValues) => { const errors: FormInputErrors = {}; if (isRequired && value[fieldKey].trim() === '') { - errors[fieldKey] = 'common.error.fieldRequired'; + errors[fieldKey] = translate('common.error.fieldRequired'); } return errors; }, - [fieldKey, isRequired], + [fieldKey, isRequired, translate], ); return ( diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index 4756db4d43ec..cc41738fa581 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -76,32 +76,32 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO if (values.dob) { if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.dob'; + errors.dob = translate('bankAccount.error.dob'); } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.age'; + errors.dob = translate('bankAccount.error.age'); } } if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { - errors.addressStreet = 'bankAccount.error.addressStreet'; + errors.addressStreet = translate('bankAccount.error.addressStreet'); } if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { - errors.addressZipCode = 'bankAccount.error.zipCode'; + errors.addressZipCode = translate('bankAccount.error.zipCode'); } if (values.phoneNumber && !ValidationUtils.isValidUSPhone(values.phoneNumber, true)) { - errors.phoneNumber = 'bankAccount.error.phoneNumber'; + errors.phoneNumber = translate('bankAccount.error.phoneNumber'); } // walletAdditionalDetails stores errors returned by the server. If the server returns an SSN error // then the user needs to provide the full 9 digit SSN. if (walletAdditionalDetails?.errorCode === CONST.WALLET.ERROR.SSN) { if (values.ssn && !ValidationUtils.isValidSSNFullNine(values.ssn)) { - errors.ssn = 'additionalDetailsStep.ssnFull9Error'; + errors.ssn = translate('additionalDetailsStep.ssnFull9Error'); } } else if (values.ssn && !ValidationUtils.isValidSSNLastFour(values.ssn)) { - errors.ssn = 'bankAccount.error.ssnLast4'; + errors.ssn = translate('bankAccount.error.ssnLast4'); } return errors; diff --git a/src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx b/src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx index fe17ea7e1afb..261613ba9318 100644 --- a/src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx +++ b/src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx @@ -48,7 +48,7 @@ function TermsStep() { const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); - const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(walletTerms ?? {}) ?? ''; + const errorMessage = error ? translate('common.error.acceptTerms') : ErrorUtils.getLatestErrorMessage(walletTerms ?? {}) ?? ''; const toggleDisclosure = () => { setHasAcceptedDisclosure(!hasAcceptedDisclosure); diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx index cfd0f4c5e3f7..6d3a1ebe9d89 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx @@ -19,20 +19,6 @@ import INPUT_IDS from '@src/types/form/WalletAdditionalDetailsForm'; const PERSONAL_INFO_DOB_KEY = INPUT_IDS.PERSONAL_INFO_STEP.DOB; const STEP_FIELDS = [PERSONAL_INFO_DOB_KEY]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.dob) { - if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.dob'; - } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.age'; - } - } - - return errors; -}; - const minDate = subYears(new Date(), CONST.DATE_BIRTH.MAX_AGE); const maxDate = subYears(new Date(), CONST.DATE_BIRTH.MIN_AGE_FOR_PAYMENT); @@ -40,6 +26,20 @@ function DateOfBirthStep({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.dob) { + if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.dob'); + } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.age'); + } + } + + return errors; + }; + const [walletAdditionalDetails] = useOnyx(ONYXKEYS.WALLET_ADDITIONAL_DETAILS); const dobDefaultValue = walletAdditionalDetails?.[PERSONAL_INFO_DOB_KEY] ?? walletAdditionalDetails?.[PERSONAL_INFO_DOB_KEY] ?? ''; diff --git a/src/pages/EnablePayments/TermsStep.tsx b/src/pages/EnablePayments/TermsStep.tsx index 916a5200a2e0..b2afb8b49fd9 100644 --- a/src/pages/EnablePayments/TermsStep.tsx +++ b/src/pages/EnablePayments/TermsStep.tsx @@ -58,7 +58,7 @@ function TermsStep(props: TermsStepProps) { const [error, setError] = useState(false); const {translate} = useLocalize(); - const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms ?? {}) ?? ''; + const errorMessage = error ? translate('common.error.acceptTerms') : ErrorUtils.getLatestErrorMessage(props.walletTerms ?? {}) ?? ''; const toggleDisclosure = () => { setHasAcceptedDisclosure(!hasAcceptedDisclosure); diff --git a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx index 31ff883834cc..04281eef0d2e 100644 --- a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx +++ b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx @@ -83,7 +83,7 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, on Navigation.navigate(ROUTES.ONBOARDING_PERSONAL_DETAILS); }, [selectedPurpose]); - const [errorMessage, setErrorMessage] = useState<'onboarding.purpose.errorSelection' | 'onboarding.purpose.errorContinue' | ''>(''); + const [errorMessage, setErrorMessage] = useState(''); const menuItems: MenuItemProps[] = Object.values(CONST.ONBOARDING_CHOICES).map((choice) => { const translationKey = `onboarding.purpose.${choice}` as const; @@ -110,11 +110,11 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, on const handleOuterClick = useCallback(() => { if (!selectedPurpose) { - setErrorMessage('onboarding.purpose.errorSelection'); + setErrorMessage(translate('onboarding.purpose.errorSelection')); } else { - setErrorMessage('onboarding.purpose.errorContinue'); + setErrorMessage(translate('onboarding.purpose.errorContinue')); } - }, [selectedPurpose]); + }, [selectedPurpose, setErrorMessage, translate]); const onboardingLocalRef = useRef(null); useImperativeHandle(isFocused ? OnboardingRefManager.ref : onboardingLocalRef, () => ({handleOuterClick}), [handleOuterClick]); @@ -147,7 +147,7 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, on buttonText={translate('common.continue')} onSubmit={() => { if (!selectedPurpose) { - setErrorMessage('onboarding.purpose.errorSelection'); + setErrorMessage(translate('onboarding.purpose.errorSelection')); return; } setErrorMessage(''); diff --git a/src/pages/ReimbursementAccount/AddressFormFields.tsx b/src/pages/ReimbursementAccount/AddressFormFields.tsx index 48af00cd4925..2133c4c5bf2e 100644 --- a/src/pages/ReimbursementAccount/AddressFormFields.tsx +++ b/src/pages/ReimbursementAccount/AddressFormFields.tsx @@ -52,7 +52,7 @@ function AddressFormFields({shouldSaveDraft = false, defaultValues, values, erro value={values?.street} defaultValue={defaultValues?.street} onInputChange={onFieldChange} - errorText={errors?.street ? 'bankAccount.error.addressStreet' : ''} + errorText={errors?.street ? translate('bankAccount.error.addressStreet') : ''} renamedInputKeys={inputKeys} maxInputLength={CONST.FORM_CHARACTER_LIMIT} isLimitedToUSA @@ -68,7 +68,7 @@ function AddressFormFields({shouldSaveDraft = false, defaultValues, values, erro value={values?.city} defaultValue={defaultValues?.city} onChangeText={(value) => onFieldChange?.({city: value})} - errorText={errors?.city ? 'bankAccount.error.addressCity' : ''} + errorText={errors?.city ? translate('bankAccount.error.addressCity') : ''} containerStyles={styles.mt6} /> @@ -94,7 +94,7 @@ function AddressFormFields({shouldSaveDraft = false, defaultValues, values, erro value={values?.zipCode} defaultValue={defaultValues?.zipCode} onChangeText={(value) => onFieldChange?.({zipCode: value})} - errorText={errors?.zipCode ? 'bankAccount.error.zipCode' : ''} + errorText={errors?.zipCode ? translate('bankAccount.error.zipCode') : ''} maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} hint={['common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}]} containerStyles={styles.mt3} diff --git a/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO.tsx b/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO.tsx index f563692f0ae9..2173d19887ad 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO.tsx +++ b/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO.tsx @@ -40,9 +40,9 @@ function DateOfBirthUBO({reimbursementAccountDraft, onNext, isEditing, beneficia if (values[dobInputID]) { if (!ValidationUtils.isValidPastDate(values[dobInputID]) || !ValidationUtils.meetsMaximumAgeRequirement(values[dobInputID])) { - errors[dobInputID] = 'bankAccount.error.dob'; + errors[dobInputID] = translate('bankAccount.error.dob'); } else if (!ValidationUtils.meetsMinimumAgeRequirement(values[dobInputID])) { - errors[dobInputID] = 'bankAccount.error.age'; + errors[dobInputID] = translate('bankAccount.error.age'); } } diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx index 6311a63a4059..5e0cd2f700c7 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx @@ -37,16 +37,6 @@ type States = keyof typeof COMMON_CONST.STATES; const BUSINESS_INFO_STEP_KEYS = INPUT_IDS.BUSINESS_INFO_STEP; const BUSINESS_INFO_STEP_INDEXES = CONST.REIMBURSEMENT_ACCOUNT.SUBSTEP_INDEX.BUSINESS_INFO; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]); - - if (!values.hasNoConnectionToCannabis) { - errors.hasNoConnectionToCannabis = 'bankAccount.error.restrictedBusiness'; - } - - return errors; -}; - function ConfirmCompanyLabel() { const {translate} = useLocalize(); @@ -62,6 +52,16 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]); + + if (!values.hasNoConnectionToCannabis) { + errors.hasNoConnectionToCannabis = translate('bankAccount.error.restrictedBusiness'); + } + + return errors; + }; + const values = useMemo(() => getSubstepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const defaultCheckboxState = reimbursementAccountDraft?.[BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS] ?? false; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx index 8fecbe46164f..14a6d03e0670 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx @@ -29,22 +29,22 @@ type IncorporationDateBusinessProps = IncorporationDateBusinessOnyxProps & SubSt const COMPANY_INCORPORATION_DATE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.INCORPORATION_DATE; const STEP_FIELDS = [COMPANY_INCORPORATION_DATE_KEY]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { - errors.incorporationDate = 'common.error.dateInvalid'; - } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) { - errors.incorporationDate = 'bankAccount.error.incorporationDateFuture'; - } - - return errors; -}; - function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, isEditing}: IncorporationDateBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { + errors.incorporationDate = translate('common.error.dateInvalid'); + } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) { + errors.incorporationDate = translate('bankAccount.error.incorporationDateFuture'); + } + + return errors; + }; + const defaultCompanyIncorporationDate = reimbursementAccount?.achData?.incorporationDate ?? reimbursementAccountDraft?.incorporationDate ?? ''; const handleSubmit = useReimbursementAccountStepFormSubmit({ diff --git a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx index 03a178f186ee..94d006d72f26 100644 --- a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx +++ b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx @@ -30,24 +30,6 @@ const STEP_FIELDS = [ INPUT_IDS.COMPLETE_VERIFICATION.CERTIFY_TRUE_INFORMATION, ]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (!ValidationUtils.isRequiredFulfilled(values.acceptTermsAndConditions)) { - errors.acceptTermsAndConditions = 'common.error.acceptTerms'; - } - - if (!ValidationUtils.isRequiredFulfilled(values.certifyTrueInformation)) { - errors.certifyTrueInformation = 'completeVerificationStep.certifyTrueAndAccurateError'; - } - - if (!ValidationUtils.isRequiredFulfilled(values.isAuthorizedToUseBankAccount)) { - errors.isAuthorizedToUseBankAccount = 'completeVerificationStep.isAuthorizedToUseBankAccountError'; - } - - return errors; -}; - function IsAuthorizedToUseBankAccountLabel() { const {translate} = useLocalize(); return {translate('completeVerificationStep.isAuthorizedToUseBankAccount')}; @@ -76,6 +58,23 @@ function ConfirmAgreements({onNext, reimbursementAccount}: ConfirmAgreementsProp certifyTrueInformation: reimbursementAccount?.achData?.certifyTrueInformation ?? false, acceptTermsAndConditions: reimbursementAccount?.achData?.acceptTermsAndConditions ?? false, }; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (!ValidationUtils.isRequiredFulfilled(values.acceptTermsAndConditions)) { + errors.acceptTermsAndConditions = translate('common.error.acceptTerms'); + } + + if (!ValidationUtils.isRequiredFulfilled(values.certifyTrueInformation)) { + errors.certifyTrueInformation = translate('completeVerificationStep.certifyTrueAndAccurateError'); + } + + if (!ValidationUtils.isRequiredFulfilled(values.isAuthorizedToUseBankAccount)) { + errors.isAuthorizedToUseBankAccount = translate('completeVerificationStep.isAuthorizedToUseBankAccountError'); + } + + return errors; + }; return ( ): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.dob) { - if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.dob'; - } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.age'; - } - } - - return errors; -}; - function DateOfBirth({reimbursementAccount, reimbursementAccountDraft, onNext, isEditing}: DateOfBirthProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.dob) { + if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.dob'); + } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.age'); + } + } + + return errors; + }; + const dobDefaultValue = reimbursementAccount?.achData?.[PERSONAL_INFO_DOB_KEY] ?? reimbursementAccountDraft?.[PERSONAL_INFO_DOB_KEY] ?? ''; const minDate = subYears(new Date(), CONST.DATE_BIRTH.MAX_AGE); diff --git a/src/pages/Travel/TravelTerms.tsx b/src/pages/Travel/TravelTerms.tsx index 468ca9b8082a..9f26284848a4 100644 --- a/src/pages/Travel/TravelTerms.tsx +++ b/src/pages/Travel/TravelTerms.tsx @@ -23,7 +23,7 @@ function TravelTerms() { const [hasAcceptedTravelTerms, setHasAcceptedTravelTerms] = useState(false); const [error, setError] = useState(false); - const errorMessage = error ? 'travel.termsAndConditions.error' : ''; + const errorMessage = error ? translate('travel.termsAndConditions.error') : ''; const toggleTravelTerms = () => { setHasAcceptedTravelTerms(!hasAcceptedTravelTerms); diff --git a/src/pages/iou/MoneyRequestAmountForm.tsx b/src/pages/iou/MoneyRequestAmountForm.tsx index 46bd34006550..07037a09df11 100644 --- a/src/pages/iou/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/MoneyRequestAmountForm.tsx @@ -16,7 +16,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; -import type {MaybePhraseKey} from '@libs/Localize'; import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {BaseTextInputRef} from '@src/components/TextInput/BaseTextInput/types'; @@ -98,7 +97,7 @@ function MoneyRequestAmountForm( const textInput = useRef(null); const moneyRequestAmountInput = useRef(null); - const [formError, setFormError] = useState(''); + const [formError, setFormError] = useState(''); const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true); const isFocused = useIsFocused(); @@ -209,12 +208,12 @@ function MoneyRequestAmountForm( // Skip the check for tax amount form as 0 is a valid input const currentAmount = moneyRequestAmountInput.current?.getAmount() ?? ''; if (!currentAmount.length || (!isTaxAmountForm && isAmountInvalid(currentAmount))) { - setFormError('iou.error.invalidAmount'); + setFormError(translate('iou.error.invalidAmount')); return; } if (isTaxAmountInvalid(currentAmount, taxAmount, isTaxAmountForm)) { - setFormError(['iou.error.invalidTaxAmount', {amount: formattedTaxAmount}]); + setFormError([translate('iou.error.invalidTaxAmount'), {amount: formattedTaxAmount}]); return; } @@ -225,7 +224,7 @@ function MoneyRequestAmountForm( onSubmitButtonPress({amount: currentAmount, currency, paymentMethod: iouPaymentType}); }, - [taxAmount, onSubmitButtonPress, currency, formattedTaxAmount, initializeAmount], + [taxAmount, initializeAmount, onSubmitButtonPress, currency, translate, formattedTaxAmount], ); const buttonText: string = useMemo(() => { diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 1d9aec1ea60d..3e8cffd3869a 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -309,7 +309,7 @@ function MoneyRequestParticipantsSelector({participants = [], onFinish, onPartic )} diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx b/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx index 13d03fd557e9..b44f5d9e0610 100644 --- a/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx @@ -135,7 +135,7 @@ function CodesStep({account, backTo}: CodesStepProps) { text={translate('common.next')} onPress={() => { if (!account?.codesAreCopied) { - setError('twoFactorAuth.errorStepCodes'); + setError(translate('twoFactorAuth.errorStepCodes')); return; } setStep(CONST.TWO_FACTOR_AUTH_STEPS.VERIFY); diff --git a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx index 2710cadf94e4..bd6fa17bff34 100644 --- a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx +++ b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx @@ -105,7 +105,7 @@ function ActivatePhysicalCardPage({ activateCardCodeInputRef.current?.blur(); if (lastFourDigits.replace(CONST.MAGIC_CODE_EMPTY_CHAR, '').length !== LAST_FOUR_DIGITS_LENGTH) { - setFormError('activateCardPage.error.thatDidntMatch'); + setFormError(translate('activateCardPage.error.thatDidntMatch')); return; } if (inactiveCard?.cardID === undefined) { diff --git a/src/pages/settings/Wallet/AddDebitCardPage.tsx b/src/pages/settings/Wallet/AddDebitCardPage.tsx index 0beb3c16018d..b3bc1d839727 100644 --- a/src/pages/settings/Wallet/AddDebitCardPage.tsx +++ b/src/pages/settings/Wallet/AddDebitCardPage.tsx @@ -89,31 +89,31 @@ function DebitCardPage({formData}: DebitCardPageProps) { const errors = ValidationUtils.getFieldRequiredErrors(values, REQUIRED_FIELDS); if (values.nameOnCard && !ValidationUtils.isValidLegalName(values.nameOnCard)) { - errors.nameOnCard = 'addDebitCardPage.error.invalidName'; + errors.nameOnCard = translate('addDebitCardPage.error.invalidName'); } if (values.cardNumber && !ValidationUtils.isValidDebitCard(values.cardNumber.replace(/ /g, ''))) { - errors.cardNumber = 'addDebitCardPage.error.debitCardNumber'; + errors.cardNumber = translate('addDebitCardPage.error.debitCardNumber'); } if (values.expirationDate && !ValidationUtils.isValidExpirationDate(values.expirationDate)) { - errors.expirationDate = 'addDebitCardPage.error.expirationDate'; + errors.expirationDate = translate('addDebitCardPage.error.expirationDate'); } if (values.securityCode && !ValidationUtils.isValidSecurityCode(values.securityCode)) { - errors.securityCode = 'addDebitCardPage.error.securityCode'; + errors.securityCode = translate('addDebitCardPage.error.securityCode'); } if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { - errors.addressStreet = 'addDebitCardPage.error.addressStreet'; + errors.addressStreet = translate('addDebitCardPage.error.addressStreet'); } if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { - errors.addressZipCode = 'addDebitCardPage.error.addressZipCode'; + errors.addressZipCode = translate('addDebitCardPage.error.addressZipCode'); } if (!values.acceptTerms) { - errors.acceptTerms = 'common.error.acceptTerms'; + errors.acceptTerms = translate('common.error.acceptTerms'); } return errors; diff --git a/src/pages/settings/Wallet/ReportCardLostPage.tsx b/src/pages/settings/Wallet/ReportCardLostPage.tsx index 11790bd44cb6..813f09af74d5 100644 --- a/src/pages/settings/Wallet/ReportCardLostPage.tsx +++ b/src/pages/settings/Wallet/ReportCardLostPage.tsx @@ -183,7 +183,7 @@ function ReportCardLostPage({ @@ -201,7 +201,7 @@ function ReportCardLostPage({ diff --git a/src/pages/signin/LoginForm/BaseLoginForm.tsx b/src/pages/signin/LoginForm/BaseLoginForm.tsx index 4286a2603341..9e4b3e487718 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.tsx +++ b/src/pages/signin/LoginForm/BaseLoginForm.tsx @@ -31,7 +31,6 @@ import * as CloseAccount from '@userActions/CloseAccount'; import * as Session from '@userActions/Session'; import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; -import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import type {CloseAccountForm} from '@src/types/form'; import type {Account, Credentials} from '@src/types/onyx'; @@ -59,7 +58,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false const {translate} = useLocalize(); const input = useRef(null); const [login, setLogin] = useState(() => Str.removeSMSDomain(credentials?.login ?? '')); - const [formError, setFormError] = useState(); + const [formError, setFormError] = useState(); const prevIsVisible = usePrevious(isVisible); const firstBlurred = useRef(false); const isFocused = useIsFocused(); @@ -73,7 +72,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false (value: string) => { const loginTrim = value.trim(); if (!loginTrim) { - setFormError('common.pleaseEnterEmailOrPhoneNumber'); + setFormError(translate('common.pleaseEnterEmailOrPhoneNumber')); return false; } @@ -82,9 +81,9 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false if (!Str.isValidEmail(loginTrim) && !parsedPhoneNumber.possible) { if (ValidationUtils.isNumericWithSpecialChars(loginTrim)) { - setFormError('common.error.phoneNumber'); + setFormError(translate('common.error.phoneNumber')); } else { - setFormError('loginForm.error.invalidFormatEmailLogin'); + setFormError(translate('loginForm.error.invalidFormatEmailLogin')); } return false; } @@ -92,7 +91,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false setFormError(undefined); return true; }, - [setFormError], + [setFormError, translate], ); /** diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx index 488d3d48eae9..7aaa5a03576b 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -323,7 +323,7 @@ function BaseValidateCodeForm({account, credentials, session, autoComplete, isUs onChangeText={(text) => onTextInput(text, 'twoFactorAuthCode')} onFulfill={validateAndSubmitForm} maxLength={CONST.TFA_CODE_LENGTH} - errorText={formError?.twoFactorAuthCode ?? ''} + errorText={formError?.twoFactorAuthCode ? translate(formError?.twoFactorAuthCode) : ''} hasError={hasError} autoFocus key="twoFactorAuthCode" @@ -356,7 +356,7 @@ function BaseValidateCodeForm({account, credentials, session, autoComplete, isUs value={validateCode} onChangeText={(text) => onTextInput(text, 'validateCode')} onFulfill={validateAndSubmitForm} - errorText={formError?.validateCode ?? ''} + errorText={formError?.validateCode ? translate(formError?.validateCode) : ''} hasError={hasError} autoFocus key="validateCode" diff --git a/src/pages/tasks/NewTaskPage.tsx b/src/pages/tasks/NewTaskPage.tsx index d038e8260418..9fdb0ae67a65 100644 --- a/src/pages/tasks/NewTaskPage.tsx +++ b/src/pages/tasks/NewTaskPage.tsx @@ -99,17 +99,17 @@ function NewTaskPage({task, reports, personalDetails}: NewTaskPageProps) { // the response const onSubmit = () => { if (!task?.title && !task?.shareDestination) { - setErrorMessage('newTaskPage.confirmError'); + setErrorMessage(translate('newTaskPage.confirmError')); return; } if (!task.title) { - setErrorMessage('newTaskPage.pleaseEnterTaskName'); + setErrorMessage(translate('newTaskPage.pleaseEnterTaskName')); return; } if (!task.shareDestination) { - setErrorMessage('newTaskPage.pleaseEnterTaskDestination'); + setErrorMessage(translate('newTaskPage.pleaseEnterTaskDestination')); return; } diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 9142361a531e..f1dbbf1047f4 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -277,7 +277,7 @@ function WorkspaceInvitePage({route, betas, invitedEmailsToAccountIDsDraft, poli isAlertVisible={shouldShowAlertPrompt} buttonText={translate('common.next')} onSubmit={inviteUser} - message={[policy?.alertMessage ?? '', {isTranslated: true}]} + message={policy?.alertMessage ?? ''} containerStyles={[styles.flexReset, styles.flexGrow0, styles.flexShrink0, styles.flexBasisAuto]} enabledWhenOffline disablePressOnEnter diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index c537ee50d19b..26c87bd0ed4f 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -411,7 +411,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, Policy.dismissAddedWithPrimaryLoginMessages(policyID)} /> diff --git a/src/pages/workspace/WorkspaceNewRoomPage.tsx b/src/pages/workspace/WorkspaceNewRoomPage.tsx index 382c1dde6d47..cf5d3c1fb3aa 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.tsx +++ b/src/pages/workspace/WorkspaceNewRoomPage.tsx @@ -169,18 +169,18 @@ function WorkspaceNewRoomPage({policies, reports, formState, session, activePoli if (!values.roomName || values.roomName === CONST.POLICY.ROOM_PREFIX) { // We error if the user doesn't enter a room name or left blank - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.pleaseEnterRoomName'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.pleaseEnterRoomName')); } else if (values.roomName !== CONST.POLICY.ROOM_PREFIX && !ValidationUtils.isValidRoomName(values.roomName)) { // We error if the room name has invalid characters - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomNameInvalidError'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomNameInvalidError')); } else if (ValidationUtils.isReservedRoomName(values.roomName)) { // Certain names are reserved for default rooms and should not be used for policy rooms. - ErrorUtils.addErrorMessage(errors, 'roomName', ['newRoomPage.roomNameReservedError', {reservedName: values.roomName}]); + ErrorUtils.addErrorMessage(errors, 'roomName', [translate('newRoomPage.roomNameReservedError'), {reservedName: values.roomName}]); } else if (ValidationUtils.isExistingRoomName(values.roomName, reports, values.policyID ?? '')) { // Certain names are reserved for default rooms and should not be used for policy rooms. - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomAlreadyExistsError'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomAlreadyExistsError')); } else if (values.roomName.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'roomName', ['common.error.characterLimitExceedCounter', {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'roomName', [translate('common.error.characterLimitExceedCounter'), {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); } const descriptionLength = ReportUtils.getCommentLength(values.reportDescription); diff --git a/src/stories/Form.stories.tsx b/src/stories/Form.stories.tsx index f4e89f6766f0..ab29612b0556 100644 --- a/src/stories/Form.stories.tsx +++ b/src/stories/Form.stories.tsx @@ -12,7 +12,6 @@ import Picker from '@components/Picker'; import StateSelector from '@components/StateSelector'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; -import type {MaybePhraseKey} from '@libs/Localize'; import NetworkConnection from '@libs/NetworkConnection'; import * as ValidationUtils from '@libs/ValidationUtils'; import * as FormActions from '@userActions/FormActions'; @@ -58,7 +57,7 @@ function Template(props: FormProviderProps) { FormActions.setDraftValues(props.formID, props.draftValues); if (props.formState?.error) { - FormActions.setErrors(props.formID, {error: props.formState.error as MaybePhraseKey}); + FormActions.setErrors(props.formID, {error: props.formState.error as string}); } else { FormActions.clearErrors(props.formID); } @@ -172,7 +171,7 @@ function WithNativeEventHandler(props: FormProviderProps) { FormActions.setDraftValues(props.formID, props.draftValues); if (props.formState?.error) { - FormActions.setErrors(props.formID, {error: props.formState.error as MaybePhraseKey}); + FormActions.setErrors(props.formID, {error: props.formState.error as string}); } else { FormActions.clearErrors(props.formID); } diff --git a/src/types/onyx/OnyxCommon.ts b/src/types/onyx/OnyxCommon.ts index 8b96a89a2a1b..37a06f20ca63 100644 --- a/src/types/onyx/OnyxCommon.ts +++ b/src/types/onyx/OnyxCommon.ts @@ -1,7 +1,7 @@ import type {ValueOf} from 'type-fest'; -import type {MaybePhraseKey} from '@libs/Localize'; import type {AvatarSource} from '@libs/UserUtils'; import type CONST from '@src/CONST'; +import type { MaybePhraseKey } from '@libs/Localize'; type PendingAction = ValueOf | null; @@ -19,7 +19,7 @@ type OnyxValueWithOfflineFeedback = keyof TO type ErrorFields = Record; -type Errors = Record; +type Errors = Record; type AvatarType = typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE; From 7010adfa191473171f573d8cdb742e20a62107fb Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 13:02:54 +0700 Subject: [PATCH 02/24] Fix translate error for DotIndicatorMessage --- src/components/AddressForm.tsx | 73 ++++++++++--------- src/components/DotIndicatorMessage.tsx | 11 ++- src/components/MessagesRow.tsx | 3 +- .../MoneyRequestConfirmationList.tsx | 20 ++++- src/components/OfflineWithFeedback.tsx | 10 +-- src/components/PDFView/PDFPasswordForm.tsx | 2 +- src/libs/ErrorUtils.ts | 24 +++--- src/libs/actions/IOU.ts | 4 +- src/libs/actions/TaxRate.ts | 2 +- .../PersonalInfo/substeps/DateOfBirthStep.tsx | 4 +- .../substeps/ConfirmationBusiness.tsx | 2 +- .../substeps/IncorporationDateBusiness.tsx | 4 +- .../substeps/ConfirmAgreements.tsx | 8 +- .../PersonalInfo/substeps/DateOfBirth.tsx | 4 +- .../MoneyRequestParticipantsSelector.tsx | 2 +- .../request/step/IOURequestStepDistance.tsx | 2 +- .../Contacts/ContactMethodDetailsPage.tsx | 2 +- .../Wallet/ActivatePhysicalCardPage.tsx | 2 +- .../settings/Wallet/ReportCardLostPage.tsx | 4 +- src/pages/signin/LoginForm/BaseLoginForm.tsx | 2 +- src/pages/workspace/WorkspaceNewRoomPage.tsx | 15 ++-- src/types/onyx/OnyxCommon.ts | 1 - 22 files changed, 107 insertions(+), 94 deletions(-) diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index bd3ad7ea0888..dc5c47ad182c 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -88,50 +88,53 @@ function AddressForm({ * @returns - An object containing the errors for each inputID */ - const validator = useCallback((values: FormOnyxValues): Errors => { - const errors: Errors & { - zipPostCode?: string | string[]; - } = {}; - const requiredFields = ['addressLine1', 'city', 'country', 'state'] as const; - - // Check "State" dropdown is a valid state if selected Country is USA - if (values.country === CONST.COUNTRY.US && !values.state) { - errors.state = translate('common.error.fieldRequired'); - } - - // Add "Field required" errors if any required field is empty - requiredFields.forEach((fieldKey) => { - const fieldValue = values[fieldKey] ?? ''; - if (ValidationUtils.isRequiredFulfilled(fieldValue)) { - return; + const validator = useCallback( + (values: FormOnyxValues): Errors => { + const errors: Errors & { + zipPostCode?: string | string[]; + } = {}; + const requiredFields = ['addressLine1', 'city', 'country', 'state'] as const; + + // Check "State" dropdown is a valid state if selected Country is USA + if (values.country === CONST.COUNTRY.US && !values.state) { + errors.state = translate('common.error.fieldRequired'); } - errors[fieldKey] = translate('common.error.fieldRequired'); - }); + // Add "Field required" errors if any required field is empty + requiredFields.forEach((fieldKey) => { + const fieldValue = values[fieldKey] ?? ''; + if (ValidationUtils.isRequiredFulfilled(fieldValue)) { + return; + } + + errors[fieldKey] = translate('common.error.fieldRequired'); + }); - // If no country is selected, default value is an empty string and there's no related regex data so we default to an empty object - const countryRegexDetails = (values.country ? CONST.COUNTRY_ZIP_REGEX_DATA?.[values.country] : {}) as CountryZipRegex; + // If no country is selected, default value is an empty string and there's no related regex data so we default to an empty object + const countryRegexDetails = (values.country ? CONST.COUNTRY_ZIP_REGEX_DATA?.[values.country] : {}) as CountryZipRegex; - // The postal code system might not exist for a country, so no regex either for them. - const countrySpecificZipRegex = countryRegexDetails?.regex; - const countryZipFormat = countryRegexDetails?.samples ?? ''; + // The postal code system might not exist for a country, so no regex either for them. + const countrySpecificZipRegex = countryRegexDetails?.regex; + const countryZipFormat = countryRegexDetails?.samples ?? ''; - ErrorUtils.addErrorMessage(errors, 'firstName', 'bankAccount.error.firstName'); + ErrorUtils.addErrorMessage(errors, 'firstName', 'bankAccount.error.firstName'); - if (countrySpecificZipRegex) { - if (!countrySpecificZipRegex.test(values.zipPostCode?.trim().toUpperCase())) { - if (ValidationUtils.isRequiredFulfilled(values.zipPostCode?.trim())) { - errors.zipPostCode = ['privatePersonalDetails.error.incorrectZipFormat', countryZipFormat]; - } else { - errors.zipPostCode = 'common.error.fieldRequired'; + if (countrySpecificZipRegex) { + if (!countrySpecificZipRegex.test(values.zipPostCode?.trim().toUpperCase())) { + if (ValidationUtils.isRequiredFulfilled(values.zipPostCode?.trim())) { + errors.zipPostCode = ['privatePersonalDetails.error.incorrectZipFormat', countryZipFormat]; + } else { + errors.zipPostCode = 'common.error.fieldRequired'; + } } + } else if (!CONST.GENERIC_ZIP_CODE_REGEX.test(values?.zipPostCode?.trim()?.toUpperCase() ?? '')) { + errors.zipPostCode = 'privatePersonalDetails.error.incorrectZipFormat'; } - } else if (!CONST.GENERIC_ZIP_CODE_REGEX.test(values?.zipPostCode?.trim()?.toUpperCase() ?? '')) { - errors.zipPostCode = 'privatePersonalDetails.error.incorrectZipFormat'; - } - return errors; - }, [translate]); + return errors; + }, + [translate], + ); return ( ; + messages: Record; /** The type of message, 'error' shows a red dot, 'success' shows a green dot */ type: 'error' | 'success'; @@ -45,12 +44,12 @@ function DotIndicatorMessage({messages = {}, style, type, textStyles}: DotIndica } // Fetch the keys, sort them, and map through each key to get the corresponding message - const sortedMessages: Array = Object.keys(messages) + const sortedMessages: Array = Object.keys(messages) .sort() - .map((key) => messages[key]); - + .map((key) => messages[key]) + .filter((message): message is string | ReceiptError => message !== null); // Removing duplicates using Set and transforming the result into an array - const uniqueMessages: Array = [...new Set(sortedMessages)].map((message) => (isReceiptError(message) ? message : Localize.translateIfPhraseKey(message))); + const uniqueMessages: Array = [...new Set(sortedMessages)].map((message) => message); const isErrorMessage = type === 'error'; diff --git a/src/components/MessagesRow.tsx b/src/components/MessagesRow.tsx index 2aead5da334c..6a5be5db07bc 100644 --- a/src/components/MessagesRow.tsx +++ b/src/components/MessagesRow.tsx @@ -5,6 +5,7 @@ import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; +import type {ReceiptError} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import DotIndicatorMessage from './DotIndicatorMessage'; import Icon from './Icon'; @@ -14,7 +15,7 @@ import Tooltip from './Tooltip'; type MessagesRowProps = { /** The messages to display */ - messages: Record; + messages: Record; /** The type of message, 'error' shows a red dot, 'success' shows a green dot */ type: 'error' | 'success'; diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 31fcdaa4843e..c745ca34251d 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -738,7 +738,25 @@ function MoneyRequestConfirmationList({ onConfirm?.(selectedParticipants); } }, - [selectedParticipants, isEditingSplitBill, isMerchantRequired, isMerchantEmpty, shouldDisplayFieldError, transaction, iouCategory.length, formError, iouType, setFormError, translate, onSendMoney, iouCurrencyCode, isDistanceRequest, isDistanceRequestWithPendingRoute, iouAmount, onConfirm], + [ + selectedParticipants, + isEditingSplitBill, + isMerchantRequired, + isMerchantEmpty, + shouldDisplayFieldError, + transaction, + iouCategory.length, + formError, + iouType, + setFormError, + translate, + onSendMoney, + iouCurrencyCode, + isDistanceRequest, + isDistanceRequestWithPendingRoute, + iouAmount, + onConfirm, + ], ); const footerContent = useMemo(() => { diff --git a/src/components/OfflineWithFeedback.tsx b/src/components/OfflineWithFeedback.tsx index 1ff3ee2ed737..70354c4a4676 100644 --- a/src/components/OfflineWithFeedback.tsx +++ b/src/components/OfflineWithFeedback.tsx @@ -5,8 +5,6 @@ import {View} from 'react-native'; import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; -import type {MaybePhraseKey} from '@libs/Localize'; import mapChildrenFlat from '@libs/mapChildrenFlat'; import shouldRenderOffscreen from '@libs/shouldRenderOffscreen'; import type {AllStyles} from '@styles/utils/types'; @@ -63,10 +61,6 @@ type OfflineWithFeedbackProps = ChildrenProps & { type StrikethroughProps = Partial & {style: Array}; -function isMaybePhraseKeyType(message: unknown): message is MaybePhraseKey { - return typeof message === 'string' || Array.isArray(message); -} - function OfflineWithFeedback({ pendingAction, canDismissError = true, @@ -90,8 +84,8 @@ function OfflineWithFeedback({ // Some errors have a null message. This is used to apply opacity only and to avoid showing redundant messages. const errorEntries = Object.entries(errors ?? {}); - const filteredErrorEntries = errorEntries.filter((errorEntry): errorEntry is [string, MaybePhraseKey | ReceiptError] => errorEntry[1] !== null); - const errorMessages = mapValues(Object.fromEntries(filteredErrorEntries), (error) => (isMaybePhraseKeyType(error) ? ErrorUtils.getErrorMessageWithTranslationData(error) : error)); + const filteredErrorEntries = errorEntries.filter((errorEntry): errorEntry is [string, string | ReceiptError] => errorEntry[1] !== null); + const errorMessages = mapValues(Object.fromEntries(filteredErrorEntries), (error) => error); const hasErrorMessages = !isEmptyObject(errorMessages); const isOfflinePendingAction = !!isOffline && !!pendingAction; diff --git a/src/components/PDFView/PDFPasswordForm.tsx b/src/components/PDFView/PDFPasswordForm.tsx index e571c2830b3c..e212d79b27d6 100644 --- a/src/components/PDFView/PDFPasswordForm.tsx +++ b/src/components/PDFView/PDFPasswordForm.tsx @@ -53,7 +53,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid = false, shouldShowLoadin return validationErrorText; } return ''; - }, [isPasswordInvalid, validationErrorText]); + }, [isPasswordInvalid, validationErrorText, translate]); useEffect(() => { if (!isFocused) { diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index af27dd5801f3..2019d5d2daf5 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -1,11 +1,11 @@ import mapValues from 'lodash/mapValues'; import CONST from '@src/CONST'; -import type {TranslationFlatObject} from '@src/languages/types'; +import type {TranslationFlatObject, TranslationPaths} from '@src/languages/types'; import type {ErrorFields, Errors} from '@src/types/onyx/OnyxCommon'; import type Response from '@src/types/onyx/Response'; import type {ReceiptError} from '@src/types/onyx/Transaction'; import DateUtils from './DateUtils'; -import type * as Localize from './Localize'; +import * as Localize from './Localize'; function getAuthenticateErrorMessage(response: Response): keyof TranslationFlatObject { switch (response.jsonCode) { @@ -40,8 +40,8 @@ function getAuthenticateErrorMessage(response: Response): keyof TranslationFlatO * Method used to get an error object with microsecond as the key. * @param error - error key or message to be saved */ -function getMicroSecondOnyxError(error: string, isTranslated = false, errorKey?: number): Errors { - return {[errorKey ?? DateUtils.getMicroseconds()]: error && [error, {isTranslated}]}; +function getMicroSecondOnyxError(error: TranslationPaths, _isTranslated = false, errorKey?: number): Errors { + return {[errorKey ?? DateUtils.getMicroseconds()]: Localize.translateLocal(error)}; } /** @@ -53,8 +53,8 @@ function getMicroSecondOnyxErrorObject(error: Errors, errorKey?: number): ErrorF } // We can assume that if error is a string, it has already been translated because it is server error -function getErrorMessageWithTranslationData(error: string): string { - return error; +function getErrorMessageWithTranslationData(error: string | null): string { + return error ?? ''; } type OnyxDataWithErrors = { @@ -130,12 +130,12 @@ function getLatestErrorFieldForAnyField; Onyx.connect({ diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx index 6d3a1ebe9d89..7c4f5f43f2a1 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx @@ -28,7 +28,7 @@ function DateOfBirthStep({onNext, isEditing}: SubStepProps) { const validate = (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - + if (values.dob) { if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { errors.dob = translate('bankAccount.error.dob'); @@ -36,7 +36,7 @@ function DateOfBirthStep({onNext, isEditing}: SubStepProps) { errors.dob = translate('bankAccount.error.age'); } } - + return errors; }; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx index 5e0cd2f700c7..fa660c98d8bc 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx @@ -54,7 +54,7 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, const validate = (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]); - + if (!values.hasNoConnectionToCannabis) { errors.hasNoConnectionToCannabis = translate('bankAccount.error.restrictedBusiness'); } diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx index 14a6d03e0670..58a1feb710c2 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx @@ -35,13 +35,13 @@ function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDr const validate = (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - + if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { errors.incorporationDate = translate('common.error.dateInvalid'); } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) { errors.incorporationDate = translate('bankAccount.error.incorporationDateFuture'); } - + return errors; }; diff --git a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx index 94d006d72f26..1e2f004b9c8d 100644 --- a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx +++ b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx @@ -60,19 +60,19 @@ function ConfirmAgreements({onNext, reimbursementAccount}: ConfirmAgreementsProp }; const validate = (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - + if (!ValidationUtils.isRequiredFulfilled(values.acceptTermsAndConditions)) { errors.acceptTermsAndConditions = translate('common.error.acceptTerms'); } - + if (!ValidationUtils.isRequiredFulfilled(values.certifyTrueInformation)) { errors.certifyTrueInformation = translate('completeVerificationStep.certifyTrueAndAccurateError'); } - + if (!ValidationUtils.isRequiredFulfilled(values.isAuthorizedToUseBankAccount)) { errors.isAuthorizedToUseBankAccount = translate('completeVerificationStep.isAuthorizedToUseBankAccountError'); } - + return errors; }; diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx b/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx index 3c3ed7cee480..c47139af8a90 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx +++ b/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx @@ -38,7 +38,7 @@ function DateOfBirth({reimbursementAccount, reimbursementAccountDraft, onNext, i const validate = (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - + if (values.dob) { if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { errors.dob = translate('bankAccount.error.dob'); @@ -46,7 +46,7 @@ function DateOfBirth({reimbursementAccount, reimbursementAccountDraft, onNext, i errors.dob = translate('bankAccount.error.age'); } } - + return errors; }; diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 3e8cffd3869a..d3afa0ad3a36 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -309,7 +309,7 @@ function MoneyRequestParticipantsSelector({participants = [], onFinish, onPartic )} diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index b486510ead0a..e2f665c52cae 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -326,7 +326,7 @@ function IOURequestStepDistance({ return {duplicateWaypointsError: translate('iou.error.duplicateWaypointsErrorMessage')} as Errors; } if (atLeastTwoDifferentWaypointsError) { - return {atLeastTwoDifferentWaypointsError: 'iou.error.atLeastTwoDifferentWaypoints'} as Errors; + return {atLeastTwoDifferentWaypointsError: translate('iou.error.atLeastTwoDifferentWaypoints')} as Errors; } return {}; }; diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.tsx b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.tsx index 8aaeb7151563..0e392bb8b3c0 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.tsx +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.tsx @@ -231,7 +231,7 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) { type="success" style={[themeStyles.mb3]} // eslint-disable-next-line @typescript-eslint/naming-convention - messages={{0: ['contacts.enterMagicCode', {contactMethod: formattedContactMethod}]}} + messages={{0: translate('contacts.enterMagicCode', {contactMethod: formattedContactMethod})}} /> ; diff --git a/src/pages/settings/Wallet/ReportCardLostPage.tsx b/src/pages/settings/Wallet/ReportCardLostPage.tsx index 813f09af74d5..4a84f0294d78 100644 --- a/src/pages/settings/Wallet/ReportCardLostPage.tsx +++ b/src/pages/settings/Wallet/ReportCardLostPage.tsx @@ -183,7 +183,7 @@ function ReportCardLostPage({ @@ -201,7 +201,7 @@ function ReportCardLostPage({ diff --git a/src/pages/signin/LoginForm/BaseLoginForm.tsx b/src/pages/signin/LoginForm/BaseLoginForm.tsx index 9e4b3e487718..097bb843402a 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.tsx +++ b/src/pages/signin/LoginForm/BaseLoginForm.tsx @@ -265,7 +265,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false style={[styles.mv2]} type="success" // eslint-disable-next-line @typescript-eslint/naming-convention,@typescript-eslint/prefer-nullish-coalescing - messages={{0: closeAccount?.success ? [closeAccount.success, {isTranslated: true}] : account?.message || ''}} + messages={{0: closeAccount?.success ? closeAccount.success : account?.message || ''}} /> )} { diff --git a/src/pages/workspace/WorkspaceNewRoomPage.tsx b/src/pages/workspace/WorkspaceNewRoomPage.tsx index cf5d3c1fb3aa..436edd0f1c89 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.tsx +++ b/src/pages/workspace/WorkspaceNewRoomPage.tsx @@ -175,20 +175,21 @@ function WorkspaceNewRoomPage({policies, reports, formState, session, activePoli ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomNameInvalidError')); } else if (ValidationUtils.isReservedRoomName(values.roomName)) { // Certain names are reserved for default rooms and should not be used for policy rooms. - ErrorUtils.addErrorMessage(errors, 'roomName', [translate('newRoomPage.roomNameReservedError'), {reservedName: values.roomName}]); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomNameReservedError', {reservedName: values.roomName})); } else if (ValidationUtils.isExistingRoomName(values.roomName, reports, values.policyID ?? '')) { // Certain names are reserved for default rooms and should not be used for policy rooms. ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomAlreadyExistsError')); } else if (values.roomName.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'roomName', [translate('common.error.characterLimitExceedCounter'), {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('common.error.characterLimitExceedCounter', {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } const descriptionLength = ReportUtils.getCommentLength(values.reportDescription); if (descriptionLength > CONST.REPORT_DESCRIPTION.MAX_LENGTH) { - ErrorUtils.addErrorMessage(errors, 'reportDescription', [ - 'common.error.characterLimitExceedCounter', - {length: descriptionLength, limit: CONST.REPORT_DESCRIPTION.MAX_LENGTH}, - ]); + ErrorUtils.addErrorMessage( + errors, + 'reportDescription', + translate('common.error.characterLimitExceedCounter', {length: descriptionLength, limit: CONST.REPORT_DESCRIPTION.MAX_LENGTH}), + ); } if (!values.policyID) { @@ -197,7 +198,7 @@ function WorkspaceNewRoomPage({policies, reports, formState, session, activePoli return errors; }, - [reports], + [reports, translate], ); const writeCapabilityOptions = useMemo( diff --git a/src/types/onyx/OnyxCommon.ts b/src/types/onyx/OnyxCommon.ts index 37a06f20ca63..98c8066da8f4 100644 --- a/src/types/onyx/OnyxCommon.ts +++ b/src/types/onyx/OnyxCommon.ts @@ -1,7 +1,6 @@ import type {ValueOf} from 'type-fest'; import type {AvatarSource} from '@libs/UserUtils'; import type CONST from '@src/CONST'; -import type { MaybePhraseKey } from '@libs/Localize'; type PendingAction = ValueOf | null; From 7d39bf56cf5db269ffaabc35961892475cde38be Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 13:37:29 +0700 Subject: [PATCH 03/24] fix test --- tests/actions/IOUTest.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 940d533b9d2b..fcfe94ce2952 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -10,6 +10,7 @@ import * as Report from '@src/libs/actions/Report'; import * as ReportActions from '@src/libs/actions/ReportActions'; import * as User from '@src/libs/actions/User'; import DateUtils from '@src/libs/DateUtils'; +import * as Localize from '@src/libs/Localize'; import Navigation from '@src/libs/Navigation/Navigation'; import * as NumberUtils from '@src/libs/NumberUtils'; import * as PersonalDetailsUtils from '@src/libs/PersonalDetailsUtils'; @@ -769,7 +770,7 @@ describe('actions/IOU', () => { Onyx.disconnect(connectionID); expect(transaction?.pendingAction).toBeFalsy(); expect(transaction?.errors).toBeTruthy(); - expect(Object.values(transaction?.errors ?? {})[0]).toEqual(expect.arrayContaining(['iou.error.genericCreateFailureMessage', {isTranslated: false}])); + expect(Object.values(transaction?.errors ?? {})[0]).toEqual(Localize.translateLocal('iou.error.genericCreateFailureMessage')); resolve(); }, }); From 6177f8b0f07aefbf4b3f350df62503aea0985646 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 13:45:04 +0700 Subject: [PATCH 04/24] fix error utils test --- src/libs/ErrorUtils.ts | 2 +- tests/unit/ErrorUtilsTest.ts | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index 2019d5d2daf5..2621aa4ebd72 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -148,7 +148,7 @@ function getErrorsWithTranslationData(errors: Errors): Errors { * @param errors - An object containing current errors in the form * @param message - Message to assign to the inputID errors */ -function addErrorMessage(errors: Errors, inputID?: string | null, message?: string) { +function addErrorMessage(errors: Errors, inputID?: string | null, message?: string | null) { if (!message || !inputID) { return; } diff --git a/tests/unit/ErrorUtilsTest.ts b/tests/unit/ErrorUtilsTest.ts index 9168c1ca12a5..6f615ab20436 100644 --- a/tests/unit/ErrorUtilsTest.ts +++ b/tests/unit/ErrorUtilsTest.ts @@ -6,21 +6,21 @@ describe('ErrorUtils', () => { const errors: Errors = {}; ErrorUtils.addErrorMessage(errors, 'username', 'Username cannot be empty'); - expect(errors).toEqual({username: ['Username cannot be empty', {isTranslated: true}]}); + expect(errors).toEqual({username: 'Username cannot be empty'}); }); test('should append an error message to an existing error message for a given inputID', () => { const errors: Errors = {username: 'Username cannot be empty'}; ErrorUtils.addErrorMessage(errors, 'username', 'Username must be at least 6 characters long'); - expect(errors).toEqual({username: ['Username cannot be empty\nUsername must be at least 6 characters long', {isTranslated: true}]}); + expect(errors).toEqual({username: 'Username cannot be empty\nUsername must be at least 6 characters long'}); }); test('should add an error to input which does not contain any errors yet', () => { const errors: Errors = {username: 'Username cannot be empty'}; ErrorUtils.addErrorMessage(errors, 'password', 'Password cannot be empty'); - expect(errors).toEqual({username: 'Username cannot be empty', password: ['Password cannot be empty', {isTranslated: true}]}); + expect(errors).toEqual({username: 'Username cannot be empty', password: 'Password cannot be empty'}); }); test('should not mutate the errors object when message is empty', () => { @@ -59,10 +59,7 @@ describe('ErrorUtils', () => { ErrorUtils.addErrorMessage(errors, 'username', 'Username must not contain special characters'); expect(errors).toEqual({ - username: [ - 'Username cannot be empty\nUsername must be at least 6 characters long\nUsername must contain at least one letter\nUsername must not contain special characters', - {isTranslated: true}, - ], + username: 'Username cannot be empty\nUsername must be at least 6 characters long\nUsername must contain at least one letter\nUsername must not contain special characters', }); }); }); From 04512137e4405c537ff75664aa6950b4fc43c929 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 13:51:18 +0700 Subject: [PATCH 05/24] complete fix tes --- tests/unit/ErrorUtilsTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/ErrorUtilsTest.ts b/tests/unit/ErrorUtilsTest.ts index 6f615ab20436..f5517c56156a 100644 --- a/tests/unit/ErrorUtilsTest.ts +++ b/tests/unit/ErrorUtilsTest.ts @@ -50,7 +50,7 @@ describe('ErrorUtils', () => { ErrorUtils.addErrorMessage(errors, 'username', 'Username must be at least 6 characters long'); ErrorUtils.addErrorMessage(errors, 'username', 'Username must contain at least one letter'); - expect(errors).toEqual({username: ['Username cannot be empty\nUsername must be at least 6 characters long\nUsername must contain at least one letter', {isTranslated: true}]}); + expect(errors).toEqual({username: 'Username cannot be empty\nUsername must be at least 6 characters long\nUsername must contain at least one letter'}); }); test('should append multiple error messages to an existing error message for the same inputID', () => { From 7b70d73d6614270502ce87f49a10eb2474f44826 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 14:54:12 +0700 Subject: [PATCH 06/24] fix translation error --- src/libs/ErrorUtils.ts | 4 ++-- src/pages/ChatFinderPage/index.tsx | 2 +- src/pages/iou/request/MoneyRequestParticipantsSelector.tsx | 2 +- tests/actions/IOUTest.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index 2621aa4ebd72..cef907a91cfc 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -126,9 +126,9 @@ function getLatestErrorFieldForAnyField option === action); diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index fcfe94ce2952..63417b7ddd3b 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -1862,7 +1862,7 @@ describe('actions/IOU', () => { Onyx.disconnect(connectionID); const updatedAction = Object.values(allActions ?? {}).find((reportAction) => !isEmptyObject(reportAction)); expect(updatedAction?.actionName).toEqual('MODIFIEDEXPENSE'); - expect(Object.values(updatedAction?.errors ?? {})).toEqual(expect.arrayContaining([['iou.error.genericEditFailureMessage', {isTranslated: false}]])); + expect(Object.values(updatedAction?.errors ?? {})).toEqual(Localize.translateLocal('iou.error.genericEditFailureMessage')); resolve(); }, }); @@ -2084,7 +2084,7 @@ describe('actions/IOU', () => { callback: (allActions) => { Onyx.disconnect(connectionID); const erroredAction = Object.values(allActions ?? {}).find((action) => !isEmptyObject(action?.errors)); - expect(Object.values(erroredAction?.errors ?? {})).toEqual(expect.arrayContaining([['iou.error.other', {isTranslated: false}]])); + expect(Object.values(erroredAction?.errors ?? {})).toEqual(Localize.translateLocal('iou.error.other')); resolve(); }, }); From 55a90773cb37ac21fd93a8b43a434e3a7c7b132a Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 15:39:24 +0700 Subject: [PATCH 07/24] remove the use of MaybePhraseKey type --- src/components/AddressForm.tsx | 3 +- src/components/AddressSearch/types.ts | 3 +- src/components/Form/types.ts | 3 +- src/components/RoomNameInput/types.ts | 3 +- src/components/SelectionList/types.ts | 3 +- src/libs/ErrorUtils.ts | 9 +- src/libs/OptionsListUtils.ts | 6 +- src/libs/ValidationUtils.ts | 8 +- src/libs/actions/BankAccounts.ts | 4 +- src/libs/actions/IOU.ts | 82 +++++++++---------- src/libs/actions/Policy/Category.ts | 12 +-- src/libs/actions/Policy/Policy.ts | 50 +++++------ src/libs/actions/Policy/Tag.ts | 12 +-- src/libs/actions/Report.ts | 22 ++--- src/libs/actions/Session/index.ts | 4 +- src/libs/actions/SignInRedirect.ts | 2 +- src/libs/actions/Task.ts | 6 +- src/libs/actions/TaxRate.ts | 10 +-- src/libs/actions/User.ts | 10 +-- src/libs/actions/connections/index.ts | 6 +- src/pages/ChatFinderPage/index.tsx | 3 +- .../BaseOnboardingPersonalDetails.tsx | 4 +- .../OnboardingWork/BaseOnboardingWork.tsx | 2 +- .../AddressFormFields.tsx | 2 +- src/pages/iou/MoneyRequestAmountForm.tsx | 2 +- .../MoneyRequestParticipantsSelector.tsx | 3 +- .../step/IOURequestStepDescription.tsx | 26 +++--- .../settings/Profile/DisplayNamePage.tsx | 4 +- .../Profile/PersonalDetails/LegalNamePage.tsx | 17 ++-- src/pages/settings/Report/RoomNamePage.tsx | 6 +- .../settings/Wallet/AddDebitCardPage.tsx | 2 +- src/pages/tasks/NewTaskDescriptionPage.tsx | 6 +- src/pages/tasks/NewTaskDetailsPage.tsx | 8 +- src/pages/tasks/NewTaskTitlePage.tsx | 2 +- src/pages/tasks/TaskDescriptionPage.tsx | 4 +- src/pages/tasks/TaskTitlePage.tsx | 4 +- src/pages/workspace/WorkspaceNamePage.tsx | 4 +- .../WorkspaceProfileDescriptionPage.tsx | 4 +- .../workspace/categories/CategoryForm.tsx | 8 +- .../workspace/tags/WorkspaceCreateTagPage.tsx | 4 +- tests/actions/IOUTest.ts | 2 +- 41 files changed, 198 insertions(+), 177 deletions(-) diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index dc5c47ad182c..8601c3fa1e9f 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -3,7 +3,6 @@ import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; -import type {MaybePhraseKey} from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; @@ -77,7 +76,7 @@ function AddressForm({ const zipSampleFormat = (country && (CONST.COUNTRY_ZIP_REGEX_DATA[country] as CountryZipRegex)?.samples) ?? ''; - const zipFormat: MaybePhraseKey = ['common.zipCodeExampleFormat', {zipSampleFormat}]; + const zipFormat = translate('common.zipCodeExampleFormat', {zipSampleFormat}); const isUSAForm = country === CONST.COUNTRY.US; diff --git a/src/components/AddressSearch/types.ts b/src/components/AddressSearch/types.ts index bc7acf3f7e40..82e4c3c3fc37 100644 --- a/src/components/AddressSearch/types.ts +++ b/src/components/AddressSearch/types.ts @@ -1,7 +1,6 @@ import type {RefObject} from 'react'; import type {NativeSyntheticEvent, StyleProp, TextInputFocusEventData, View, ViewStyle} from 'react-native'; import type {Place} from 'react-native-google-places-autocomplete'; -import type {MaybePhraseKey} from '@libs/Localize'; import type Locale from '@src/types/onyx/Locale'; import type {Address} from '@src/types/onyx/PrivatePersonalDetails'; @@ -35,7 +34,7 @@ type AddressSearchProps = { onBlur?: () => void; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Hint text to display */ hint?: string; diff --git a/src/components/Form/types.ts b/src/components/Form/types.ts index 331f1c943b30..9aa8bc921164 100644 --- a/src/components/Form/types.ts +++ b/src/components/Form/types.ts @@ -18,7 +18,6 @@ import type StateSelector from '@components/StateSelector'; import type TextInput from '@components/TextInput'; import type TextPicker from '@components/TextPicker'; import type ValuePicker from '@components/ValuePicker'; -import type {MaybePhraseKey} from '@libs/Localize'; import type BusinessTypePicker from '@pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker'; import type {Country} from '@src/CONST'; import type {OnyxFormKey, OnyxValues} from '@src/ONYXKEYS'; @@ -139,7 +138,7 @@ type FormRef = { type InputRefs = Record>; -type FormInputErrors = Partial, MaybePhraseKey>>; +type FormInputErrors = Partial, string | undefined>>; export type { FormProps, diff --git a/src/components/RoomNameInput/types.ts b/src/components/RoomNameInput/types.ts index 80f08a01e472..763d0f3f2668 100644 --- a/src/components/RoomNameInput/types.ts +++ b/src/components/RoomNameInput/types.ts @@ -1,10 +1,9 @@ import type {NativeSyntheticEvent, ReturnKeyTypeOptions, TextInputFocusEventData, TextInputSubmitEditingEventData} from 'react-native'; -import type {MaybePhraseKey} from '@libs/Localize'; type RoomNameInputProps = { value?: string; disabled?: boolean; - errorText?: MaybePhraseKey; + errorText?: string; onChangeText?: (value: string) => void; onSubmitEditing?: (event: NativeSyntheticEvent) => void; onInputChange?: (value: string) => void; diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index b3bee8fb15c5..f0d2c479c9c5 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -1,6 +1,5 @@ import type {MutableRefObject, ReactElement, ReactNode} from 'react'; import type {GestureResponderEvent, InputModeOptions, LayoutChangeEvent, SectionListData, StyleProp, TextInput, TextStyle, ViewStyle} from 'react-native'; -import type {MaybePhraseKey} from '@libs/Localize'; import type {BrickRoad} from '@libs/WorkspacesSettingsUtils'; import type CONST from '@src/CONST'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; @@ -288,7 +287,7 @@ type BaseSelectionListProps = Partial & { textInputPlaceholder?: string; /** Hint for the text input */ - textInputHint?: MaybePhraseKey; + textInputHint?: string; /** Value for the text input */ textInputValue?: string; diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index cef907a91cfc..44630efe9f45 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -40,10 +40,14 @@ function getAuthenticateErrorMessage(response: Response): keyof TranslationFlatO * Method used to get an error object with microsecond as the key. * @param error - error key or message to be saved */ -function getMicroSecondOnyxError(error: TranslationPaths, _isTranslated = false, errorKey?: number): Errors { +function getMicroSecondOnyxErrorWithTranslationKey(error: TranslationPaths, errorKey?: number): Errors { return {[errorKey ?? DateUtils.getMicroseconds()]: Localize.translateLocal(error)}; } +function getMicroSecondOnyxErrorWithMessage(error: string, errorKey?: number): Errors { + return {[errorKey ?? DateUtils.getMicroseconds()]: error}; +} + /** * Method used to get an error object with microsecond as the key and an object as the value. * @param error - error key or message to be saved @@ -189,7 +193,8 @@ export { getLatestErrorMessage, getLatestErrorMessageField, getLatestErrorFieldForAnyField, - getMicroSecondOnyxError, + getMicroSecondOnyxErrorWithTranslationKey, + getMicroSecondOnyxErrorWithMessage, getMicroSecondOnyxErrorObject, isReceiptError, }; diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index f321c10c686e..b23ce6f23847 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -532,14 +532,14 @@ function getAllReportErrors(report: OnyxEntry, reportActions: OnyxEntry< const transactionID = parentReportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? parentReportAction?.originalMessage?.IOUTransactionID : null; const transaction = allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; if (TransactionUtils.hasMissingSmartscanFields(transaction ?? null) && !ReportUtils.isSettled(transaction?.reportID)) { - reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxError('report.genericSmartscanFailureMessage'); + reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericSmartscanFailureMessage'); } } else if ((ReportUtils.isIOUReport(report) || ReportUtils.isExpenseReport(report)) && report?.ownerAccountID === currentUserAccountID) { if (ReportUtils.hasMissingSmartscanFields(report?.reportID ?? '') && !ReportUtils.isSettled(report?.reportID)) { - reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxError('report.genericSmartscanFailureMessage'); + reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericSmartscanFailureMessage'); } } else if (ReportUtils.hasSmartscanError(Object.values(reportActions ?? {}))) { - reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxError('report.genericSmartscanFailureMessage'); + reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericSmartscanFailureMessage'); } // All error objects related to the report. Each object in the sources contains error messages keyed by microtime const errorSources = { diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts index 7fe73526a1a5..c9144547833a 100644 --- a/src/libs/ValidationUtils.ts +++ b/src/libs/ValidationUtils.ts @@ -191,12 +191,12 @@ function meetsMaximumAgeRequirement(date: string): boolean { /** * Validate that given date is in a specified range of years before now. */ -function getAgeRequirementError(date: string, minimumAge: number, maximumAge: number): Localize.MaybePhraseKey { +function getAgeRequirementError(date: string, minimumAge: number, maximumAge: number): string { const currentDate = startOfDay(new Date()); const testDate = parse(date, CONST.DATE.FNS_FORMAT_STRING, currentDate); if (!isValid(testDate)) { - return 'common.error.dateInvalid'; + return Localize.translateLocal('common.error.dateInvalid'); } const maximalDate = subYears(currentDate, minimumAge); @@ -207,10 +207,10 @@ function getAgeRequirementError(date: string, minimumAge: number, maximumAge: nu } if (isSameDay(testDate, maximalDate) || isAfter(testDate, maximalDate)) { - return ['privatePersonalDetails.error.dateShouldBeBefore', {dateString: format(maximalDate, CONST.DATE.FNS_FORMAT_STRING)}]; + return Localize.translateLocal('privatePersonalDetails.error.dateShouldBeBefore', {dateString: format(maximalDate, CONST.DATE.FNS_FORMAT_STRING)}); } - return ['privatePersonalDetails.error.dateShouldBeAfter', {dateString: format(minimalDate, CONST.DATE.FNS_FORMAT_STRING)}]; + return Localize.translateLocal('privatePersonalDetails.error.dateShouldBeAfter', {dateString: format(minimalDate, CONST.DATE.FNS_FORMAT_STRING)}); } /** diff --git a/src/libs/actions/BankAccounts.ts b/src/libs/actions/BankAccounts.ts index cddb2c371a60..89d0296994e3 100644 --- a/src/libs/actions/BankAccounts.ts +++ b/src/libs/actions/BankAccounts.ts @@ -163,7 +163,7 @@ function getVBBADataForOnyx(currentStep?: BankAccountStep): OnyxData { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, value: { isLoading: false, - errors: ErrorUtils.getMicroSecondOnyxError('walletPage.addBankAccountFailure'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('walletPage.addBankAccountFailure'), }, }, ], @@ -239,7 +239,7 @@ function addPersonalBankAccount(account: PlaidBankAccount) { key: ONYXKEYS.PERSONAL_BANK_ACCOUNT, value: { isLoading: false, - errors: ErrorUtils.getMicroSecondOnyxError('walletPage.addBankAccountFailure'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('walletPage.addBankAccountFailure'), }, }, ], diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index dfaea862b888..0b4991ec2138 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -444,7 +444,7 @@ function updateDistanceRequestRate(transactionID: string, rateID: string, policy /** Helper function to get the receipt error for expenses, or the generic error if there's no receipt */ function getReceiptError(receipt?: Receipt, filename?: string, isScanRequest = true, errorKey?: number): Errors | ErrorFields { return isEmptyObject(receipt) || !isScanRequest - ? ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage', false, errorKey) + ? ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage', errorKey) : ErrorUtils.getMicroSecondOnyxErrorObject({error: CONST.IOU.RECEIPT_ERROR, source: receipt.source?.toString() ?? '', filename: filename ?? ''}, errorKey); } @@ -740,7 +740,7 @@ function buildOnyxDataForMoneyRequest( ...(isNewChatReport ? { errorFields: { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, } : {}), @@ -752,7 +752,7 @@ function buildOnyxDataForMoneyRequest( value: { pendingFields: null, errorFields: { - ...(shouldCreateNewMoneyRequestReport ? {createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage')} : {}), + ...(shouldCreateNewMoneyRequestReport ? {createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage')} : {}), }, }, }, @@ -764,7 +764,7 @@ function buildOnyxDataForMoneyRequest( errorFields: existingTransactionThreadReport ? null : { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -791,7 +791,7 @@ function buildOnyxDataForMoneyRequest( errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt?.filename, isScanRequest, errorKey), }, [iouAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, } : { @@ -811,7 +811,7 @@ function buildOnyxDataForMoneyRequest( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, value: { [transactionThreadCreatedReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, }); @@ -1072,7 +1072,7 @@ function buildOnyxDataForInvoice( ...(isNewChatReport ? { errorFields: { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, } : {}), @@ -1084,7 +1084,7 @@ function buildOnyxDataForInvoice( value: { pendingFields: null, errorFields: { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -1093,7 +1093,7 @@ function buildOnyxDataForInvoice( key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`, value: { errorFields: { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -1101,7 +1101,7 @@ function buildOnyxDataForInvoice( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, value: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateInvoiceFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateInvoiceFailureMessage'), pendingAction: null, pendingFields: clearedPendingFields, }, @@ -1116,7 +1116,7 @@ function buildOnyxDataForInvoice( errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt?.filename, false, errorKey), }, [iouAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateInvoiceFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateInvoiceFailureMessage'), }, }, }, @@ -1125,7 +1125,7 @@ function buildOnyxDataForInvoice( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, value: { [transactionThreadCreatedReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateInvoiceFailureMessage', false, errorKey), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateInvoiceFailureMessage', errorKey), }, }, }, @@ -1413,7 +1413,7 @@ function buildOnyxDataForTrackExpense( value: { pendingFields: null, errorFields: { - ...(shouldCreateNewMoneyRequestReport ? {createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage')} : {}), + ...(shouldCreateNewMoneyRequestReport ? {createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage')} : {}), }, }, }, @@ -1429,7 +1429,7 @@ function buildOnyxDataForTrackExpense( errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt?.filename, isScanRequest), }, [iouAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, } : { @@ -1474,7 +1474,7 @@ function buildOnyxDataForTrackExpense( errorFields: existingTransactionThreadReport ? null : { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -1494,7 +1494,7 @@ function buildOnyxDataForTrackExpense( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, value: { [transactionThreadCreatedReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, }, @@ -1680,7 +1680,7 @@ function getDeleteTrackExpenseInformation( [reportAction.reportActionID]: { ...reportAction, pendingAction: null, - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericDeleteFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericDeleteFailureMessage'), }, }, }, @@ -2518,7 +2518,7 @@ function getUpdateMoneyRequestParams( value: { [updatedReportAction.reportActionID]: { ...(updatedReportAction as OnyxTypes.ReportAction), - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericEditFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'), }, }, }); @@ -2802,7 +2802,7 @@ function getUpdateTrackExpenseParams( value: { [updatedReportAction.reportActionID]: { ...(updatedReportAction as OnyxTypes.ReportAction), - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericEditFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'), }, }, }); @@ -3130,7 +3130,7 @@ const getConvertTrackedExpenseInformation = ( value: { [modifiedExpenseReportAction.reportActionID]: { ...(modifiedExpenseReportAction as OnyxTypes.ReportAction), - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericEditFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'), }, }, }); @@ -3934,7 +3934,7 @@ function createSplitsAndOnyxData( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${splitTransaction.transactionID}`, value: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, ]; @@ -3945,7 +3945,7 @@ function createSplitsAndOnyxData( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`, value: { [splitIOUReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, }); @@ -3956,7 +3956,7 @@ function createSplitsAndOnyxData( key: `${ONYXKEYS.COLLECTION.REPORT}${splitChatReport.reportID}`, value: { errorFields: { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -3965,7 +3965,7 @@ function createSplitsAndOnyxData( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`, value: { [splitIOUReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, }, @@ -4480,7 +4480,7 @@ function startSplitBill({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${splitTransaction.transactionID}`, value: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, ]; @@ -4502,7 +4502,7 @@ function startSplitBill({ key: `${ONYXKEYS.COLLECTION.REPORT}${splitChatReport.reportID}`, value: { errorFields: { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -4511,7 +4511,7 @@ function startSplitBill({ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`, value: { [splitChatCreatedReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, [splitIOUReportAction.reportActionID]: { errors: getReceiptError(receipt, filename), @@ -4686,7 +4686,7 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, value: { ...unmodifiedTransaction, - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, { @@ -4695,7 +4695,7 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA value: { [reportAction.reportActionID]: { ...reportAction, - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, }, @@ -5060,7 +5060,7 @@ function editRegularMoneyRequest( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`, value: { [updatedReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericEditFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'), }, }, }, @@ -5741,7 +5741,7 @@ function getSendMoneyParams( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${optimisticTransaction.transactionID}`, value: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.other'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), }, }, { @@ -5749,7 +5749,7 @@ function getSendMoneyParams( key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticTransactionThread.reportID}`, value: { errorFields: { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -5758,7 +5758,7 @@ function getSendMoneyParams( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTransactionThread.reportID}`, value: { [optimisticCreatedActionForTransactionThread.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, }, @@ -5777,7 +5777,7 @@ function getSendMoneyParams( key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, value: { errorFields: { - createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + createChat: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -5786,7 +5786,7 @@ function getSendMoneyParams( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticIOUReport.reportID}`, value: { [optimisticIOUReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, }, @@ -5802,7 +5802,7 @@ function getSendMoneyParams( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticIOUReport.reportID}`, value: { [optimisticIOUReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.other'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), }, }, }); @@ -5950,7 +5950,7 @@ function getPayMoneyRequestParams( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`, value: { [optimisticIOUReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.other'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), }, }, }, @@ -6190,7 +6190,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, value: { [optimisticApprovedReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.other'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), }, }, }, @@ -6344,7 +6344,7 @@ function submitReport(expenseReport: OnyxTypes.Report) { key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, value: { [optimisticSubmittedReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.other'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), }, }, }); @@ -6432,7 +6432,7 @@ function cancelPayment(expenseReport: OnyxTypes.Report, chatReport: OnyxTypes.Re key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, value: { [optimisticReportAction.reportActionID ?? '']: { - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.other'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), }, }, }, @@ -6505,7 +6505,7 @@ function detachReceipt(transactionID: string) { key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, value: { ...transaction, - errors: ErrorUtils.getMicroSecondOnyxError('iou.error.receiptDeleteFailureError'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.receiptDeleteFailureError'), }, }, ]; diff --git a/src/libs/actions/Policy/Category.ts b/src/libs/actions/Policy/Category.ts index 82bca6dc7c22..ec540e624ffb 100644 --- a/src/libs/actions/Policy/Category.ts +++ b/src/libs/actions/Policy/Category.ts @@ -92,7 +92,7 @@ function buildOptimisticPolicyCategories(policyID: string, categories: readonly (acc, category) => ({ ...acc, [category]: { - errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.createFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.createFailureMessage'), pendingAction: null, }, }), @@ -211,7 +211,7 @@ function setWorkspaceCategoryEnabled(policyID: string, categoriesToUpdate: Recor acc[key] = { ...policyCategories[key], ...categoriesToUpdate[key], - errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.updateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.updateFailureMessage'), pendingFields: { enabled: null, }, @@ -327,7 +327,7 @@ function renamePolicyCategory(policyID: string, policyCategory: {oldName: string ...policyCategoryToUpdate, name: policyCategory.oldName, unencodedName: decodeURIComponent(policyCategory.oldName), - errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.updateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.updateFailureMessage'), pendingAction: null, }, }, @@ -380,7 +380,7 @@ function setWorkspaceRequiresCategory(policyID: string, requiresCategory: boolea key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { requiresCategory: !requiresCategory, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.updateFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.updateFailureMessage'), pendingFields: { requiresCategory: null, }, @@ -446,7 +446,7 @@ function deleteWorkspaceCategories(policyID: string, categoryNamesToDelete: stri value: categoryNamesToDelete.reduce>>((acc, categoryName) => { acc[categoryName] = { pendingAction: null, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.deleteFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.deleteFailureMessage'), }; return acc; }, {}), @@ -579,7 +579,7 @@ function setPolicyDistanceRatesDefaultCategory(policyID: string, currentCustomUn customUnits: { [currentCustomUnit.customUnitID]: { ...currentCustomUnit, - errorFields: {defaultCategory: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {defaultCategory: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, pendingFields: {defaultCategory: null}, }, }, diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index fc2a8ad7970e..9bdc433b7e71 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -467,7 +467,7 @@ function setWorkspaceAutoReporting(policyID: string, enabled: boolean, frequency }, autoReportingFrequency: policy.autoReportingFrequency ?? null, pendingFields: {autoReporting: null}, - errorFields: {autoReporting: ErrorUtils.getMicroSecondOnyxError('workflowsDelayedSubmissionPage.autoReportingErrorMessage')}, + errorFields: {autoReporting: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsDelayedSubmissionPage.autoReportingErrorMessage')}, }, }, ]; @@ -508,7 +508,7 @@ function setWorkspaceAutoReportingFrequency(policyID: string, frequency: ValueOf value: { autoReportingFrequency: policy.autoReportingFrequency ?? null, pendingFields: {autoReportingFrequency: null}, - errorFields: {autoReportingFrequency: ErrorUtils.getMicroSecondOnyxError('workflowsDelayedSubmissionPage.autoReportingFrequencyErrorMessage')}, + errorFields: {autoReportingFrequency: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsDelayedSubmissionPage.autoReportingFrequencyErrorMessage')}, }, }, ]; @@ -549,7 +549,7 @@ function setWorkspaceAutoReportingMonthlyOffset(policyID: string, autoReportingO value: { autoReportingOffset: policy.autoReportingOffset ?? null, pendingFields: {autoReportingOffset: null}, - errorFields: {autoReportingOffset: ErrorUtils.getMicroSecondOnyxError('workflowsDelayedSubmissionPage.monthlyOffsetErrorMessage')}, + errorFields: {autoReportingOffset: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsDelayedSubmissionPage.monthlyOffsetErrorMessage')}, }, }, ]; @@ -595,7 +595,7 @@ function setWorkspaceApprovalMode(policyID: string, approver: string, approvalMo approver: policy.approver ?? null, approvalMode: policy.approvalMode ?? null, pendingFields: {approvalMode: null}, - errorFields: {approvalMode: ErrorUtils.getMicroSecondOnyxError('workflowsApprovalPage.genericErrorMessage')}, + errorFields: {approvalMode: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsApprovalPage.genericErrorMessage')}, }, }, ]; @@ -653,7 +653,7 @@ function setWorkspacePayer(policyID: string, reimburserEmail: string) { key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { achAccount: {reimburser: policy.achAccount?.reimburser ?? null}, - errorFields: {reimburser: ErrorUtils.getMicroSecondOnyxError('workflowsPayerPage.genericErrorMessage')}, + errorFields: {reimburser: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsPayerPage.genericErrorMessage')}, pendingFields: {reimburser: null}, }, }, @@ -713,7 +713,7 @@ function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueO isLoadingWorkspaceReimbursement: false, reimbursementChoice: policy.reimbursementChoice ?? null, achAccount: {reimburser: policy.achAccount?.reimburser ?? null}, - errorFields: {reimbursementChoice: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {reimbursementChoice: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, pendingFields: {reimbursementChoice: null}, }, }, @@ -810,7 +810,7 @@ function removeMembers(accountIDs: number[], policyID: string) { emailList.forEach((email) => { optimisticMembersState[email] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}; successMembersState[email] = null; - failureMembersState[email] = {errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericRemove')}; + failureMembersState[email] = {errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.people.error.genericRemove')}; }); const optimisticData: OnyxUpdate[] = [ @@ -969,7 +969,7 @@ function leaveWorkspace(policyID: string) { pendingAction: policy?.pendingAction, employeeList: { [sessionEmail]: { - errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericRemove'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.people.error.genericRemove'), }, }, }, @@ -1075,7 +1075,7 @@ function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newR key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { employeeList: previousEmployeeList, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.editor.genericFailureMessage'), }, }, ]; @@ -1363,7 +1363,7 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount optimisticMembersState[email] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, role: CONST.POLICY.ROLE.USER}; successMembersState[email] = {pendingAction: null}; failureMembersState[email] = { - errors: ErrorUtils.getMicroSecondOnyxError('workspace.people.error.genericAdd'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.people.error.genericAdd'), }; }); @@ -1441,7 +1441,7 @@ function inviteMemberToWorkspace(policyID: string, inviterEmail: string) { { onyxMethod: Onyx.METHOD.MERGE, key: memberJoinKey, - value: {...failureMembersState, errors: ErrorUtils.getMicroSecondOnyxError('common.genericEditFailureMessage')}, + value: {...failureMembersState, errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, }, ]; @@ -1535,7 +1535,7 @@ function deleteWorkspaceAvatar(policyID: string) { key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { errorFields: { - avatarURL: ErrorUtils.getMicroSecondOnyxError('avatarWithImagePicker.deleteWorkspaceError'), + avatarURL: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('avatarWithImagePicker.deleteWorkspaceError'), }, }, }, @@ -1594,7 +1594,7 @@ function updateGeneralSettings(policyID: string, name: string, currencyValue?: s failureRates[rateID] = { ...currentRates[rateID], pendingFields: {currency: null}, - errorFields: {currency: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {currency: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, }; } } @@ -1655,7 +1655,7 @@ function updateGeneralSettings(policyID: string, name: string, currencyValue?: s key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { errorFields: { - generalSettings: ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), + generalSettings: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.editor.genericFailureMessage'), }, ...(customUnitID && { customUnits: { @@ -1720,7 +1720,7 @@ function updateWorkspaceDescription(policyID: string, description: string, curre key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { errorFields: { - description: ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), + description: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.editor.genericFailureMessage'), }, }, }, @@ -1869,7 +1869,7 @@ function updateWorkspaceCustomUnitAndRate(policyID: string, currentCustomUnit: C rates: { [newCustomUnit.rates.customUnitRateID]: { ...currentCustomUnit.rates, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.reimburse.updateCustomUnitError'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.reimburse.updateCustomUnitError'), }, }, }, @@ -2096,7 +2096,7 @@ function buildOptimisticPolicyCategories(policyID: string, categories: readonly (acc, category) => ({ ...acc, [category]: { - errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.createFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.createFailureMessage'), pendingAction: null, }, }), @@ -3635,7 +3635,7 @@ function createPolicyDistanceRate(policyID: string, customUnitID: string, custom [customUnitID]: { rates: { [customUnitRate.customUnitRateID ?? '']: { - errors: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), }, }, }, @@ -3753,7 +3753,7 @@ function setPolicyDistanceRatesUnit(policyID: string, currentCustomUnit: CustomU customUnits: { [currentCustomUnit.customUnitID]: { ...currentCustomUnit, - errorFields: {attributes: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {attributes: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, pendingFields: {attributes: null}, }, }, @@ -3799,7 +3799,7 @@ function updatePolicyDistanceRateValue(policyID: string, customUnit: CustomUnit, failureRates[rateID] = { ...currentRates[rateID], pendingFields: {rate: null}, - errorFields: {rate: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {rate: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, }; } } @@ -3870,7 +3870,7 @@ function setPolicyDistanceRatesEnabled(policyID: string, customUnit: CustomUnit, failureRates[rateID] = { ...currentRates[rateID], pendingFields: {enabled: null}, - errorFields: {enabled: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {enabled: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, }; } } @@ -3941,7 +3941,7 @@ function deletePolicyDistanceRates(policyID: string, customUnit: CustomUnit, rat failureRates[rateID] = { ...currentRates[rateID], pendingAction: null, - errors: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), }; } else { optimisticRates[rateID] = currentRates[rateID]; @@ -4037,7 +4037,7 @@ function setPolicyCustomTaxName(policyID: string, customTaxName: string) { taxRates: { name: originalCustomTaxName, pendingFields: {name: null}, - errorFields: {name: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {name: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, }, }, }, @@ -4089,7 +4089,7 @@ function setWorkspaceCurrencyDefault(policyID: string, taxCode: string) { taxRates: { defaultExternalID: originalDefaultExternalID, pendingFields: {defaultExternalID: null}, - errorFields: {defaultExternalID: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {defaultExternalID: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, }, }, }, @@ -4141,7 +4141,7 @@ function setForeignCurrencyDefault(policyID: string, taxCode: string) { taxRates: { foreignTaxDefault: originalDefaultForeignCurrencyID, pendingFields: {foreignTaxDefault: null}, - errorFields: {foreignTaxDefault: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {foreignTaxDefault: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, }, }, }, diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 7760f29d6703..512300591fd1 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -160,7 +160,7 @@ function createPolicyTag(policyID: string, tagName: string) { [policyTag.name]: { tags: { [newTagName]: { - errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.tags.genericFailureMessage'), }, }, }, @@ -242,7 +242,7 @@ function setWorkspaceTagEnabled(policyID: string, tagsToUpdate: Record>>>((acc, tagName) => { - acc[tagName] = {pendingAction: null, errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.deleteFailureMessage')}; + acc[tagName] = {pendingAction: null, errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.tags.deleteFailureMessage')}; return acc; }, {}), }, @@ -416,7 +416,7 @@ function renamePolicyTag(policyID: string, policyTag: {oldName: string; newName: [newTagName]: null, [oldTagName]: { ...oldTag, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.tags.genericFailureMessage'), }, }, }, @@ -514,7 +514,7 @@ function renamePolicyTaglist(policyID: string, policyTagListName: {oldName: stri value: { errors: { [oldName]: oldName, - [newName]: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + [newName]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.tags.genericFailureMessage'), }, [newName]: null, [oldName]: oldPolicyTags, @@ -566,7 +566,7 @@ function setPolicyRequiresTag(policyID: string, requiresTag: boolean) { key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { requiresTag: !requiresTag, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.tags.genericFailureMessage'), pendingFields: { requiresTag: null, }, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 33da5f6336a0..0af60ee812d6 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -569,7 +569,7 @@ function addActions(reportID: string, text = '', file?: FileObject) { failureReportActions[actionKey] = { // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style ...(action as OptimisticAddCommentReportAction), - errors: ErrorUtils.getMicroSecondOnyxError('report.genericAddCommentFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericAddCommentFailureMessage'), }; }); @@ -1746,7 +1746,7 @@ function updateReportName(reportID: string, value: string, previousValue: string reportName: null, }, errorFields: { - reportName: ErrorUtils.getMicroSecondOnyxError('report.genericUpdateReporNameEditFailureMessage'), + reportName: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericUpdateReporNameEditFailureMessage'), }, }, }, @@ -1828,7 +1828,7 @@ function updateReportField(reportID: string, reportField: PolicyReportField, pre [fieldKey]: null, }, errorFields: { - [fieldKey]: ErrorUtils.getMicroSecondOnyxError('report.genericUpdateReportFieldFailureMessage'), + [fieldKey]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericUpdateReportFieldFailureMessage'), }, }, }, @@ -1897,7 +1897,7 @@ function deleteReportField(reportID: string, reportField: PolicyReportField) { [fieldKey]: null, }, errorFields: { - [fieldKey]: ErrorUtils.getMicroSecondOnyxError('report.genericUpdateReportFieldFailureMessage'), + [fieldKey]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericUpdateReportFieldFailureMessage'), }, }, }, @@ -2074,7 +2074,7 @@ function addPolicyReport(policyReport: ReportUtils.OptimisticChatReport) { key: `${ONYXKEYS.COLLECTION.REPORT}${policyReport.reportID}`, value: { errorFields: { - addWorkspaceRoom: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'), + addWorkspaceRoom: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericCreateReportFailureMessage'), }, }, }, @@ -2755,7 +2755,7 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: InvitedEmails } return { ...pendingChatMember, - errors: ErrorUtils.getMicroSecondOnyxError('roomMembersPage.error.genericAdd'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('roomMembersPage.error.genericAdd'), }; }) ?? null, }, @@ -3047,7 +3047,7 @@ const updatePrivateNotes = (reportID: string, accountID: number, note: string) = value: { privateNotes: { [accountID]: { - errors: ErrorUtils.getMicroSecondOnyxError('privateNotes.error.genericFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('privateNotes.error.genericFailureMessage'), }, }, }, @@ -3271,7 +3271,7 @@ function completeOnboarding( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetChatReportID}`, value: { [taskReportAction.reportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('report.genericAddCommentFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericAddCommentFailureMessage'), } as ReportAction, }, }, @@ -3353,10 +3353,10 @@ function completeOnboarding( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetChatReportID}`, value: { [introductionCommentAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('report.genericAddCommentFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericAddCommentFailureMessage'), } as ReportAction, [textCommentAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('report.genericAddCommentFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericAddCommentFailureMessage'), } as ReportAction, }, }, @@ -3394,7 +3394,7 @@ function completeOnboarding( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetChatReportID}`, value: { [videoCommentAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('report.genericAddCommentFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericAddCommentFailureMessage'), } as ReportAction, }, }); diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index 303517558206..b2a433864723 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -392,7 +392,7 @@ function signInAttemptState(): OnyxData { value: { isLoading: false, loadingForm: null, - errors: ErrorUtils.getMicroSecondOnyxError('loginForm.cannotGetAccountDetails'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('loginForm.cannotGetAccountDetails'), }, }, ], @@ -673,7 +673,7 @@ function clearAccountMessages() { } function setAccountError(error: string) { - Onyx.merge(ONYXKEYS.ACCOUNT, {errors: ErrorUtils.getMicroSecondOnyxError(error, true)}); + Onyx.merge(ONYXKEYS.ACCOUNT, {errors: ErrorUtils.getMicroSecondOnyxErrorWithMessage(error)}); } // It's necessary to throttle requests to reauthenticate since calling this multiple times will cause Pusher to diff --git a/src/libs/actions/SignInRedirect.ts b/src/libs/actions/SignInRedirect.ts index c6d4ffcaa30f..e72a4b011074 100644 --- a/src/libs/actions/SignInRedirect.ts +++ b/src/libs/actions/SignInRedirect.ts @@ -34,7 +34,7 @@ function clearStorageAndRedirect(errorMessage?: string): Promise { } // `Onyx.clear` reinitializes the Onyx instance with initial values so use `Onyx.merge` instead of `Onyx.set` - Onyx.merge(ONYXKEYS.SESSION, {errors: ErrorUtils.getMicroSecondOnyxError(errorMessage)}); + Onyx.merge(ONYXKEYS.SESSION, {errors: ErrorUtils.getMicroSecondOnyxErrorWithMessage(errorMessage)}); }); } diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 55d898d3d4f3..143b30ac6406 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -269,7 +269,7 @@ function createTaskAndNavigate( key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`, value: { [optimisticAddCommentReport.reportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('task.genericCreateTaskFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('task.genericCreateTaskFailureMessage'), }, }, }); @@ -347,7 +347,7 @@ function completeTask(taskReport: OnyxEntry) { key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReportID}`, value: { [completedTaskReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('task.messages.error'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('task.messages.error'), }, }, }, @@ -416,7 +416,7 @@ function reopenTask(taskReport: OnyxEntry) { key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReportID}`, value: { [reopenedTaskReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxError('task.messages.error'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('task.messages.error'), }, }, }, diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index cdf5bd490c29..b4624a48fc7b 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -124,7 +124,7 @@ function createPolicyTax(policyID: string, taxRate: TaxRate) { taxRates: { taxes: { [taxRate.code]: { - errors: ErrorUtils.getMicroSecondOnyxError('workspace.taxes.error.createFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.taxes.error.createFailureMessage'), }, }, }, @@ -232,7 +232,7 @@ function setPolicyTaxesEnabled(policyID: string, taxesIDsToUpdate: string[], isE acc[taxID] = { isDisabled: !!originalTaxes[taxID].isDisabled, pendingFields: {isDisabled: null}, - errorFields: {isDisabled: ErrorUtils.getMicroSecondOnyxError('workspace.taxes.error.updateFailureMessage')}, + errorFields: {isDisabled: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.taxes.error.updateFailureMessage')}, }; return acc; }, {}), @@ -313,7 +313,7 @@ function deletePolicyTaxes(policyID: string, taxesToDelete: string[]) { taxes: taxesToDelete.reduce((acc, taxID) => { acc[taxID] = { pendingAction: null, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.taxes.error.deleteFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.taxes.error.deleteFailureMessage'), }; return acc; }, {}), @@ -377,7 +377,7 @@ function updatePolicyTaxValue(policyID: string, taxID: string, taxValue: number) [taxID]: { value: originalTaxRate.value, pendingFields: {value: null}, - errorFields: {value: ErrorUtils.getMicroSecondOnyxError('workspace.taxes.error.updateFailureMessage')}, + errorFields: {value: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.taxes.error.updateFailureMessage')}, }, }, }, @@ -439,7 +439,7 @@ function renamePolicyTax(policyID: string, taxID: string, newName: string) { [taxID]: { name: originalTaxRate.name, pendingFields: {name: null}, - errorFields: {name: ErrorUtils.getMicroSecondOnyxError('workspace.taxes.error.updateFailureMessage')}, + errorFields: {name: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.taxes.error.updateFailureMessage')}, }, }, }, diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index f7e90f775b65..67c9a38afb35 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -156,7 +156,7 @@ function requestContactMethodValidateCode(contactMethod: string) { [contactMethod]: { validateCodeSent: false, errorFields: { - validateCodeSent: ErrorUtils.getMicroSecondOnyxError('contacts.genericFailureMessages.requestContactMethodValidateCode'), + validateCodeSent: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('contacts.genericFailureMessages.requestContactMethodValidateCode'), }, pendingFields: { validateCodeSent: null, @@ -239,7 +239,7 @@ function deleteContactMethod(contactMethod: string, loginList: Record [settingName, null])), - errorFields: Object.fromEntries(Object.keys(configUpdate).map((settingName) => [settingName, ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')])), + errorFields: Object.fromEntries( + Object.keys(configUpdate).map((settingName) => [settingName, ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')]), + ), }, }, }, diff --git a/src/pages/ChatFinderPage/index.tsx b/src/pages/ChatFinderPage/index.tsx index 35417cf4ecd4..9ec8a24d23c3 100644 --- a/src/pages/ChatFinderPage/index.tsx +++ b/src/pages/ChatFinderPage/index.tsx @@ -13,7 +13,6 @@ import useDebouncedState from '@hooks/useDebouncedState'; import useDismissedReferralBanners from '@hooks/useDismissedReferralBanners'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import type {MaybePhraseKey} from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import type {RootStackParamList} from '@libs/Navigation/types'; import * as OptionsListUtils from '@libs/OptionsListUtils'; @@ -59,7 +58,7 @@ function ChatFinderPage({betas, isSearchingForReports, navigation}: ChatFinderPa shouldInitialize: isScreenTransitionEnd, }); - const offlineMessage: MaybePhraseKey = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; + const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState(''); const [, debouncedSearchValueInServer, setSearchValueInServer] = useDebouncedState('', 500); diff --git a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx index 2260fc872270..a7a78aa9048c 100644 --- a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx +++ b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx @@ -96,7 +96,7 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat if (!ValidationUtils.isValidDisplayName(values.firstName)) { ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.hasInvalidCharacter'); } else if (values.firstName.length > CONST.DISPLAY_NAME.MAX_LENGTH) { - ErrorUtils.addErrorMessage(errors, 'firstName', ['common.error.characterLimitExceedCounter', {length: values.firstName.length, limit: CONST.DISPLAY_NAME.MAX_LENGTH}]); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('common.error.characterLimitExceedCounter', {length: values.firstName.length, limit: CONST.DISPLAY_NAME.MAX_LENGTH})); } if (ValidationUtils.doesContainReservedWord(values.firstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.containsReservedWord'); @@ -106,7 +106,7 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat if (!ValidationUtils.isValidDisplayName(values.lastName)) { ErrorUtils.addErrorMessage(errors, 'lastName', 'personalDetails.error.hasInvalidCharacter'); } else if (values.lastName.length > CONST.DISPLAY_NAME.MAX_LENGTH) { - ErrorUtils.addErrorMessage(errors, 'lastName', ['common.error.characterLimitExceedCounter', {length: values.lastName.length, limit: CONST.DISPLAY_NAME.MAX_LENGTH}]); + ErrorUtils.addErrorMessage(errors, 'lastName', translate('common.error.characterLimitExceedCounter', {length: values.lastName.length, limit: CONST.DISPLAY_NAME.MAX_LENGTH})); } if (ValidationUtils.doesContainReservedWord(values.lastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { ErrorUtils.addErrorMessage(errors, 'lastName', 'personalDetails.error.containsReservedWord'); diff --git a/src/pages/OnboardingWork/BaseOnboardingWork.tsx b/src/pages/OnboardingWork/BaseOnboardingWork.tsx index b0e01d0c8caa..cdaa264682d1 100644 --- a/src/pages/OnboardingWork/BaseOnboardingWork.tsx +++ b/src/pages/OnboardingWork/BaseOnboardingWork.tsx @@ -63,7 +63,7 @@ function BaseOnboardingWork({shouldUseNativeStyles, onboardingPurposeSelected, o } else if ([...work].length > CONST.TITLE_CHARACTER_LIMIT) { // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 // code units. - ErrorUtils.addErrorMessage(errors, 'work', ['common.error.characterLimitExceedCounter', {length: [...work].length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'work', translate('common.error.characterLimitExceedCounter', {length: [...work].length, limit: CONST.TITLE_CHARACTER_LIMIT})); } return errors; diff --git a/src/pages/ReimbursementAccount/AddressFormFields.tsx b/src/pages/ReimbursementAccount/AddressFormFields.tsx index 2133c4c5bf2e..c586c71f3d47 100644 --- a/src/pages/ReimbursementAccount/AddressFormFields.tsx +++ b/src/pages/ReimbursementAccount/AddressFormFields.tsx @@ -96,7 +96,7 @@ function AddressFormFields({shouldSaveDraft = false, defaultValues, values, erro onChangeText={(value) => onFieldChange?.({zipCode: value})} errorText={errors?.zipCode ? translate('bankAccount.error.zipCode') : ''} maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} - hint={['common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}]} + hint={translate('common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples})} containerStyles={styles.mt3} /> diff --git a/src/pages/iou/MoneyRequestAmountForm.tsx b/src/pages/iou/MoneyRequestAmountForm.tsx index 07037a09df11..01a0565c4f96 100644 --- a/src/pages/iou/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/MoneyRequestAmountForm.tsx @@ -213,7 +213,7 @@ function MoneyRequestAmountForm( } if (isTaxAmountInvalid(currentAmount, taxAmount, isTaxAmountForm)) { - setFormError([translate('iou.error.invalidTaxAmount'), {amount: formattedTaxAmount}]); + setFormError(translate('iou.error.invalidTaxAmount', {amount: formattedTaxAmount})); return; } diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 2000652d9511..113ece3eca35 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -19,7 +19,6 @@ import usePermissions from '@hooks/usePermissions'; import useScreenWrapperTranstionStatus from '@hooks/useScreenWrapperTransitionStatus'; import useThemeStyles from '@hooks/useThemeStyles'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; -import type {MaybePhraseKey} from '@libs/Localize'; import type {Options} from '@libs/OptionsListUtils'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as Policy from '@userActions/Policy/Policy'; @@ -65,7 +64,7 @@ function MoneyRequestParticipantsSelector({participants = [], onFinish, onPartic shouldInitialize: didScreenTransitionEnd, }); - const offlineMessage: MaybePhraseKey = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; + const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; const isIOUSplit = iouType === CONST.IOU.TYPE.SPLIT; const isCategorizeOrShareAction = [CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.ACTION.SHARE].some((option) => option === action); diff --git a/src/pages/iou/request/step/IOURequestStepDescription.tsx b/src/pages/iou/request/step/IOURequestStepDescription.tsx index e8388a92e602..cbee039e2b28 100644 --- a/src/pages/iou/request/step/IOURequestStepDescription.tsx +++ b/src/pages/iou/request/step/IOURequestStepDescription.tsx @@ -94,18 +94,22 @@ function IOURequestStepDescription({ /** * @returns - An object containing the errors for each inputID */ - const validate = useCallback((values: FormOnyxValues): FormInputErrors => { - const errors = {}; - - if (values.moneyRequestComment.length > CONST.DESCRIPTION_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'moneyRequestComment', [ - 'common.error.characterLimitExceedCounter', - {length: values.moneyRequestComment.length, limit: CONST.DESCRIPTION_LIMIT}, - ]); - } + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = {}; + + if (values.moneyRequestComment.length > CONST.DESCRIPTION_LIMIT) { + ErrorUtils.addErrorMessage( + errors, + 'moneyRequestComment', + translate('common.error.characterLimitExceedCounter', {length: values.moneyRequestComment.length, limit: CONST.DESCRIPTION_LIMIT}), + ); + } - return errors; - }, []); + return errors; + }, + [translate], + ); const navigateBack = () => { Navigation.goBack(backTo); diff --git a/src/pages/settings/Profile/DisplayNamePage.tsx b/src/pages/settings/Profile/DisplayNamePage.tsx index 3ab443b23561..830c06c9a254 100644 --- a/src/pages/settings/Profile/DisplayNamePage.tsx +++ b/src/pages/settings/Profile/DisplayNamePage.tsx @@ -49,7 +49,7 @@ function DisplayNamePage({isLoadingApp = true, currentUserPersonalDetails}: Disp if (!ValidationUtils.isValidDisplayName(values.firstName)) { ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.hasInvalidCharacter'); } else if (values.firstName.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'firstName', ['common.error.characterLimitExceedCounter', {length: values.firstName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('common.error.characterLimitExceedCounter', {length: values.firstName.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } if (ValidationUtils.doesContainReservedWord(values.firstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.containsReservedWord'); @@ -59,7 +59,7 @@ function DisplayNamePage({isLoadingApp = true, currentUserPersonalDetails}: Disp if (!ValidationUtils.isValidDisplayName(values.lastName)) { ErrorUtils.addErrorMessage(errors, 'lastName', 'personalDetails.error.hasInvalidCharacter'); } else if (values.lastName.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'lastName', ['common.error.characterLimitExceedCounter', {length: values.lastName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'lastName', translate('common.error.characterLimitExceedCounter', {length: values.lastName.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } if (ValidationUtils.doesContainReservedWord(values.lastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { ErrorUtils.addErrorMessage(errors, 'lastName', 'personalDetails.error.containsReservedWord'); diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx index 085c70b47937..1242618d1407 100644 --- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx @@ -49,10 +49,11 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP } else if (!values.legalFirstName) { errors.legalFirstName = 'common.error.fieldRequired'; } else if (values.legalFirstName.length > CONST.LEGAL_NAME.MAX_LENGTH) { - ErrorUtils.addErrorMessage(errors, 'legalFirstName', [ - 'common.error.characterLimitExceedCounter', - {length: values.legalFirstName.length, limit: CONST.LEGAL_NAME.MAX_LENGTH}, - ]); + ErrorUtils.addErrorMessage( + errors, + 'legalFirstName', + translate('common.error.characterLimitExceedCounter', {length: values.legalFirstName.length, limit: CONST.LEGAL_NAME.MAX_LENGTH}), + ); } if (ValidationUtils.doesContainReservedWord(values.legalFirstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'personalDetails.error.containsReservedWord'); @@ -65,7 +66,11 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP } else if (!values.legalLastName) { errors.legalLastName = 'common.error.fieldRequired'; } else if (values.legalLastName.length > CONST.LEGAL_NAME.MAX_LENGTH) { - ErrorUtils.addErrorMessage(errors, 'legalLastName', ['common.error.characterLimitExceedCounter', {length: values.legalLastName.length, limit: CONST.LEGAL_NAME.MAX_LENGTH}]); + ErrorUtils.addErrorMessage( + errors, + 'legalLastName', + translate('common.error.characterLimitExceedCounter', {length: values.legalLastName.length, limit: CONST.LEGAL_NAME.MAX_LENGTH}), + ); } if (ValidationUtils.doesContainReservedWord(values.legalLastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { ErrorUtils.addErrorMessage(errors, 'legalLastName', 'personalDetails.error.containsReservedWord'); @@ -73,7 +78,7 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP } return errors; - }, []); + }, [translate]); return ( CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'roomName', ['common.error.characterLimitExceedCounter', {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('common.error.characterLimitExceedCounter', {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } return errors; }, - [report, reports], + [report, reports, translate], ); return ( diff --git a/src/pages/settings/Wallet/AddDebitCardPage.tsx b/src/pages/settings/Wallet/AddDebitCardPage.tsx index b3bc1d839727..a5085b3d2315 100644 --- a/src/pages/settings/Wallet/AddDebitCardPage.tsx +++ b/src/pages/settings/Wallet/AddDebitCardPage.tsx @@ -199,7 +199,7 @@ function DebitCardPage({formData}: DebitCardPageProps) { role={CONST.ROLE.PRESENTATION} inputMode={CONST.INPUT_MODE.NUMERIC} maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} - hint={['common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}]} + hint={translate('common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples})} containerStyles={[styles.mt4]} /> diff --git a/src/pages/tasks/NewTaskDescriptionPage.tsx b/src/pages/tasks/NewTaskDescriptionPage.tsx index 93ad5e63f3d7..2f186149f9ae 100644 --- a/src/pages/tasks/NewTaskDescriptionPage.tsx +++ b/src/pages/tasks/NewTaskDescriptionPage.tsx @@ -49,7 +49,11 @@ function NewTaskDescriptionPage({task}: NewTaskDescriptionPageProps) { const errors = {}; if (values.taskDescription.length > CONST.DESCRIPTION_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'taskDescription', ['common.error.characterLimitExceedCounter', {length: values.taskDescription.length, limit: CONST.DESCRIPTION_LIMIT}]); + ErrorUtils.addErrorMessage( + errors, + 'taskDescription', + translate('common.error.characterLimitExceedCounter', {length: values.taskDescription.length, limit: CONST.DESCRIPTION_LIMIT}), + ); } return errors; diff --git a/src/pages/tasks/NewTaskDetailsPage.tsx b/src/pages/tasks/NewTaskDetailsPage.tsx index 52fdbf5523a2..ae269b1dbc81 100644 --- a/src/pages/tasks/NewTaskDetailsPage.tsx +++ b/src/pages/tasks/NewTaskDetailsPage.tsx @@ -58,10 +58,14 @@ function NewTaskDetailsPage({task}: NewTaskDetailsPageProps) { // We error if the user doesn't enter a task name ErrorUtils.addErrorMessage(errors, 'taskTitle', 'newTaskPage.pleaseEnterTaskName'); } else if (values.taskTitle.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'taskTitle', ['common.error.characterLimitExceedCounter', {length: values.taskTitle.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'taskTitle', translate('common.error.characterLimitExceedCounter', {length: values.taskTitle.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } if (values.taskDescription.length > CONST.DESCRIPTION_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'taskDescription', ['common.error.characterLimitExceedCounter', {length: values.taskDescription.length, limit: CONST.DESCRIPTION_LIMIT}]); + ErrorUtils.addErrorMessage( + errors, + 'taskDescription', + translate('common.error.characterLimitExceedCounter', {length: values.taskDescription.length, limit: CONST.DESCRIPTION_LIMIT}), + ); } return errors; diff --git a/src/pages/tasks/NewTaskTitlePage.tsx b/src/pages/tasks/NewTaskTitlePage.tsx index 582d2a5c6500..0ff6c178d24a 100644 --- a/src/pages/tasks/NewTaskTitlePage.tsx +++ b/src/pages/tasks/NewTaskTitlePage.tsx @@ -42,7 +42,7 @@ function NewTaskTitlePage({task}: NewTaskTitlePageProps) { // We error if the user doesn't enter a task name ErrorUtils.addErrorMessage(errors, 'taskTitle', 'newTaskPage.pleaseEnterTaskName'); } else if (values.taskTitle.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'taskTitle', ['common.error.characterLimitExceedCounter', {length: values.taskTitle.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'taskTitle', translate('common.error.characterLimitExceedCounter', {length: values.taskTitle.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } return errors; diff --git a/src/pages/tasks/TaskDescriptionPage.tsx b/src/pages/tasks/TaskDescriptionPage.tsx index c48746c81239..dbceacd1e97a 100644 --- a/src/pages/tasks/TaskDescriptionPage.tsx +++ b/src/pages/tasks/TaskDescriptionPage.tsx @@ -39,11 +39,11 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti const errors = {}; if (values?.description && values.description?.length > CONST.DESCRIPTION_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'description', ['common.error.characterLimitExceedCounter', {length: values.description.length, limit: CONST.DESCRIPTION_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'description', translate('common.error.characterLimitExceedCounter', {length: values.description.length, limit: CONST.DESCRIPTION_LIMIT})); } return errors; - }, []); + }, [translate]); const submit = useCallback( (values: FormOnyxValues) => { diff --git a/src/pages/tasks/TaskTitlePage.tsx b/src/pages/tasks/TaskTitlePage.tsx index 99558efaeb03..918d9d624f5b 100644 --- a/src/pages/tasks/TaskTitlePage.tsx +++ b/src/pages/tasks/TaskTitlePage.tsx @@ -35,11 +35,11 @@ function TaskTitlePage({report, currentUserPersonalDetails}: TaskTitlePageProps) if (!title) { ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, 'newTaskPage.pleaseEnterTaskName'); } else if (title.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, ['common.error.characterLimitExceedCounter', {length: title.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, translate('common.error.characterLimitExceedCounter', {length: title.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } return errors; - }, []); + }, [translate]); const submit = useCallback( (values: FormOnyxValues) => { diff --git a/src/pages/workspace/WorkspaceNamePage.tsx b/src/pages/workspace/WorkspaceNamePage.tsx index 6eea77962334..173543043a6b 100644 --- a/src/pages/workspace/WorkspaceNamePage.tsx +++ b/src/pages/workspace/WorkspaceNamePage.tsx @@ -47,11 +47,11 @@ function WorkspaceNamePage({policy}: Props) { } else if ([...name].length > CONST.TITLE_CHARACTER_LIMIT) { // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 // code units. - ErrorUtils.addErrorMessage(errors, 'name', ['common.error.characterLimitExceedCounter', {length: [...name].length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'name', translate('common.error.characterLimitExceedCounter', {length: [...name].length, limit: CONST.TITLE_CHARACTER_LIMIT})); } return errors; - }, []); + }, [translate]); return ( CONST.DESCRIPTION_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'description', ['common.error.characterLimitExceedCounter', {length: values.description.length, limit: CONST.DESCRIPTION_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'description', translate('common.error.characterLimitExceedCounter', {length: values.description.length, limit: CONST.DESCRIPTION_LIMIT})); } return errors; - }, []); + }, [translate]); const submit = useCallback( (values: FormOnyxValues) => { diff --git a/src/pages/workspace/categories/CategoryForm.tsx b/src/pages/workspace/categories/CategoryForm.tsx index 397677ab749a..e045889ff6b6 100644 --- a/src/pages/workspace/categories/CategoryForm.tsx +++ b/src/pages/workspace/categories/CategoryForm.tsx @@ -48,12 +48,16 @@ function CategoryForm({onSubmit, policyCategories, categoryName, validateEdit}: errors.categoryName = 'workspace.categories.invalidCategoryName'; } else if ([...newCategoryName].length > CONST.CATEGORY_NAME_LIMIT) { // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 code units. - ErrorUtils.addErrorMessage(errors, 'categoryName', ['common.error.characterLimitExceedCounter', {length: [...newCategoryName].length, limit: CONST.CATEGORY_NAME_LIMIT}]); + ErrorUtils.addErrorMessage( + errors, + 'categoryName', + translate('common.error.characterLimitExceedCounter', {length: [...newCategoryName].length, limit: CONST.CATEGORY_NAME_LIMIT}), + ); } return errors; }, - [policyCategories], + [policyCategories, translate], ); const submit = useCallback( diff --git a/src/pages/workspace/tags/WorkspaceCreateTagPage.tsx b/src/pages/workspace/tags/WorkspaceCreateTagPage.tsx index 0ed373f135e4..408bf4eb2366 100644 --- a/src/pages/workspace/tags/WorkspaceCreateTagPage.tsx +++ b/src/pages/workspace/tags/WorkspaceCreateTagPage.tsx @@ -49,12 +49,12 @@ function CreateTagPage({route, policyTags}: CreateTagPageProps) { errors.tagName = 'workspace.tags.existingTagError'; } else if ([...tagName].length > CONST.TAG_NAME_LIMIT) { // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 code units. - ErrorUtils.addErrorMessage(errors, 'tagName', ['common.error.characterLimitExceedCounter', {length: [...tagName].length, limit: CONST.TAG_NAME_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'tagName', translate('common.error.characterLimitExceedCounter', {length: [...tagName].length, limit: CONST.TAG_NAME_LIMIT})); } return errors; }, - [policyTags], + [policyTags, translate], ); const createTag = useCallback( diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 63417b7ddd3b..164e51393e21 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -1862,7 +1862,7 @@ describe('actions/IOU', () => { Onyx.disconnect(connectionID); const updatedAction = Object.values(allActions ?? {}).find((reportAction) => !isEmptyObject(reportAction)); expect(updatedAction?.actionName).toEqual('MODIFIEDEXPENSE'); - expect(Object.values(updatedAction?.errors ?? {})).toEqual(Localize.translateLocal('iou.error.genericEditFailureMessage')); + expect(Object.values(updatedAction?.errors ?? {})[0]).toEqual(Localize.translateLocal('iou.error.genericEditFailureMessage')); resolve(); }, }); From 20e829fe0f9d92937b11fb9517613605d6c9be5e Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 15:48:25 +0700 Subject: [PATCH 08/24] fix test --- .../Profile/PersonalDetails/LegalNamePage.tsx | 71 ++++++++++--------- src/pages/tasks/TaskDescriptionPage.tsx | 17 +++-- src/pages/tasks/TaskTitlePage.tsx | 21 +++--- src/pages/workspace/WorkspaceNamePage.tsx | 27 +++---- .../WorkspaceProfileDescriptionPage.tsx | 17 +++-- tests/actions/IOUTest.ts | 2 +- tests/unit/ValidationUtilsTest.ts | 11 ++- 7 files changed, 93 insertions(+), 73 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx index 1242618d1407..83f8456f5fd3 100644 --- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx @@ -40,45 +40,48 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP const legalFirstName = privatePersonalDetails?.legalFirstName ?? ''; const legalLastName = privatePersonalDetails?.legalLastName ?? ''; - const validate = useCallback((values: FormOnyxValues) => { - const errors: Errors = {}; + const validate = useCallback( + (values: FormOnyxValues) => { + const errors: Errors = {}; - if (typeof values.legalFirstName === 'string') { - if (!ValidationUtils.isValidLegalName(values.legalFirstName)) { - ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'privatePersonalDetails.error.hasInvalidCharacter'); - } else if (!values.legalFirstName) { - errors.legalFirstName = 'common.error.fieldRequired'; - } else if (values.legalFirstName.length > CONST.LEGAL_NAME.MAX_LENGTH) { - ErrorUtils.addErrorMessage( - errors, - 'legalFirstName', - translate('common.error.characterLimitExceedCounter', {length: values.legalFirstName.length, limit: CONST.LEGAL_NAME.MAX_LENGTH}), - ); + if (typeof values.legalFirstName === 'string') { + if (!ValidationUtils.isValidLegalName(values.legalFirstName)) { + ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'privatePersonalDetails.error.hasInvalidCharacter'); + } else if (!values.legalFirstName) { + errors.legalFirstName = 'common.error.fieldRequired'; + } else if (values.legalFirstName.length > CONST.LEGAL_NAME.MAX_LENGTH) { + ErrorUtils.addErrorMessage( + errors, + 'legalFirstName', + translate('common.error.characterLimitExceedCounter', {length: values.legalFirstName.length, limit: CONST.LEGAL_NAME.MAX_LENGTH}), + ); + } + if (ValidationUtils.doesContainReservedWord(values.legalFirstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { + ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'personalDetails.error.containsReservedWord'); + } } - if (ValidationUtils.doesContainReservedWord(values.legalFirstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'personalDetails.error.containsReservedWord'); - } - } - if (typeof values.legalLastName === 'string') { - if (!ValidationUtils.isValidLegalName(values.legalLastName)) { - ErrorUtils.addErrorMessage(errors, 'legalLastName', 'privatePersonalDetails.error.hasInvalidCharacter'); - } else if (!values.legalLastName) { - errors.legalLastName = 'common.error.fieldRequired'; - } else if (values.legalLastName.length > CONST.LEGAL_NAME.MAX_LENGTH) { - ErrorUtils.addErrorMessage( - errors, - 'legalLastName', - translate('common.error.characterLimitExceedCounter', {length: values.legalLastName.length, limit: CONST.LEGAL_NAME.MAX_LENGTH}), - ); - } - if (ValidationUtils.doesContainReservedWord(values.legalLastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'legalLastName', 'personalDetails.error.containsReservedWord'); + if (typeof values.legalLastName === 'string') { + if (!ValidationUtils.isValidLegalName(values.legalLastName)) { + ErrorUtils.addErrorMessage(errors, 'legalLastName', 'privatePersonalDetails.error.hasInvalidCharacter'); + } else if (!values.legalLastName) { + errors.legalLastName = 'common.error.fieldRequired'; + } else if (values.legalLastName.length > CONST.LEGAL_NAME.MAX_LENGTH) { + ErrorUtils.addErrorMessage( + errors, + 'legalLastName', + translate('common.error.characterLimitExceedCounter', {length: values.legalLastName.length, limit: CONST.LEGAL_NAME.MAX_LENGTH}), + ); + } + if (ValidationUtils.doesContainReservedWord(values.legalLastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { + ErrorUtils.addErrorMessage(errors, 'legalLastName', 'personalDetails.error.containsReservedWord'); + } } - } - return errors; - }, [translate]); + return errors; + }, + [translate], + ); return ( ): FormInputErrors => { - const errors = {}; + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = {}; - if (values?.description && values.description?.length > CONST.DESCRIPTION_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'description', translate('common.error.characterLimitExceedCounter', {length: values.description.length, limit: CONST.DESCRIPTION_LIMIT})); - } + if (values?.description && values.description?.length > CONST.DESCRIPTION_LIMIT) { + ErrorUtils.addErrorMessage(errors, 'description', translate('common.error.characterLimitExceedCounter', {length: values.description.length, limit: CONST.DESCRIPTION_LIMIT})); + } - return errors; - }, [translate]); + return errors; + }, + [translate], + ); const submit = useCallback( (values: FormOnyxValues) => { diff --git a/src/pages/tasks/TaskTitlePage.tsx b/src/pages/tasks/TaskTitlePage.tsx index 918d9d624f5b..70ced7a81072 100644 --- a/src/pages/tasks/TaskTitlePage.tsx +++ b/src/pages/tasks/TaskTitlePage.tsx @@ -29,17 +29,20 @@ function TaskTitlePage({report, currentUserPersonalDetails}: TaskTitlePageProps) const styles = useThemeStyles(); const {translate} = useLocalize(); - const validate = useCallback(({title}: FormOnyxValues): FormInputErrors => { - const errors: FormInputErrors = {}; + const validate = useCallback( + ({title}: FormOnyxValues): FormInputErrors => { + const errors: FormInputErrors = {}; - if (!title) { - ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, 'newTaskPage.pleaseEnterTaskName'); - } else if (title.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, translate('common.error.characterLimitExceedCounter', {length: title.length, limit: CONST.TITLE_CHARACTER_LIMIT})); - } + if (!title) { + ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, 'newTaskPage.pleaseEnterTaskName'); + } else if (title.length > CONST.TITLE_CHARACTER_LIMIT) { + ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, translate('common.error.characterLimitExceedCounter', {length: title.length, limit: CONST.TITLE_CHARACTER_LIMIT})); + } - return errors; - }, [translate]); + return errors; + }, + [translate], + ); const submit = useCallback( (values: FormOnyxValues) => { diff --git a/src/pages/workspace/WorkspaceNamePage.tsx b/src/pages/workspace/WorkspaceNamePage.tsx index 173543043a6b..03d4e7107c1c 100644 --- a/src/pages/workspace/WorkspaceNamePage.tsx +++ b/src/pages/workspace/WorkspaceNamePage.tsx @@ -38,20 +38,23 @@ function WorkspaceNamePage({policy}: Props) { [policy], ); - const validate = useCallback((values: FormOnyxValues) => { - const errors: FormInputErrors = {}; - const name = values.name.trim(); + const validate = useCallback( + (values: FormOnyxValues) => { + const errors: FormInputErrors = {}; + const name = values.name.trim(); - if (!ValidationUtils.isRequiredFulfilled(name)) { - errors.name = 'workspace.editor.nameIsRequiredError'; - } else if ([...name].length > CONST.TITLE_CHARACTER_LIMIT) { - // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 - // code units. - ErrorUtils.addErrorMessage(errors, 'name', translate('common.error.characterLimitExceedCounter', {length: [...name].length, limit: CONST.TITLE_CHARACTER_LIMIT})); - } + if (!ValidationUtils.isRequiredFulfilled(name)) { + errors.name = 'workspace.editor.nameIsRequiredError'; + } else if ([...name].length > CONST.TITLE_CHARACTER_LIMIT) { + // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 + // code units. + ErrorUtils.addErrorMessage(errors, 'name', translate('common.error.characterLimitExceedCounter', {length: [...name].length, limit: CONST.TITLE_CHARACTER_LIMIT})); + } - return errors; - }, [translate]); + return errors; + }, + [translate], + ); return ( ) => { - const errors = {}; + const validate = useCallback( + (values: FormOnyxValues) => { + const errors = {}; - if (values.description.length > CONST.DESCRIPTION_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'description', translate('common.error.characterLimitExceedCounter', {length: values.description.length, limit: CONST.DESCRIPTION_LIMIT})); - } + if (values.description.length > CONST.DESCRIPTION_LIMIT) { + ErrorUtils.addErrorMessage(errors, 'description', translate('common.error.characterLimitExceedCounter', {length: values.description.length, limit: CONST.DESCRIPTION_LIMIT})); + } - return errors; - }, [translate]); + return errors; + }, + [translate], + ); const submit = useCallback( (values: FormOnyxValues) => { diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 164e51393e21..de0e4556ba5e 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -2084,7 +2084,7 @@ describe('actions/IOU', () => { callback: (allActions) => { Onyx.disconnect(connectionID); const erroredAction = Object.values(allActions ?? {}).find((action) => !isEmptyObject(action?.errors)); - expect(Object.values(erroredAction?.errors ?? {})).toEqual(Localize.translateLocal('iou.error.other')); + expect(Object.values(erroredAction?.errors ?? {})[0]).toEqual(Localize.translateLocal('iou.error.other')); resolve(); }, }); diff --git a/tests/unit/ValidationUtilsTest.ts b/tests/unit/ValidationUtilsTest.ts index fc5dacee2cf2..3bd083bc07e4 100644 --- a/tests/unit/ValidationUtilsTest.ts +++ b/tests/unit/ValidationUtilsTest.ts @@ -1,4 +1,5 @@ import {addDays, format, startOfDay, subYears} from 'date-fns'; +import * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; import * as ValidationUtils from '@src/libs/ValidationUtils'; @@ -186,19 +187,23 @@ describe('ValidationUtils', () => { test('Should return an error message for a date before the minimum age requirement', () => { const invalidDate: string = format(subYears(new Date(), 17), CONST.DATE.FNS_FORMAT_STRING); // Date of birth 17 years ago const error = ValidationUtils.getAgeRequirementError(invalidDate, 18, 150); - expect(error).toEqual(['privatePersonalDetails.error.dateShouldBeBefore', {dateString: format(startOfDay(subYears(new Date(), 18)), CONST.DATE.FNS_FORMAT_STRING)}]); + expect(error).toEqual( + Localize.translateLocal('privatePersonalDetails.error.dateShouldBeBefore', {dateString: format(startOfDay(subYears(new Date(), 18)), CONST.DATE.FNS_FORMAT_STRING)}), + ); }); test('Should return an error message for a date after the maximum age requirement', () => { const invalidDate: string = format(subYears(new Date(), 160), CONST.DATE.FNS_FORMAT_STRING); // Date of birth 160 years ago const error = ValidationUtils.getAgeRequirementError(invalidDate, 18, 150); - expect(error).toEqual(['privatePersonalDetails.error.dateShouldBeAfter', {dateString: format(startOfDay(subYears(new Date(), 150)), CONST.DATE.FNS_FORMAT_STRING)}]); + expect(error).toEqual( + Localize.translateLocal('privatePersonalDetails.error.dateShouldBeAfter', {dateString: format(startOfDay(subYears(new Date(), 150)), CONST.DATE.FNS_FORMAT_STRING)}), + ); }); test('Should return an error message for an invalid date', () => { const invalidDate = '2023-07-32'; // Invalid date const error = ValidationUtils.getAgeRequirementError(invalidDate, 18, 150); - expect(error).toBe('common.error.dateInvalid'); + expect(error).toBe(Localize.translateLocal('common.error.dateInvalid')); }); }); From a7fb5482db646a8e41a4be8254d851172343b183 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 16:04:33 +0700 Subject: [PATCH 09/24] fix lint --- src/components/AddPlaidBankAccount.tsx | 1 + src/components/Form/FormProvider.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/src/components/AddPlaidBankAccount.tsx b/src/components/AddPlaidBankAccount.tsx index 366f14ec9780..26444b1a48c4 100644 --- a/src/components/AddPlaidBankAccount.tsx +++ b/src/components/AddPlaidBankAccount.tsx @@ -177,6 +177,7 @@ function AddPlaidBankAccount({ })); const {icon, iconSize, iconStyles} = getBankIcon({styles}); const plaidErrors = plaidData?.errors; + // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style const plaidDataErrorMessage = !isEmptyObject(plaidErrors) ? (Object.values(plaidErrors)[0] as string) : ''; const bankName = plaidData?.bankName; diff --git a/src/components/Form/FormProvider.tsx b/src/components/Form/FormProvider.tsx index 3d20f910dca0..bd65d3046e18 100644 --- a/src/components/Form/FormProvider.tsx +++ b/src/components/Form/FormProvider.tsx @@ -256,6 +256,7 @@ function FormProvider( (Object.keys(errorFields) .sort() .map((key) => errorFields[key]) + // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style .at(-1) as string) ?? ''; const inputRef = inputProps.ref; From 6d3a233ef472f09fc30f01ce115d07a5f9309b28 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 16:22:02 +0700 Subject: [PATCH 10/24] fix test --- src/components/Form/FormProvider.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Form/FormProvider.tsx b/src/components/Form/FormProvider.tsx index bd65d3046e18..536af18d85b3 100644 --- a/src/components/Form/FormProvider.tsx +++ b/src/components/Form/FormProvider.tsx @@ -256,8 +256,7 @@ function FormProvider( (Object.keys(errorFields) .sort() .map((key) => errorFields[key]) - // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - .at(-1) as string) ?? ''; + .at(-1)) ?? ''; const inputRef = inputProps.ref; From 0c4cabc755963e8ccae139198d6f7e9e830d6248 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 3 Jun 2024 16:31:03 +0700 Subject: [PATCH 11/24] fix prettier --- src/components/Form/FormProvider.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Form/FormProvider.tsx b/src/components/Form/FormProvider.tsx index 536af18d85b3..16ecc3805d2d 100644 --- a/src/components/Form/FormProvider.tsx +++ b/src/components/Form/FormProvider.tsx @@ -253,10 +253,10 @@ function FormProvider( const errorFields = formState?.errorFields?.[inputID] ?? {}; const fieldErrorMessage = - (Object.keys(errorFields) + Object.keys(errorFields) .sort() .map((key) => errorFields[key]) - .at(-1)) ?? ''; + .at(-1) ?? ''; const inputRef = inputProps.ref; From f29281c39395a8378d87b52a3d040ee9b68b14cd Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 4 Jun 2024 00:05:08 +0700 Subject: [PATCH 12/24] add missing form helper error translation --- src/libs/PolicyDistanceRatesUtils.ts | 5 ++- src/libs/actions/BankAccounts.ts | 3 +- src/pages/EditReportFieldText.tsx | 4 +- .../PersonalInfo/substeps/AddressStep.tsx | 28 +++++++------- .../PersonalInfo/substeps/FullNameStep.tsx | 24 ++++++------ .../PersonalInfo/substeps/PhoneNumberStep.tsx | 17 +++++---- .../substeps/SocialSecurityNumberStep.tsx | 19 +++++----- .../BaseOnboardingPersonalDetails.tsx | 10 ++--- .../OnboardingWork/BaseOnboardingWork.tsx | 2 +- .../BankInfo/substeps/Manual.tsx | 37 ++++++++++--------- .../AddressUBO.tsx | 4 +- .../SocialSecurityNumberUBO.tsx | 2 +- .../BusinessInfo/substeps/AddressBusiness.tsx | 32 ++++++++-------- .../BusinessInfo/substeps/NameBusiness.tsx | 20 +++++----- .../substeps/PhoneNumberBusiness.tsx | 20 +++++----- .../BusinessInfo/substeps/TaxIdBusiness.tsx | 21 +++++------ .../BusinessInfo/substeps/WebsiteBusiness.tsx | 20 +++++----- .../components/BankAccountValidationForm.tsx | 2 +- .../PersonalInfo/substeps/Address.tsx | 28 +++++++------- .../PersonalInfo/substeps/FullName.tsx | 25 ++++++------- .../substeps/SocialSecurityNumber.tsx | 19 +++++----- .../IntroSchoolPrincipalPage.tsx | 14 +++---- src/pages/TeachersUnite/KnowATeacherPage.tsx | 12 +++--- src/pages/iou/HoldReasonPage.tsx | 6 +-- .../request/step/IOURequestStepMerchant.tsx | 4 +- .../request/step/IOURequestStepWaypoint.tsx | 4 +- .../ExitSurvey/ExitSurveyReasonPage.tsx | 2 +- .../ExitSurvey/ExitSurveyResponsePage.tsx | 2 +- .../Profile/Contacts/NewContactMethodPage.tsx | 6 +-- .../settings/Profile/DisplayNamePage.tsx | 8 ++-- .../Profile/PersonalDetails/LegalNamePage.tsx | 10 ++--- src/pages/settings/Report/RoomNamePage.tsx | 6 +-- .../settings/Security/CloseAccountPage.tsx | 2 +- .../Wallet/Card/GetPhysicalCardName.tsx | 8 ++-- .../Wallet/Card/GetPhysicalCardPhone.tsx | 4 +- src/pages/tasks/NewTaskDetailsPage.tsx | 2 +- src/pages/tasks/NewTaskTitlePage.tsx | 2 +- src/pages/tasks/TaskTitlePage.tsx | 2 +- .../workspace/WorkspaceInviteMessagePage.tsx | 2 +- src/pages/workspace/WorkspaceNamePage.tsx | 2 +- .../workspace/categories/CategoryForm.tsx | 6 +-- .../workspace/categories/EditCategoryPage.tsx | 6 +-- .../members/WorkspaceOwnerPaymentCardForm.tsx | 12 +++--- src/pages/workspace/tags/EditTagPage.tsx | 6 +-- .../workspace/tags/WorkspaceCreateTagPage.tsx | 4 +- .../workspace/tags/WorkspaceEditTagsPage.tsx | 16 ++++---- .../WorkspaceTaxesSettingsCustomTaxName.tsx | 19 ++++++---- 47 files changed, 259 insertions(+), 250 deletions(-) diff --git a/src/libs/PolicyDistanceRatesUtils.ts b/src/libs/PolicyDistanceRatesUtils.ts index db739cc3b8c7..11ee74bab232 100644 --- a/src/libs/PolicyDistanceRatesUtils.ts +++ b/src/libs/PolicyDistanceRatesUtils.ts @@ -4,6 +4,7 @@ import type ONYXKEYS from '@src/ONYXKEYS'; import type {Rate} from '@src/types/onyx/Policy'; import * as CurrencyUtils from './CurrencyUtils'; import getPermittedDecimalSeparator from './getPermittedDecimalSeparator'; +import * as Localize from './Localize'; import * as MoneyRequestUtils from './MoneyRequestUtils'; import * as NumberUtils from './NumberUtils'; @@ -17,9 +18,9 @@ function validateRateValue(values: FormOnyxValues, currency: stri // Allow one more decimal place for accuracy const rateValueRegex = RegExp(String.raw`^-?\d{0,8}([${getPermittedDecimalSeparator(decimalSeparator)}]\d{0,${CurrencyUtils.getCurrencyDecimals(currency) + 1}})?$`, 'i'); if (!rateValueRegex.test(parsedRate) || parsedRate === '') { - errors.rate = 'workspace.reimburse.invalidRateError'; + errors.rate = Localize.translateLocal('workspace.reimburse.invalidRateError'); } else if (NumberUtils.parseFloatAnyLocale(parsedRate) <= 0) { - errors.rate = 'workspace.reimburse.lowRateError'; + errors.rate = Localize.translateLocal('workspace.reimburse.lowRateError'); } return errors; } diff --git a/src/libs/actions/BankAccounts.ts b/src/libs/actions/BankAccounts.ts index 89d0296994e3..3912572418c2 100644 --- a/src/libs/actions/BankAccounts.ts +++ b/src/libs/actions/BankAccounts.ts @@ -14,6 +14,7 @@ import type { } from '@libs/API/parameters'; import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; +import * as Localize from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -532,7 +533,7 @@ function validatePlaidSelection(values: FormOnyxValues): Form const errorFields: FormInputErrors = {}; if (!values.selectedPlaidAccountID) { - errorFields.selectedPlaidAccountID = 'bankAccount.error.youNeedToSelectAnOption'; + errorFields.selectedPlaidAccountID = Localize.translateLocal('bankAccount.error.youNeedToSelectAnOption'); } return errorFields; diff --git a/src/pages/EditReportFieldText.tsx b/src/pages/EditReportFieldText.tsx index 0649d59cd2ee..d619eb52b695 100644 --- a/src/pages/EditReportFieldText.tsx +++ b/src/pages/EditReportFieldText.tsx @@ -36,11 +36,11 @@ function EditReportFieldTextPage({fieldName, onSubmit, fieldValue, isRequired, f (values: FormOnyxValues) => { const errors: FormInputErrors = {}; if (isRequired && values[fieldKey].trim() === '') { - errors[fieldKey] = 'common.error.fieldRequired'; + errors[fieldKey] = translate('common.error.fieldRequired'); } return errors; }, - [fieldKey, isRequired], + [fieldKey, isRequired, translate], ); return ( diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/AddressStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/AddressStep.tsx index ad490fa2d7c9..22347f1b3bff 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/AddressStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/AddressStep.tsx @@ -25,20 +25,6 @@ const INPUT_KEYS = { const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.STREET, PERSONAL_INFO_STEP_KEY.CITY, PERSONAL_INFO_STEP_KEY.STATE, PERSONAL_INFO_STEP_KEY.ZIP_CODE]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { - errors.addressStreet = 'bankAccount.error.addressStreet'; - } - - if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { - errors.addressZipCode = 'bankAccount.error.zipCode'; - } - - return errors; -}; - function AddressStep({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -52,6 +38,20 @@ function AddressStep({onNext, isEditing}: SubStepProps) { zipCode: walletAdditionalDetails?.[PERSONAL_INFO_STEP_KEY.ZIP_CODE] ?? '', }; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { + errors.addressStreet = translate('bankAccount.error.addressStreet'); + } + + if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { + errors.addressZipCode = translate('bankAccount.error.zipCode'); + } + + return errors; + }; + const handleSubmit = useWalletAdditionalDetailsStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/FullNameStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/FullNameStep.tsx index f63d5ef84879..89240720f533 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/FullNameStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/FullNameStep.tsx @@ -19,18 +19,6 @@ import INPUT_IDS from '@src/types/form/WalletAdditionalDetailsForm'; const PERSONAL_INFO_STEP_KEY = INPUT_IDS.PERSONAL_INFO_STEP; const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.FIRST_NAME, PERSONAL_INFO_STEP_KEY.LAST_NAME]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.legalFirstName && !ValidationUtils.isValidLegalName(values.legalFirstName)) { - errors.legalFirstName = 'bankAccount.error.firstName'; - } - - if (values.legalLastName && !ValidationUtils.isValidLegalName(values.legalLastName)) { - errors.legalLastName = 'bankAccount.error.lastName'; - } - return errors; -}; - function FullNameStep({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -42,6 +30,18 @@ function FullNameStep({onNext, isEditing}: SubStepProps) { lastName: walletAdditionalDetails?.[PERSONAL_INFO_STEP_KEY.LAST_NAME] ?? '', }; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + if (values.legalFirstName && !ValidationUtils.isValidLegalName(values.legalFirstName)) { + errors.legalFirstName = translate('bankAccount.error.firstName'); + } + + if (values.legalLastName && !ValidationUtils.isValidLegalName(values.legalLastName)) { + errors.legalLastName = translate('bankAccount.error.lastName'); + } + return errors; + }; + const handleSubmit = useWalletAdditionalDetailsStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/PhoneNumberStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/PhoneNumberStep.tsx index 86b6a40948fc..a5326504a1c6 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/PhoneNumberStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/PhoneNumberStep.tsx @@ -19,14 +19,6 @@ import INPUT_IDS from '@src/types/form/WalletAdditionalDetailsForm'; const PERSONAL_INFO_STEP_KEY = INPUT_IDS.PERSONAL_INFO_STEP; const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.PHONE_NUMBER]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.phoneNumber && !ValidationUtils.isValidUSPhone(values.phoneNumber, true)) { - errors.phoneNumber = 'bankAccount.error.phoneNumber'; - } - return errors; -}; function PhoneNumberStep({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -35,6 +27,15 @@ function PhoneNumberStep({onNext, isEditing}: SubStepProps) { const defaultPhoneNumber = walletAdditionalDetails?.[PERSONAL_INFO_STEP_KEY.PHONE_NUMBER] ?? ''; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.phoneNumber && !ValidationUtils.isValidUSPhone(values.phoneNumber, true)) { + errors.phoneNumber = translate('bankAccount.error.phoneNumber'); + } + return errors; + }; + const handleSubmit = useWalletAdditionalDetailsStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/SocialSecurityNumberStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/SocialSecurityNumberStep.tsx index 4c366c5a1873..cb3f2fa263f7 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/SocialSecurityNumberStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/SocialSecurityNumberStep.tsx @@ -19,19 +19,20 @@ import INPUT_IDS from '@src/types/form/WalletAdditionalDetailsForm'; const PERSONAL_INFO_STEP_KEY = INPUT_IDS.PERSONAL_INFO_STEP; const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.SSN_LAST_4]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.ssn && !ValidationUtils.isValidSSNLastFour(values.ssn)) { - errors.ssn = 'bankAccount.error.ssnLast4'; - } - - return errors; -}; function SocialSecurityNumberStep({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.ssn && !ValidationUtils.isValidSSNLastFour(values.ssn)) { + errors.ssn = translate('bankAccount.error.ssnLast4'); + } + + return errors; + }; + const [walletAdditionalDetails] = useOnyx(ONYXKEYS.WALLET_ADDITIONAL_DETAILS); const defaultSsnLast4 = walletAdditionalDetails?.[PERSONAL_INFO_STEP_KEY.SSN_LAST_4] ?? ''; diff --git a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx index a7a78aa9048c..7a5fa8fe013a 100644 --- a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx +++ b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx @@ -91,25 +91,25 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat // First we validate the first name field if (values.firstName.replace(CONST.REGEX.ANY_SPACE, '').length === 0) { - ErrorUtils.addErrorMessage(errors, 'firstName', 'onboarding.error.requiredFirstName'); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('onboarding.error.requiredFirstName')); } if (!ValidationUtils.isValidDisplayName(values.firstName)) { - ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.hasInvalidCharacter'); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('personalDetails.error.hasInvalidCharacter')); } else if (values.firstName.length > CONST.DISPLAY_NAME.MAX_LENGTH) { ErrorUtils.addErrorMessage(errors, 'firstName', translate('common.error.characterLimitExceedCounter', {length: values.firstName.length, limit: CONST.DISPLAY_NAME.MAX_LENGTH})); } if (ValidationUtils.doesContainReservedWord(values.firstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.containsReservedWord'); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('personalDetails.error.containsReservedWord')); } // Then we validate the last name field if (!ValidationUtils.isValidDisplayName(values.lastName)) { - ErrorUtils.addErrorMessage(errors, 'lastName', 'personalDetails.error.hasInvalidCharacter'); + ErrorUtils.addErrorMessage(errors, 'lastName', translate('personalDetails.error.hasInvalidCharacter')); } else if (values.lastName.length > CONST.DISPLAY_NAME.MAX_LENGTH) { ErrorUtils.addErrorMessage(errors, 'lastName', translate('common.error.characterLimitExceedCounter', {length: values.lastName.length, limit: CONST.DISPLAY_NAME.MAX_LENGTH})); } if (ValidationUtils.doesContainReservedWord(values.lastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'lastName', 'personalDetails.error.containsReservedWord'); + ErrorUtils.addErrorMessage(errors, 'lastName', translate('personalDetails.error.containsReservedWord')); } return errors; diff --git a/src/pages/OnboardingWork/BaseOnboardingWork.tsx b/src/pages/OnboardingWork/BaseOnboardingWork.tsx index cdaa264682d1..9b8824300d30 100644 --- a/src/pages/OnboardingWork/BaseOnboardingWork.tsx +++ b/src/pages/OnboardingWork/BaseOnboardingWork.tsx @@ -59,7 +59,7 @@ function BaseOnboardingWork({shouldUseNativeStyles, onboardingPurposeSelected, o const work = values.work.trim(); if (!ValidationUtils.isRequiredFulfilled(work)) { - errors.work = 'workspace.editor.nameIsRequiredError'; + errors.work = translate('workspace.editor.nameIsRequiredError'); } else if ([...work].length > CONST.TITLE_CHARACTER_LIMIT) { // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 // code units. diff --git a/src/pages/ReimbursementAccount/BankInfo/substeps/Manual.tsx b/src/pages/ReimbursementAccount/BankInfo/substeps/Manual.tsx index 3f58d7a2073e..b85ca99b2935 100644 --- a/src/pages/ReimbursementAccount/BankInfo/substeps/Manual.tsx +++ b/src/pages/ReimbursementAccount/BankInfo/substeps/Manual.tsx @@ -37,25 +37,28 @@ function Manual({reimbursementAccount, onNext}: ManualProps) { [BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER]: reimbursementAccount?.achData?.[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER] ?? '', }; - const validate = useCallback((values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - const routingNumber = values.routingNumber?.trim(); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const routingNumber = values.routingNumber?.trim(); - if ( - values.accountNumber && - !CONST.BANK_ACCOUNT.REGEX.US_ACCOUNT_NUMBER.test(values.accountNumber.trim()) && - !CONST.BANK_ACCOUNT.REGEX.MASKED_US_ACCOUNT_NUMBER.test(values.accountNumber.trim()) - ) { - errors.accountNumber = 'bankAccount.error.accountNumber'; - } else if (values.accountNumber && values.accountNumber === routingNumber) { - errors.accountNumber = 'bankAccount.error.routingAndAccountNumberCannotBeSame'; - } - if (routingNumber && (!CONST.BANK_ACCOUNT.REGEX.SWIFT_BIC.test(routingNumber) || !ValidationUtils.isValidRoutingNumber(routingNumber))) { - errors.routingNumber = 'bankAccount.error.routingNumber'; - } + if ( + values.accountNumber && + !CONST.BANK_ACCOUNT.REGEX.US_ACCOUNT_NUMBER.test(values.accountNumber.trim()) && + !CONST.BANK_ACCOUNT.REGEX.MASKED_US_ACCOUNT_NUMBER.test(values.accountNumber.trim()) + ) { + errors.accountNumber = translate('bankAccount.error.accountNumber'); + } else if (values.accountNumber && values.accountNumber === routingNumber) { + errors.accountNumber = translate('bankAccount.error.routingAndAccountNumberCannotBeSame'); + } + if (routingNumber && (!CONST.BANK_ACCOUNT.REGEX.SWIFT_BIC.test(routingNumber) || !ValidationUtils.isValidRoutingNumber(routingNumber))) { + errors.routingNumber = translate('bankAccount.error.routingNumber'); + } - return errors; - }, []); + return errors; + }, + [translate], + ); const shouldDisableInputs = !!(reimbursementAccount?.achData?.bankAccountID ?? ''); diff --git a/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/AddressUBO.tsx b/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/AddressUBO.tsx index c49f26abf80c..284a27108a48 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/AddressUBO.tsx +++ b/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/AddressUBO.tsx @@ -47,11 +47,11 @@ function AddressUBO({reimbursementAccountDraft, onNext, isEditing, beneficialOwn const errors = ValidationUtils.getFieldRequiredErrors(values, stepFields); if (values[inputKeys.street] && !ValidationUtils.isValidAddress(values[inputKeys.street])) { - errors[inputKeys.street] = 'bankAccount.error.addressStreet'; + errors[inputKeys.street] = translate('bankAccount.error.addressStreet'); } if (values[inputKeys.zipCode] && !ValidationUtils.isValidZipCode(values[inputKeys.zipCode])) { - errors[inputKeys.zipCode] = 'bankAccount.error.zipCode'; + errors[inputKeys.zipCode] = translate('bankAccount.error.zipCode'); } return errors; diff --git a/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/SocialSecurityNumberUBO.tsx b/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/SocialSecurityNumberUBO.tsx index 7c0c5ac0c057..d7814816cdb9 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/SocialSecurityNumberUBO.tsx +++ b/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/SocialSecurityNumberUBO.tsx @@ -36,7 +36,7 @@ function SocialSecurityNumberUBO({reimbursementAccountDraft, onNext, isEditing, const validate = (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, stepFields); if (values[ssnLast4InputID] && !ValidationUtils.isValidSSNLastFour(values[ssnLast4InputID])) { - errors[ssnLast4InputID] = 'bankAccount.error.ssnLast4'; + errors[ssnLast4InputID] = translate('bankAccount.error.ssnLast4'); } return errors; }; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx index cca9e5619d59..8454a82969e7 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx @@ -32,27 +32,27 @@ const INPUT_KEYS = { const STEP_FIELDS = [COMPANY_BUSINESS_INFO_KEY.STREET, COMPANY_BUSINESS_INFO_KEY.CITY, COMPANY_BUSINESS_INFO_KEY.STATE, COMPANY_BUSINESS_INFO_KEY.ZIP_CODE]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); +function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusinessProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); - if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { - errors.addressStreet = 'bankAccount.error.addressStreet'; - } + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.addressCity && !ValidationUtils.isValidAddress(values.addressCity)) { - errors.addressCity = 'bankAccount.error.addressCity'; - } + if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { + errors.addressStreet = translate('bankAccount.error.addressStreet'); + } - if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { - errors.addressZipCode = 'bankAccount.error.zipCode'; - } + if (values.addressCity && !ValidationUtils.isValidAddress(values.addressCity)) { + errors.addressCity = translate('bankAccount.error.addressCity'); + } - return errors; -}; + if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { + errors.addressZipCode = translate('bankAccount.error.zipCode'); + } -function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusinessProps) { - const {translate} = useLocalize(); - const styles = useThemeStyles(); + return errors; + }; const defaultValues = { street: reimbursementAccount?.achData?.addressStreet ?? '', diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx index 377fbf9782ae..712f42578f36 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx @@ -26,16 +26,6 @@ type NameBusinessProps = NameBusinessOnyxProps & SubStepProps; const COMPANY_NAME_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_NAME; const STEP_FIELDS = [COMPANY_NAME_KEY]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.companyName && !ValidationUtils.isValidCompanyName(values.companyName)) { - errors.companyName = 'bankAccount.error.companyName'; - } - - return errors; -}; - function NameBusiness({reimbursementAccount, onNext, isEditing}: NameBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -45,6 +35,16 @@ function NameBusiness({reimbursementAccount, onNext, isEditing}: NameBusinessPro const shouldDisableCompanyName = !!(bankAccountID && defaultCompanyName && reimbursementAccount?.achData?.state !== 'SETUP'); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.companyName && !ValidationUtils.isValidCompanyName(values.companyName)) { + errors.companyName = translate('bankAccount.error.companyName'); + } + + return errors; + }; + const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx index 018922610080..b22424d194f9 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx @@ -26,21 +26,21 @@ type PhoneNumberBusinessProps = PhoneNumberBusinessOnyxProps & SubStepProps; const COMPANY_PHONE_NUMBER_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_PHONE; const STEP_FIELDS = [COMPANY_PHONE_NUMBER_KEY]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.companyPhone && !ValidationUtils.isValidUSPhone(values.companyPhone, true)) { - errors.companyPhone = 'bankAccount.error.phoneNumber'; - } - - return errors; -}; - function PhoneNumberBusiness({reimbursementAccount, onNext, isEditing}: PhoneNumberBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const defaultCompanyPhoneNumber = reimbursementAccount?.achData?.companyPhone ?? ''; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.companyPhone && !ValidationUtils.isValidUSPhone(values.companyPhone, true)) { + errors.companyPhone = translate('bankAccount.error.phoneNumber'); + } + + return errors; + }; + const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx index cabf0fc01576..6fba24b901e3 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx @@ -25,17 +25,6 @@ type TaxIdBusinessProps = TaxIdBusinessOnyxProps & SubStepProps; const COMPANY_TAX_ID_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_TAX_ID; const STEP_FIELDS = [COMPANY_TAX_ID_KEY]; - -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.companyTaxID && !ValidationUtils.isValidTaxID(values.companyTaxID)) { - errors.companyTaxID = 'bankAccount.error.taxID'; - } - - return errors; -}; - function TaxIdBusiness({reimbursementAccount, onNext, isEditing}: TaxIdBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -43,6 +32,16 @@ function TaxIdBusiness({reimbursementAccount, onNext, isEditing}: TaxIdBusinessP const bankAccountID = reimbursementAccount?.achData?.bankAccountID ?? 0; const shouldDisableCompanyTaxID = !!(bankAccountID && defaultCompanyTaxId && reimbursementAccount?.achData?.state !== 'SETUP'); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.companyTaxID && !ValidationUtils.isValidTaxID(values.companyTaxID)) { + errors.companyTaxID = translate('bankAccount.error.taxID'); + } + + return errors; + }; + const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx index e06c4d9d575e..7115e1a82158 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx @@ -34,16 +34,6 @@ type WebsiteBusinessProps = WebsiteBusinessOnyxProps & SubStepProps; const COMPANY_WEBSITE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_WEBSITE; const STEP_FIELDS = [COMPANY_WEBSITE_KEY]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.website && !ValidationUtils.isValidWebsite(values.website)) { - errors.website = 'bankAccount.error.website'; - } - - return errors; -}; - function WebsiteBusiness({reimbursementAccount, user, session, onNext, isEditing}: WebsiteBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -51,6 +41,16 @@ function WebsiteBusiness({reimbursementAccount, user, session, onNext, isEditing const defaultWebsiteExample = useMemo(() => getDefaultCompanyWebsite(session, user), [session, user]); const defaultCompanyWebsite = reimbursementAccount?.achData?.website ?? defaultWebsiteExample; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.website && !ValidationUtils.isValidWebsite(values.website)) { + errors.website = translate('bankAccount.error.website'); + } + + return errors; + }; + const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/ReimbursementAccount/ConnectBankAccount/components/BankAccountValidationForm.tsx b/src/pages/ReimbursementAccount/ConnectBankAccount/components/BankAccountValidationForm.tsx index a83e18d119c9..9bb4b4a56bfe 100644 --- a/src/pages/ReimbursementAccount/ConnectBankAccount/components/BankAccountValidationForm.tsx +++ b/src/pages/ReimbursementAccount/ConnectBankAccount/components/BankAccountValidationForm.tsx @@ -73,7 +73,7 @@ function BankAccountValidationForm({requiresTwoFactorAuth, reimbursementAccount, if (ValidationUtils.isRequiredFulfilled(filteredValue.toString())) { return; } - errors[key as keyof AmountValues] = 'common.error.invalidAmount'; + errors[key as keyof AmountValues] = translate('common.error.invalidAmount'); }); return errors; diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/Address.tsx b/src/pages/ReimbursementAccount/PersonalInfo/substeps/Address.tsx index a0ec8220ce3e..e75978b77298 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/Address.tsx +++ b/src/pages/ReimbursementAccount/PersonalInfo/substeps/Address.tsx @@ -34,20 +34,6 @@ const INPUT_KEYS = { const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.STREET, PERSONAL_INFO_STEP_KEY.CITY, PERSONAL_INFO_STEP_KEY.STATE, PERSONAL_INFO_STEP_KEY.ZIP_CODE]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.requestorAddressStreet && !ValidationUtils.isValidAddress(values.requestorAddressStreet)) { - errors.requestorAddressStreet = 'bankAccount.error.addressStreet'; - } - - if (values.requestorAddressZipCode && !ValidationUtils.isValidZipCode(values.requestorAddressZipCode)) { - errors.requestorAddressZipCode = 'bankAccount.error.zipCode'; - } - - return errors; -}; - function Address({reimbursementAccount, onNext, isEditing}: AddressProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -59,6 +45,20 @@ function Address({reimbursementAccount, onNext, isEditing}: AddressProps) { zipCode: reimbursementAccount?.achData?.[PERSONAL_INFO_STEP_KEY.ZIP_CODE] ?? '', }; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.requestorAddressStreet && !ValidationUtils.isValidAddress(values.requestorAddressStreet)) { + errors.requestorAddressStreet = translate('bankAccount.error.addressStreet'); + } + + if (values.requestorAddressZipCode && !ValidationUtils.isValidZipCode(values.requestorAddressZipCode)) { + errors.requestorAddressZipCode = translate('bankAccount.error.zipCode'); + } + + return errors; + }; + const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx b/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx index 1d225c1c32f2..79da5ea4c707 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx +++ b/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx @@ -27,19 +27,6 @@ type FullNameProps = FullNameOnyxProps & SubStepProps; const PERSONAL_INFO_STEP_KEY = INPUT_IDS.PERSONAL_INFO_STEP; const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.FIRST_NAME, PERSONAL_INFO_STEP_KEY.LAST_NAME]; - -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.firstName && !ValidationUtils.isValidLegalName(values.firstName)) { - errors.firstName = 'bankAccount.error.firstName'; - } - - if (values.lastName && !ValidationUtils.isValidLegalName(values.lastName)) { - errors.lastName = 'bankAccount.error.lastName'; - } - return errors; -}; - function FullName({reimbursementAccount, onNext, isEditing}: FullNameProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -49,6 +36,18 @@ function FullName({reimbursementAccount, onNext, isEditing}: FullNameProps) { lastName: reimbursementAccount?.achData?.[PERSONAL_INFO_STEP_KEY.LAST_NAME] ?? '', }; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + if (values.firstName && !ValidationUtils.isValidLegalName(values.firstName)) { + errors.firstName = translate('bankAccount.error.firstName'); + } + + if (values.lastName && !ValidationUtils.isValidLegalName(values.lastName)) { + errors.lastName = translate('bankAccount.error.lastName'); + } + return errors; + }; + const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx b/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx index e647fd768fb1..d33a0ac6243a 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx +++ b/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx @@ -28,21 +28,22 @@ type SocialSecurityNumberProps = SocialSecurityNumberOnyxProps & SubStepProps; const PERSONAL_INFO_STEP_KEY = INPUT_IDS.PERSONAL_INFO_STEP; const STEP_FIELDS = [PERSONAL_INFO_STEP_KEY.SSN_LAST_4]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.ssnLast4 && !ValidationUtils.isValidSSNLastFour(values.ssnLast4)) { - errors.ssnLast4 = 'bankAccount.error.ssnLast4'; - } - - return errors; -}; function SocialSecurityNumber({reimbursementAccount, onNext, isEditing}: SocialSecurityNumberProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const defaultSsnLast4 = reimbursementAccount?.achData?.[PERSONAL_INFO_STEP_KEY.SSN_LAST_4] ?? ''; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.ssnLast4 && !ValidationUtils.isValidSSNLastFour(values.ssnLast4)) { + errors.ssnLast4 = translate('bankAccount.error.ssnLast4'); + } + + return errors; + }; + const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/TeachersUnite/IntroSchoolPrincipalPage.tsx b/src/pages/TeachersUnite/IntroSchoolPrincipalPage.tsx index 6e8c3b340f4e..00bc9a1e73c9 100644 --- a/src/pages/TeachersUnite/IntroSchoolPrincipalPage.tsx +++ b/src/pages/TeachersUnite/IntroSchoolPrincipalPage.tsx @@ -50,27 +50,27 @@ function IntroSchoolPrincipalPage(props: IntroSchoolPrincipalPageProps) { const errors: FormInputErrors = {}; if (!values.firstName || !ValidationUtils.isValidPersonName(values.firstName)) { - ErrorUtils.addErrorMessage(errors, 'firstName', 'bankAccount.error.firstName'); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('bankAccount.error.firstName')); } if (!values.lastName || !ValidationUtils.isValidPersonName(values.lastName)) { - ErrorUtils.addErrorMessage(errors, 'lastName', 'bankAccount.error.lastName'); + ErrorUtils.addErrorMessage(errors, 'lastName', translate('bankAccount.error.lastName')); } if (!values.partnerUserID) { - ErrorUtils.addErrorMessage(errors, 'partnerUserID', 'teachersUnitePage.error.enterEmail'); + ErrorUtils.addErrorMessage(errors, 'partnerUserID', translate('teachersUnitePage.error.enterEmail')); } if (values.partnerUserID && props.loginList?.[values.partnerUserID.toLowerCase()]) { - ErrorUtils.addErrorMessage(errors, 'partnerUserID', 'teachersUnitePage.error.tryDifferentEmail'); + ErrorUtils.addErrorMessage(errors, 'partnerUserID', translate('teachersUnitePage.error.tryDifferentEmail')); } if (values.partnerUserID && !Str.isValidEmail(values.partnerUserID)) { - ErrorUtils.addErrorMessage(errors, 'partnerUserID', 'teachersUnitePage.error.enterValidEmail'); + ErrorUtils.addErrorMessage(errors, 'partnerUserID', translate('teachersUnitePage.error.enterValidEmail')); } if (values.partnerUserID && LoginUtils.isEmailPublicDomain(values.partnerUserID)) { - ErrorUtils.addErrorMessage(errors, 'partnerUserID', 'teachersUnitePage.error.tryDifferentEmail'); + ErrorUtils.addErrorMessage(errors, 'partnerUserID', translate('teachersUnitePage.error.tryDifferentEmail')); } return errors; }, - [props.loginList], + [props.loginList, translate], ); return ( diff --git a/src/pages/TeachersUnite/KnowATeacherPage.tsx b/src/pages/TeachersUnite/KnowATeacherPage.tsx index cb58009c40f0..54de95f81828 100644 --- a/src/pages/TeachersUnite/KnowATeacherPage.tsx +++ b/src/pages/TeachersUnite/KnowATeacherPage.tsx @@ -59,24 +59,24 @@ function KnowATeacherPage(props: KnowATeacherPageProps) { const validateIfNumber = LoginUtils.validateNumber(phoneLogin); if (!values.firstName || !ValidationUtils.isValidPersonName(values.firstName)) { - ErrorUtils.addErrorMessage(errors, 'firstName', 'bankAccount.error.firstName'); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('bankAccount.error.firstName')); } if (!values.lastName || !ValidationUtils.isValidPersonName(values.lastName)) { - ErrorUtils.addErrorMessage(errors, 'lastName', 'bankAccount.error.lastName'); + ErrorUtils.addErrorMessage(errors, 'lastName', translate('bankAccount.error.lastName')); } if (!values.partnerUserID) { - ErrorUtils.addErrorMessage(errors, 'partnerUserID', 'teachersUnitePage.error.enterPhoneEmail'); + ErrorUtils.addErrorMessage(errors, 'partnerUserID', translate('teachersUnitePage.error.enterPhoneEmail')); } if (values.partnerUserID && props.loginList?.[validateIfNumber || values.partnerUserID.toLowerCase()]) { - ErrorUtils.addErrorMessage(errors, 'partnerUserID', 'teachersUnitePage.error.tryDifferentEmail'); + ErrorUtils.addErrorMessage(errors, 'partnerUserID', translate('teachersUnitePage.error.tryDifferentEmail')); } if (values.partnerUserID && !(validateIfNumber || Str.isValidEmail(values.partnerUserID))) { - ErrorUtils.addErrorMessage(errors, 'partnerUserID', 'contacts.genericFailureMessages.invalidContactMethod'); + ErrorUtils.addErrorMessage(errors, 'partnerUserID', translate('contacts.genericFailureMessages.invalidContactMethod')); } return errors; }, - [props.loginList], + [props.loginList, translate], ); return ( diff --git a/src/pages/iou/HoldReasonPage.tsx b/src/pages/iou/HoldReasonPage.tsx index 18b290a81ea4..a17ed6df11d3 100644 --- a/src/pages/iou/HoldReasonPage.tsx +++ b/src/pages/iou/HoldReasonPage.tsx @@ -73,20 +73,20 @@ function HoldReasonPage({route}: HoldReasonPageProps) { const errors: FormInputErrors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.COMMENT]); if (!values.comment) { - errors.comment = 'common.error.fieldRequired'; + errors.comment = translate('common.error.fieldRequired'); } // We have extra isWorkspaceRequest condition since, for 1:1 requests, canEditMoneyRequest will rightly return false // as we do not allow requestee to edit fields like description and amount. // But, we still want the requestee to be able to put the request on hold if (!ReportUtils.canEditMoneyRequest(parentReportAction) && isWorkspaceRequest) { const formErrors = {}; - ErrorUtils.addErrorMessage(formErrors, 'reportModified', 'common.error.requestModified'); + ErrorUtils.addErrorMessage(formErrors, 'reportModified', translate('common.error.requestModified')); FormActions.setErrors(ONYXKEYS.FORMS.MONEY_REQUEST_HOLD_FORM, formErrors); } return errors; }, - [parentReportAction, isWorkspaceRequest], + [parentReportAction, isWorkspaceRequest, translate], ); useEffect(() => { diff --git a/src/pages/iou/request/step/IOURequestStepMerchant.tsx b/src/pages/iou/request/step/IOURequestStepMerchant.tsx index fc7d39b49089..bd5ec0eed4c3 100644 --- a/src/pages/iou/request/step/IOURequestStepMerchant.tsx +++ b/src/pages/iou/request/step/IOURequestStepMerchant.tsx @@ -73,12 +73,12 @@ function IOURequestStepMerchant({ const errors: FormInputErrors = {}; if (isMerchantRequired && !value.moneyRequestMerchant) { - errors.moneyRequestMerchant = 'common.error.fieldRequired'; + errors.moneyRequestMerchant = translate('common.error.fieldRequired'); } return errors; }, - [isMerchantRequired], + [isMerchantRequired, translate], ); const updateMerchant = (value: FormOnyxValues) => { diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx index 6c0eae98fb85..158cc8ceca85 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -90,13 +90,13 @@ function IOURequestStepWaypoint({ const errors = {}; const waypointValue = values[`waypoint${pageIndex}`] ?? ''; if (isOffline && waypointValue !== '' && !ValidationUtils.isValidAddress(waypointValue)) { - ErrorUtils.addErrorMessage(errors, `waypoint${pageIndex}`, 'bankAccount.error.address'); + ErrorUtils.addErrorMessage(errors, `waypoint${pageIndex}`, translate('bankAccount.error.address')); } // If the user is online, and they are trying to save a value without using the autocomplete, show an error message instructing them to use a selected address instead. // That enables us to save the address with coordinates when it is selected if (!isOffline && waypointValue !== '' && waypointAddress !== waypointValue) { - ErrorUtils.addErrorMessage(errors, `waypoint${pageIndex}`, 'distance.error.selectSuggestedAddress'); + ErrorUtils.addErrorMessage(errors, `waypoint${pageIndex}`, translate('distance.error.selectSuggestedAddress')); } return errors; diff --git a/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx index dbaf330803c1..d9f53faa62d0 100644 --- a/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx +++ b/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx @@ -60,7 +60,7 @@ function ExitSurveyReasonPage({draftReason}: ExitSurveyReasonPageOnyxProps) { validate={() => { const errors: Errors = {}; if (!reason) { - errors[INPUT_IDS.REASON] = 'common.error.fieldRequired'; + errors[INPUT_IDS.REASON] = translate('common.error.fieldRequired'); } return errors; }} diff --git a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx index 62183b0ebc26..64e8159334d9 100644 --- a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx +++ b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx @@ -110,7 +110,7 @@ function ExitSurveyResponsePage({draftResponse, route, navigation}: ExitSurveyRe validate={() => { const errors: Errors = {}; if (!draftResponse?.trim()) { - errors[INPUT_IDS.RESPONSE] = 'common.error.fieldRequired'; + errors[INPUT_IDS.RESPONSE] = translate('common.error.fieldRequired'); } return errors; }} diff --git a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx index 20e12f71664e..4366f8ff284d 100644 --- a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx +++ b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx @@ -57,15 +57,15 @@ function NewContactMethodPage({loginList, route}: NewContactMethodPageProps) { const errors = {}; if (!values.phoneOrEmail) { - ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', 'contacts.genericFailureMessages.contactMethodRequired'); + ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', translate('contacts.genericFailureMessages.contactMethodRequired')); } if (!!values.phoneOrEmail && !(validateIfnumber || Str.isValidEmail(values.phoneOrEmail))) { - ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', 'contacts.genericFailureMessages.invalidContactMethod'); + ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', translate('contacts.genericFailureMessages.invalidContactMethod')); } if (!!values.phoneOrEmail && loginList?.[validateIfnumber || values.phoneOrEmail.toLowerCase()]) { - ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', 'contacts.genericFailureMessages.enteredMethodIsAlreadySubmited'); + ErrorUtils.addErrorMessage(errors, 'phoneOrEmail', translate('contacts.genericFailureMessages.enteredMethodIsAlreadySubmited')); } return errors; diff --git a/src/pages/settings/Profile/DisplayNamePage.tsx b/src/pages/settings/Profile/DisplayNamePage.tsx index 830c06c9a254..e338fc16b0ee 100644 --- a/src/pages/settings/Profile/DisplayNamePage.tsx +++ b/src/pages/settings/Profile/DisplayNamePage.tsx @@ -47,22 +47,22 @@ function DisplayNamePage({isLoadingApp = true, currentUserPersonalDetails}: Disp // First we validate the first name field if (!ValidationUtils.isValidDisplayName(values.firstName)) { - ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.hasInvalidCharacter'); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('personalDetails.error.hasInvalidCharacter')); } else if (values.firstName.length > CONST.TITLE_CHARACTER_LIMIT) { ErrorUtils.addErrorMessage(errors, 'firstName', translate('common.error.characterLimitExceedCounter', {length: values.firstName.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } if (ValidationUtils.doesContainReservedWord(values.firstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.containsReservedWord'); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('personalDetails.error.containsReservedWord')); } // Then we validate the last name field if (!ValidationUtils.isValidDisplayName(values.lastName)) { - ErrorUtils.addErrorMessage(errors, 'lastName', 'personalDetails.error.hasInvalidCharacter'); + ErrorUtils.addErrorMessage(errors, 'lastName', translate('personalDetails.error.hasInvalidCharacter')); } else if (values.lastName.length > CONST.TITLE_CHARACTER_LIMIT) { ErrorUtils.addErrorMessage(errors, 'lastName', translate('common.error.characterLimitExceedCounter', {length: values.lastName.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } if (ValidationUtils.doesContainReservedWord(values.lastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'lastName', 'personalDetails.error.containsReservedWord'); + ErrorUtils.addErrorMessage(errors, 'lastName', translate('personalDetails.error.containsReservedWord')); } return errors; }; diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx index 83f8456f5fd3..c5e725450264 100644 --- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx @@ -46,9 +46,9 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP if (typeof values.legalFirstName === 'string') { if (!ValidationUtils.isValidLegalName(values.legalFirstName)) { - ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'privatePersonalDetails.error.hasInvalidCharacter'); + ErrorUtils.addErrorMessage(errors, 'legalFirstName', translate('privatePersonalDetails.error.hasInvalidCharacter')); } else if (!values.legalFirstName) { - errors.legalFirstName = 'common.error.fieldRequired'; + errors.legalFirstName = translate('common.error.fieldRequired'); } else if (values.legalFirstName.length > CONST.LEGAL_NAME.MAX_LENGTH) { ErrorUtils.addErrorMessage( errors, @@ -57,13 +57,13 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP ); } if (ValidationUtils.doesContainReservedWord(values.legalFirstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'personalDetails.error.containsReservedWord'); + ErrorUtils.addErrorMessage(errors, 'legalFirstName', translate('personalDetails.error.containsReservedWord')); } } if (typeof values.legalLastName === 'string') { if (!ValidationUtils.isValidLegalName(values.legalLastName)) { - ErrorUtils.addErrorMessage(errors, 'legalLastName', 'privatePersonalDetails.error.hasInvalidCharacter'); + ErrorUtils.addErrorMessage(errors, 'legalLastName', translate('privatePersonalDetails.error.hasInvalidCharacter')); } else if (!values.legalLastName) { errors.legalLastName = 'common.error.fieldRequired'; } else if (values.legalLastName.length > CONST.LEGAL_NAME.MAX_LENGTH) { @@ -74,7 +74,7 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP ); } if (ValidationUtils.doesContainReservedWord(values.legalLastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'legalLastName', 'personalDetails.error.containsReservedWord'); + ErrorUtils.addErrorMessage(errors, 'legalLastName', translate('personalDetails.error.containsReservedWord')); } } diff --git a/src/pages/settings/Report/RoomNamePage.tsx b/src/pages/settings/Report/RoomNamePage.tsx index 91451307aed7..67068182c8a5 100644 --- a/src/pages/settings/Report/RoomNamePage.tsx +++ b/src/pages/settings/Report/RoomNamePage.tsx @@ -53,16 +53,16 @@ function RoomNamePage({report, policy, reports}: RoomNamePageProps) { if (!values.roomName || values.roomName === CONST.POLICY.ROOM_PREFIX) { // We error if the user doesn't enter a room name or left blank - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.pleaseEnterRoomName'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.pleaseEnterRoomName')); } else if (!ValidationUtils.isValidRoomName(values.roomName)) { // We error if the room name has invalid characters - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomNameInvalidError'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomNameInvalidError')); } else if (ValidationUtils.isReservedRoomName(values.roomName)) { // Certain names are reserved for default rooms and should not be used for policy rooms. ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomNameReservedError', {reservedName: values.roomName})); } else if (ValidationUtils.isExistingRoomName(values.roomName, reports, report?.policyID ?? '')) { // The room name can't be set to one that already exists on the policy - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomAlreadyExistsError'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomAlreadyExistsError')); } else if (values.roomName.length > CONST.TITLE_CHARACTER_LIMIT) { ErrorUtils.addErrorMessage(errors, 'roomName', translate('common.error.characterLimitExceedCounter', {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 0fc0f5b7790a..d7a8087edb57 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -72,7 +72,7 @@ function CloseAccountPage({session}: CloseAccountPageProps) { const errors = ValidationUtils.getFieldRequiredErrors(values, ['phoneOrEmail']); if (values.phoneOrEmail && userEmailOrPhone && sanitizePhoneOrEmail(userEmailOrPhone) !== sanitizePhoneOrEmail(values.phoneOrEmail)) { - errors.phoneOrEmail = 'closeAccountPage.enterYourDefaultContactMethod'; + errors.phoneOrEmail = translate('closeAccountPage.enterYourDefaultContactMethod'); } return errors; }; diff --git a/src/pages/settings/Wallet/Card/GetPhysicalCardName.tsx b/src/pages/settings/Wallet/Card/GetPhysicalCardName.tsx index 1667aa8d36d3..deaa05350c7f 100644 --- a/src/pages/settings/Wallet/Card/GetPhysicalCardName.tsx +++ b/src/pages/settings/Wallet/Card/GetPhysicalCardName.tsx @@ -43,15 +43,15 @@ function GetPhysicalCardName({ const errors: OnValidateResult = {}; if (values?.legalFirstName && !ValidationUtils.isValidLegalName(values.legalFirstName)) { - errors.legalFirstName = 'privatePersonalDetails.error.hasInvalidCharacter'; + errors.legalFirstName = translate('privatePersonalDetails.error.hasInvalidCharacter'); } else if (!values?.legalFirstName) { - errors.legalFirstName = 'common.error.fieldRequired'; + errors.legalFirstName = translate('common.error.fieldRequired'); } if (values?.legalLastName && !ValidationUtils.isValidLegalName(values.legalLastName)) { - errors.legalLastName = 'privatePersonalDetails.error.hasInvalidCharacter'; + errors.legalLastName = translate('privatePersonalDetails.error.hasInvalidCharacter'); } else if (!values?.legalLastName) { - errors.legalLastName = 'common.error.fieldRequired'; + errors.legalLastName = translate('common.error.fieldRequired'); } return errors; diff --git a/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.tsx b/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.tsx index f709de4b51c3..56d5a29a3203 100644 --- a/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.tsx +++ b/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.tsx @@ -42,9 +42,9 @@ function GetPhysicalCardPhone({ const errors: OnValidateResult = {}; if (!LoginUtils.validateNumber(phoneNumberToValidate)) { - errors.phoneNumber = 'common.error.phoneNumber'; + errors.phoneNumber = translate('common.error.phoneNumber'); } else if (!phoneNumberToValidate) { - errors.phoneNumber = 'common.error.fieldRequired'; + errors.phoneNumber = translate('common.error.fieldRequired'); } return errors; diff --git a/src/pages/tasks/NewTaskDetailsPage.tsx b/src/pages/tasks/NewTaskDetailsPage.tsx index ae269b1dbc81..3824bebde1e9 100644 --- a/src/pages/tasks/NewTaskDetailsPage.tsx +++ b/src/pages/tasks/NewTaskDetailsPage.tsx @@ -56,7 +56,7 @@ function NewTaskDetailsPage({task}: NewTaskDetailsPageProps) { if (!values.taskTitle) { // We error if the user doesn't enter a task name - ErrorUtils.addErrorMessage(errors, 'taskTitle', 'newTaskPage.pleaseEnterTaskName'); + ErrorUtils.addErrorMessage(errors, 'taskTitle', translate('newTaskPage.pleaseEnterTaskName')); } else if (values.taskTitle.length > CONST.TITLE_CHARACTER_LIMIT) { ErrorUtils.addErrorMessage(errors, 'taskTitle', translate('common.error.characterLimitExceedCounter', {length: values.taskTitle.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } diff --git a/src/pages/tasks/NewTaskTitlePage.tsx b/src/pages/tasks/NewTaskTitlePage.tsx index 0ff6c178d24a..cdc9fc27596a 100644 --- a/src/pages/tasks/NewTaskTitlePage.tsx +++ b/src/pages/tasks/NewTaskTitlePage.tsx @@ -40,7 +40,7 @@ function NewTaskTitlePage({task}: NewTaskTitlePageProps) { if (!values.taskTitle) { // We error if the user doesn't enter a task name - ErrorUtils.addErrorMessage(errors, 'taskTitle', 'newTaskPage.pleaseEnterTaskName'); + ErrorUtils.addErrorMessage(errors, 'taskTitle', translate('newTaskPage.pleaseEnterTaskName')); } else if (values.taskTitle.length > CONST.TITLE_CHARACTER_LIMIT) { ErrorUtils.addErrorMessage(errors, 'taskTitle', translate('common.error.characterLimitExceedCounter', {length: values.taskTitle.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } diff --git a/src/pages/tasks/TaskTitlePage.tsx b/src/pages/tasks/TaskTitlePage.tsx index 70ced7a81072..e99b0b3da67a 100644 --- a/src/pages/tasks/TaskTitlePage.tsx +++ b/src/pages/tasks/TaskTitlePage.tsx @@ -34,7 +34,7 @@ function TaskTitlePage({report, currentUserPersonalDetails}: TaskTitlePageProps) const errors: FormInputErrors = {}; if (!title) { - ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, 'newTaskPage.pleaseEnterTaskName'); + ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, translate('newTaskPage.pleaseEnterTaskName')); } else if (title.length > CONST.TITLE_CHARACTER_LIMIT) { ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, translate('common.error.characterLimitExceedCounter', {length: title.length, limit: CONST.TITLE_CHARACTER_LIMIT})); } diff --git a/src/pages/workspace/WorkspaceInviteMessagePage.tsx b/src/pages/workspace/WorkspaceInviteMessagePage.tsx index ffc7299eb1f0..add00da9643a 100644 --- a/src/pages/workspace/WorkspaceInviteMessagePage.tsx +++ b/src/pages/workspace/WorkspaceInviteMessagePage.tsx @@ -125,7 +125,7 @@ function WorkspaceInviteMessagePage({ const validate = (): FormInputErrors => { const errorFields: FormInputErrors = {}; if (isEmptyObject(invitedEmailsToAccountIDsDraft)) { - errorFields.welcomeMessage = 'workspace.inviteMessage.inviteNoMembersError'; + errorFields.welcomeMessage = translate('workspace.inviteMessage.inviteNoMembersError'); } return errorFields; }; diff --git a/src/pages/workspace/WorkspaceNamePage.tsx b/src/pages/workspace/WorkspaceNamePage.tsx index 03d4e7107c1c..eee99a912d82 100644 --- a/src/pages/workspace/WorkspaceNamePage.tsx +++ b/src/pages/workspace/WorkspaceNamePage.tsx @@ -44,7 +44,7 @@ function WorkspaceNamePage({policy}: Props) { const name = values.name.trim(); if (!ValidationUtils.isRequiredFulfilled(name)) { - errors.name = 'workspace.editor.nameIsRequiredError'; + errors.name = translate('workspace.editor.nameIsRequiredError'); } else if ([...name].length > CONST.TITLE_CHARACTER_LIMIT) { // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 // code units. diff --git a/src/pages/workspace/categories/CategoryForm.tsx b/src/pages/workspace/categories/CategoryForm.tsx index ae1822515fa5..efe457729e36 100644 --- a/src/pages/workspace/categories/CategoryForm.tsx +++ b/src/pages/workspace/categories/CategoryForm.tsx @@ -40,11 +40,11 @@ function CategoryForm({onSubmit, policyCategories, categoryName, validateEdit}: const newCategoryName = values.categoryName.trim(); if (!ValidationUtils.isRequiredFulfilled(newCategoryName)) { - errors.categoryName = 'workspace.categories.categoryRequiredError'; + errors.categoryName = translate('workspace.categories.categoryRequiredError'); } else if (policyCategories?.[newCategoryName]) { - errors.categoryName = 'workspace.categories.existingCategoryError'; + errors.categoryName = translate('workspace.categories.existingCategoryError'); } else if (newCategoryName === CONST.INVALID_CATEGORY_NAME) { - errors.categoryName = 'workspace.categories.invalidCategoryName'; + errors.categoryName = translate('workspace.categories.invalidCategoryName'); } else if ([...newCategoryName].length > CONST.CATEGORY_NAME_LIMIT) { // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 code units. ErrorUtils.addErrorMessage( diff --git a/src/pages/workspace/categories/EditCategoryPage.tsx b/src/pages/workspace/categories/EditCategoryPage.tsx index 7b37375272d2..224233fff318 100644 --- a/src/pages/workspace/categories/EditCategoryPage.tsx +++ b/src/pages/workspace/categories/EditCategoryPage.tsx @@ -37,14 +37,14 @@ function EditCategoryPage({route, policyCategories}: EditCategoryPageProps) { const newCategoryName = values.categoryName.trim(); if (!newCategoryName) { - errors.categoryName = 'workspace.categories.categoryRequiredError'; + errors.categoryName = translate('workspace.categories.categoryRequiredError'); } else if (policyCategories?.[newCategoryName] && currentCategoryName !== newCategoryName) { - errors.categoryName = 'workspace.categories.existingCategoryError'; + errors.categoryName = translate('workspace.categories.existingCategoryError'); } return errors; }, - [policyCategories, currentCategoryName], + [policyCategories, currentCategoryName, translate], ); const editCategory = useCallback( diff --git a/src/pages/workspace/members/WorkspaceOwnerPaymentCardForm.tsx b/src/pages/workspace/members/WorkspaceOwnerPaymentCardForm.tsx index 1a2f32449c41..8684792be806 100644 --- a/src/pages/workspace/members/WorkspaceOwnerPaymentCardForm.tsx +++ b/src/pages/workspace/members/WorkspaceOwnerPaymentCardForm.tsx @@ -76,27 +76,27 @@ function WorkspaceOwnerPaymentCardForm({policy}: WorkspaceOwnerPaymentCardFormPr const errors = ValidationUtils.getFieldRequiredErrors(formValues, REQUIRED_FIELDS); if (formValues.nameOnCard && !ValidationUtils.isValidLegalName(formValues.nameOnCard)) { - errors.nameOnCard = 'addDebitCardPage.error.invalidName'; + errors.nameOnCard = translate('addDebitCardPage.error.invalidName'); } if (formValues.cardNumber && !ValidationUtils.isValidDebitCard(formValues.cardNumber.replace(/ /g, ''))) { - errors.cardNumber = 'addDebitCardPage.error.debitCardNumber'; + errors.cardNumber = translate('addDebitCardPage.error.debitCardNumber'); } if (formValues.expirationDate && !ValidationUtils.isValidExpirationDate(formValues.expirationDate)) { - errors.expirationDate = 'addDebitCardPage.error.expirationDate'; + errors.expirationDate = translate('addDebitCardPage.error.expirationDate'); } if (formValues.securityCode && !ValidationUtils.isValidSecurityCode(formValues.securityCode)) { - errors.securityCode = 'addDebitCardPage.error.securityCode'; + errors.securityCode = translate('addDebitCardPage.error.securityCode'); } if (formValues.addressStreet && !ValidationUtils.isValidAddress(formValues.addressStreet)) { - errors.addressStreet = 'addDebitCardPage.error.addressStreet'; + errors.addressStreet = translate('addDebitCardPage.error.addressStreet'); } if (formValues.addressZipCode && !ValidationUtils.isValidZipCode(formValues.addressZipCode)) { - errors.addressZipCode = 'addDebitCardPage.error.addressZipCode'; + errors.addressZipCode = translate('addDebitCardPage.error.addressZipCode'); } return errors; diff --git a/src/pages/workspace/tags/EditTagPage.tsx b/src/pages/workspace/tags/EditTagPage.tsx index a6b3b5dd6657..f2269bbb8c53 100644 --- a/src/pages/workspace/tags/EditTagPage.tsx +++ b/src/pages/workspace/tags/EditTagPage.tsx @@ -43,14 +43,14 @@ function EditTagPage({route, policyTags}: EditTagPageProps) { const tagName = values.tagName.trim(); const {tags} = PolicyUtils.getTagList(policyTags, route.params.orderWeight); if (!ValidationUtils.isRequiredFulfilled(tagName)) { - errors.tagName = 'workspace.tags.tagRequiredError'; + errors.tagName = translate('workspace.tags.tagRequiredError'); } else if (tags?.[tagName] && currentTagName !== tagName) { - errors.tagName = 'workspace.tags.existingTagError'; + errors.tagName = translate('workspace.tags.existingTagError'); } return errors; }, - [route.params.orderWeight, currentTagName, policyTags], + [policyTags, route.params.orderWeight, currentTagName, translate], ); const editTag = useCallback( diff --git a/src/pages/workspace/tags/WorkspaceCreateTagPage.tsx b/src/pages/workspace/tags/WorkspaceCreateTagPage.tsx index 408bf4eb2366..1214507480ae 100644 --- a/src/pages/workspace/tags/WorkspaceCreateTagPage.tsx +++ b/src/pages/workspace/tags/WorkspaceCreateTagPage.tsx @@ -44,9 +44,9 @@ function CreateTagPage({route, policyTags}: CreateTagPageProps) { const {tags} = PolicyUtils.getTagList(policyTags, 0); if (!ValidationUtils.isRequiredFulfilled(tagName)) { - errors.tagName = 'workspace.tags.tagRequiredError'; + errors.tagName = translate('workspace.tags.tagRequiredError'); } else if (tags?.[tagName]) { - errors.tagName = 'workspace.tags.existingTagError'; + errors.tagName = translate('workspace.tags.existingTagError'); } else if ([...tagName].length > CONST.TAG_NAME_LIMIT) { // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 code units. ErrorUtils.addErrorMessage(errors, 'tagName', translate('common.error.characterLimitExceedCounter', {length: [...tagName].length, limit: CONST.TAG_NAME_LIMIT})); diff --git a/src/pages/workspace/tags/WorkspaceEditTagsPage.tsx b/src/pages/workspace/tags/WorkspaceEditTagsPage.tsx index f0b3ada7f2e5..91883cc989b0 100644 --- a/src/pages/workspace/tags/WorkspaceEditTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceEditTagsPage.tsx @@ -30,20 +30,20 @@ type WorkspaceEditTagsPageOnyxProps = { type WorkspaceEditTagsPageProps = WorkspaceEditTagsPageOnyxProps & StackScreenProps; -const validateTagName = (values: FormOnyxValues) => { - const errors: FormInputErrors = {}; - if (!values[INPUT_IDS.POLICY_TAGS_NAME] && values[INPUT_IDS.POLICY_TAGS_NAME].trim() === '') { - errors[INPUT_IDS.POLICY_TAGS_NAME] = 'common.error.fieldRequired'; - } - return errors; -}; - function WorkspaceEditTagsPage({route, policyTags}: WorkspaceEditTagsPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const taglistName = useMemo(() => PolicyUtils.getTagListName(policyTags, route.params.orderWeight), [policyTags, route.params.orderWeight]); const {inputCallbackRef} = useAutoFocusInput(); + const validateTagName = (values: FormOnyxValues) => { + const errors: FormInputErrors = {}; + if (!values[INPUT_IDS.POLICY_TAGS_NAME] && values[INPUT_IDS.POLICY_TAGS_NAME].trim() === '') { + errors[INPUT_IDS.POLICY_TAGS_NAME] = translate('common.error.fieldRequired'); + } + return errors; + }; + const updateTaglistName = useCallback( (values: FormOnyxValues) => { if (values[INPUT_IDS.POLICY_TAGS_NAME] !== taglistName) { diff --git a/src/pages/workspace/taxes/WorkspaceTaxesSettingsCustomTaxName.tsx b/src/pages/workspace/taxes/WorkspaceTaxesSettingsCustomTaxName.tsx index dbade9a82aa2..f24a388011ab 100644 --- a/src/pages/workspace/taxes/WorkspaceTaxesSettingsCustomTaxName.tsx +++ b/src/pages/workspace/taxes/WorkspaceTaxesSettingsCustomTaxName.tsx @@ -36,16 +36,19 @@ function WorkspaceTaxesSettingsCustomTaxName({ const {translate} = useLocalize(); const {inputCallbackRef} = useAutoFocusInput(); - const validate = useCallback((values: FormOnyxValues) => { - const errors: FormInputErrors = {}; - const customTaxName = values[INPUT_IDS.NAME]; + const validate = useCallback( + (values: FormOnyxValues) => { + const errors: FormInputErrors = {}; + const customTaxName = values[INPUT_IDS.NAME]; - if (!ValidationUtils.isRequiredFulfilled(customTaxName)) { - errors.name = 'workspace.taxes.error.customNameRequired'; - } + if (!ValidationUtils.isRequiredFulfilled(customTaxName)) { + errors.name = translate('workspace.taxes.error.customNameRequired'); + } - return errors; - }, []); + return errors; + }, + [translate], + ); const submit = ({name}: WorkspaceTaxCustomName) => { setPolicyCustomTaxName(policyID, name); From ba60fea1b49ab0f2eafd8cdb95c5b9de16e1a921 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 5 Jun 2024 01:34:42 +0700 Subject: [PATCH 13/24] clean code --- src/components/AddressForm.tsx | 8 ++--- .../MoneyRequestConfirmationList.tsx | 25 +++++++++------ src/components/PDFView/PDFPasswordForm.tsx | 2 +- src/libs/OptionsListUtils.ts | 2 +- .../PersonalInfo/substeps/AddressStep.tsx | 25 ++++++++------- .../PersonalInfo/substeps/DateOfBirthStep.tsx | 25 ++++++++------- .../PersonalInfo/substeps/FullNameStep.tsx | 25 ++++++++------- .../PersonalInfo/substeps/PhoneNumberStep.tsx | 19 +++++++----- .../substeps/SocialSecurityNumberStep.tsx | 19 +++++++----- .../substeps/ConfirmationBusiness.tsx | 19 +++++++----- .../substeps/IncorporationDateBusiness.tsx | 23 ++++++++------ .../BusinessInfo/substeps/NameBusiness.tsx | 19 +++++++----- .../substeps/PhoneNumberBusiness.tsx | 19 +++++++----- .../BusinessInfo/substeps/TaxIdBusiness.tsx | 19 +++++++----- .../BusinessInfo/substeps/WebsiteBusiness.tsx | 20 ++++++------ .../substeps/ConfirmAgreements.tsx | 31 ++++++++++--------- .../PersonalInfo/substeps/Address.tsx | 25 ++++++++------- .../PersonalInfo/substeps/DateOfBirth.tsx | 25 ++++++++------- .../PersonalInfo/substeps/FullName.tsx | 25 ++++++++------- .../substeps/SocialSecurityNumber.tsx | 19 +++++++----- .../Profile/Contacts/NewContactMethodPage.tsx | 2 +- .../BaseTwoFactorAuthForm.tsx | 8 +++-- .../workspace/tags/WorkspaceEditTagsPage.tsx | 17 +++++----- 23 files changed, 239 insertions(+), 182 deletions(-) diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index 8601c3fa1e9f..006550664f93 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -116,18 +116,18 @@ function AddressForm({ const countrySpecificZipRegex = countryRegexDetails?.regex; const countryZipFormat = countryRegexDetails?.samples ?? ''; - ErrorUtils.addErrorMessage(errors, 'firstName', 'bankAccount.error.firstName'); + ErrorUtils.addErrorMessage(errors, 'firstName', translate('bankAccount.error.firstName')); if (countrySpecificZipRegex) { if (!countrySpecificZipRegex.test(values.zipPostCode?.trim().toUpperCase())) { if (ValidationUtils.isRequiredFulfilled(values.zipPostCode?.trim())) { - errors.zipPostCode = ['privatePersonalDetails.error.incorrectZipFormat', countryZipFormat]; + errors.zipPostCode = [translate('privatePersonalDetails.error.incorrectZipFormat', countryZipFormat)]; } else { - errors.zipPostCode = 'common.error.fieldRequired'; + errors.zipPostCode = translate('common.error.fieldRequired'); } } } else if (!CONST.GENERIC_ZIP_CODE_REGEX.test(values?.zipPostCode?.trim()?.toUpperCase() ?? '')) { - errors.zipPostCode = 'privatePersonalDetails.error.incorrectZipFormat'; + errors.zipPostCode = translate('privatePersonalDetails.error.incorrectZipFormat'); } return errors; diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 9f01d63cc439..a073b021207d 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -35,6 +35,7 @@ import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; import * as IOU from '@userActions/IOU'; import type {IOUAction, IOUType} from '@src/CONST'; import CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Route} from '@src/ROUTES'; @@ -322,7 +323,7 @@ function MoneyRequestConfirmationList({ const previousTransactionCurrency = usePrevious(transaction?.currency); const isFocused = useIsFocused(); - const [formError, debouncedFormError, setFormError] = useDebouncedState(''); + const [formError, debouncedFormError, setFormError] = useDebouncedState(''); const [didConfirm, setDidConfirm] = useState(false); const [didConfirmSplit, setDidConfirmSplit] = useState(false); @@ -349,8 +350,12 @@ function MoneyRequestConfirmationList({ const isCategoryRequired = !!policy?.requiresCategory; useEffect(() => { + if (shouldDisplayFieldError && hasSmartScanFailed) { + setFormError('iou.receiptScanningFailed'); + return; + } if (shouldDisplayFieldError && didConfirmSplit) { - setFormError(translate('iou.error.genericSmartscanFailureMessage')); + setFormError('iou.error.genericSmartscanFailureMessage'); return; } @@ -435,7 +440,7 @@ function MoneyRequestConfirmationList({ const shares: number[] = Object.values(splitSharesMap).map((splitShare) => splitShare?.amount ?? 0); const sumOfShares = shares?.reduce((prev, current): number => prev + current, 0); if (sumOfShares !== iouAmount) { - setFormError(translate('iou.error.invalidSplit')); + setFormError('iou.error.invalidSplit'); return; } @@ -445,7 +450,7 @@ function MoneyRequestConfirmationList({ // A split must have at least two participants with amounts bigger than 0 if (participantsWithAmount.length === 1) { - setFormError(translate('iou.error.invalidSplitParticipants')); + setFormError('iou.error.invalidSplitParticipants'); return; } @@ -702,11 +707,11 @@ function MoneyRequestConfirmationList({ return; } if (!isEditingSplitBill && isMerchantRequired && (isMerchantEmpty || (shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction ?? null)))) { - setFormError(translate('iou.error.invalidMerchant')); + setFormError('iou.error.invalidMerchant'); return; } if (iouCategory.length > CONST.API_TRANSACTION_CATEGORY_MAX_LENGTH) { - setFormError(translate('iou.error.invalidCategoryLength')); + setFormError('iou.error.invalidCategoryLength'); return; } if (iouType !== CONST.IOU.TYPE.PAY) { @@ -751,7 +756,6 @@ function MoneyRequestConfirmationList({ formError, iouType, setFormError, - translate, onSendMoney, iouCurrencyCode, isDistanceRequest, @@ -808,7 +812,7 @@ function MoneyRequestConfirmationList({ )} @@ -825,10 +829,11 @@ function MoneyRequestConfirmationList({ policyID, splitOrRequestOptions, formError, - debouncedFormError, - shouldShowReadOnlySplits, styles.ph1, styles.mb2, + shouldShowReadOnlySplits, + debouncedFormError, + translate, ]); // An intermediate structure that helps us classify the fields as "primary" and "supplementary". diff --git a/src/components/PDFView/PDFPasswordForm.tsx b/src/components/PDFView/PDFPasswordForm.tsx index e212d79b27d6..4b6491addbef 100644 --- a/src/components/PDFView/PDFPasswordForm.tsx +++ b/src/components/PDFView/PDFPasswordForm.tsx @@ -90,7 +90,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid = false, shouldShowLoadin return true; } if (!password) { - setValidationErrorText('attachmentView.passwordRequired'); + setValidationErrorText(translate('attachmentView.passwordRequired')); } return false; }; diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 7cc0b49a88d9..6f475af474ec 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -539,7 +539,7 @@ function getAllReportErrors(report: OnyxEntry, reportActions: OnyxEntry< } } else if ((ReportUtils.isIOUReport(report) || ReportUtils.isExpenseReport(report)) && report?.ownerAccountID === currentUserAccountID) { if (ReportUtils.shouldShowRBRForMissingSmartscanFields(report?.reportID ?? '') && !ReportUtils.isSettled(report?.reportID)) { - reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericSmartscanFailureMessage'); + reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericSmartscanFailureMessage'); } } else if (ReportUtils.hasSmartscanError(Object.values(reportActions ?? {}))) { reportActionErrors.smartscan = ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericSmartscanFailureMessage'); diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/AddressStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/AddressStep.tsx index 22347f1b3bff..56703fb4b5c4 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/AddressStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/AddressStep.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -38,19 +38,22 @@ function AddressStep({onNext, isEditing}: SubStepProps) { zipCode: walletAdditionalDetails?.[PERSONAL_INFO_STEP_KEY.ZIP_CODE] ?? '', }; - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { - errors.addressStreet = translate('bankAccount.error.addressStreet'); - } + if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { + errors.addressStreet = translate('bankAccount.error.addressStreet'); + } - if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { - errors.addressZipCode = translate('bankAccount.error.zipCode'); - } + if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { + errors.addressZipCode = translate('bankAccount.error.zipCode'); + } - return errors; - }; + return errors; + }, + [translate], + ); const handleSubmit = useWalletAdditionalDetailsStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx index 7c4f5f43f2a1..d476fdcc5c86 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx @@ -1,5 +1,5 @@ import {subYears} from 'date-fns'; -import React from 'react'; +import React, {useCallback} from 'react'; import {useOnyx} from 'react-native-onyx'; import DatePicker from '@components/DatePicker'; import FormProvider from '@components/Form/FormProvider'; @@ -26,19 +26,22 @@ function DateOfBirthStep({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.dob) { - if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { - errors.dob = translate('bankAccount.error.dob'); - } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { - errors.dob = translate('bankAccount.error.age'); + if (values.dob) { + if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.dob'); + } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.age'); + } } - } - return errors; - }; + return errors; + }, + [translate], + ); const [walletAdditionalDetails] = useOnyx(ONYXKEYS.WALLET_ADDITIONAL_DETAILS); diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/FullNameStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/FullNameStep.tsx index 89240720f533..b40fb2202943 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/FullNameStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/FullNameStep.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -30,17 +30,20 @@ function FullNameStep({onNext, isEditing}: SubStepProps) { lastName: walletAdditionalDetails?.[PERSONAL_INFO_STEP_KEY.LAST_NAME] ?? '', }; - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.legalFirstName && !ValidationUtils.isValidLegalName(values.legalFirstName)) { - errors.legalFirstName = translate('bankAccount.error.firstName'); - } + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + if (values.legalFirstName && !ValidationUtils.isValidLegalName(values.legalFirstName)) { + errors.legalFirstName = translate('bankAccount.error.firstName'); + } - if (values.legalLastName && !ValidationUtils.isValidLegalName(values.legalLastName)) { - errors.legalLastName = translate('bankAccount.error.lastName'); - } - return errors; - }; + if (values.legalLastName && !ValidationUtils.isValidLegalName(values.legalLastName)) { + errors.legalLastName = translate('bankAccount.error.lastName'); + } + return errors; + }, + [translate], + ); const handleSubmit = useWalletAdditionalDetailsStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/PhoneNumberStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/PhoneNumberStep.tsx index a5326504a1c6..60bfa431ca78 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/PhoneNumberStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/PhoneNumberStep.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -27,14 +27,17 @@ function PhoneNumberStep({onNext, isEditing}: SubStepProps) { const defaultPhoneNumber = walletAdditionalDetails?.[PERSONAL_INFO_STEP_KEY.PHONE_NUMBER] ?? ''; - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.phoneNumber && !ValidationUtils.isValidUSPhone(values.phoneNumber, true)) { - errors.phoneNumber = translate('bankAccount.error.phoneNumber'); - } - return errors; - }; + if (values.phoneNumber && !ValidationUtils.isValidUSPhone(values.phoneNumber, true)) { + errors.phoneNumber = translate('bankAccount.error.phoneNumber'); + } + return errors; + }, + [translate], + ); const handleSubmit = useWalletAdditionalDetailsStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/SocialSecurityNumberStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/SocialSecurityNumberStep.tsx index cb3f2fa263f7..bdaa3fe98f67 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/SocialSecurityNumberStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/SocialSecurityNumberStep.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -23,15 +23,18 @@ function SocialSecurityNumberStep({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.ssn && !ValidationUtils.isValidSSNLastFour(values.ssn)) { - errors.ssn = translate('bankAccount.error.ssnLast4'); - } + if (values.ssn && !ValidationUtils.isValidSSNLastFour(values.ssn)) { + errors.ssn = translate('bankAccount.error.ssnLast4'); + } - return errors; - }; + return errors; + }, + [translate], + ); const [walletAdditionalDetails] = useOnyx(ONYXKEYS.WALLET_ADDITIONAL_DETAILS); diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx index fa660c98d8bc..fb6a246ce84e 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx @@ -1,5 +1,5 @@ import type {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; -import React, {useMemo} from 'react'; +import React, {useCallback, useMemo} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import CheckboxWithLabel from '@components/CheckboxWithLabel'; @@ -52,15 +52,18 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, const {translate} = useLocalize(); const styles = useThemeStyles(); - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]); - if (!values.hasNoConnectionToCannabis) { - errors.hasNoConnectionToCannabis = translate('bankAccount.error.restrictedBusiness'); - } + if (!values.hasNoConnectionToCannabis) { + errors.hasNoConnectionToCannabis = translate('bankAccount.error.restrictedBusiness'); + } - return errors; - }; + return errors; + }, + [translate], + ); const values = useMemo(() => getSubstepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx index 58a1feb710c2..274e087cc415 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import DatePicker from '@components/DatePicker'; @@ -33,17 +33,20 @@ function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDr const {translate} = useLocalize(); const styles = useThemeStyles(); - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { - errors.incorporationDate = translate('common.error.dateInvalid'); - } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) { - errors.incorporationDate = translate('bankAccount.error.incorporationDateFuture'); - } + if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { + errors.incorporationDate = translate('common.error.dateInvalid'); + } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) { + errors.incorporationDate = translate('bankAccount.error.incorporationDateFuture'); + } - return errors; - }; + return errors; + }, + [translate], + ); const defaultCompanyIncorporationDate = reimbursementAccount?.achData?.incorporationDate ?? reimbursementAccountDraft?.incorporationDate ?? ''; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx index 712f42578f36..d7be083df3a0 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -35,15 +35,18 @@ function NameBusiness({reimbursementAccount, onNext, isEditing}: NameBusinessPro const shouldDisableCompanyName = !!(bankAccountID && defaultCompanyName && reimbursementAccount?.achData?.state !== 'SETUP'); - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.companyName && !ValidationUtils.isValidCompanyName(values.companyName)) { - errors.companyName = translate('bankAccount.error.companyName'); - } + if (values.companyName && !ValidationUtils.isValidCompanyName(values.companyName)) { + errors.companyName = translate('bankAccount.error.companyName'); + } - return errors; - }; + return errors; + }, + [translate], + ); const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx index b22424d194f9..e0c83737b6f8 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -31,15 +31,18 @@ function PhoneNumberBusiness({reimbursementAccount, onNext, isEditing}: PhoneNum const styles = useThemeStyles(); const defaultCompanyPhoneNumber = reimbursementAccount?.achData?.companyPhone ?? ''; - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.companyPhone && !ValidationUtils.isValidUSPhone(values.companyPhone, true)) { - errors.companyPhone = translate('bankAccount.error.phoneNumber'); - } + if (values.companyPhone && !ValidationUtils.isValidUSPhone(values.companyPhone, true)) { + errors.companyPhone = translate('bankAccount.error.phoneNumber'); + } - return errors; - }; + return errors; + }, + [translate], + ); const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx index 6fba24b901e3..8e3ec6d5ec6e 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -32,15 +32,18 @@ function TaxIdBusiness({reimbursementAccount, onNext, isEditing}: TaxIdBusinessP const bankAccountID = reimbursementAccount?.achData?.bankAccountID ?? 0; const shouldDisableCompanyTaxID = !!(bankAccountID && defaultCompanyTaxId && reimbursementAccount?.achData?.state !== 'SETUP'); - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.companyTaxID && !ValidationUtils.isValidTaxID(values.companyTaxID)) { - errors.companyTaxID = translate('bankAccount.error.taxID'); - } + if (values.companyTaxID && !ValidationUtils.isValidTaxID(values.companyTaxID)) { + errors.companyTaxID = translate('bankAccount.error.taxID'); + } - return errors; - }; + return errors; + }, + [translate], + ); const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx index 7115e1a82158..541e47f6cb10 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useMemo} from 'react'; +import React, {useCallback, useEffect, useMemo} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -41,16 +41,18 @@ function WebsiteBusiness({reimbursementAccount, user, session, onNext, isEditing const defaultWebsiteExample = useMemo(() => getDefaultCompanyWebsite(session, user), [session, user]); const defaultCompanyWebsite = reimbursementAccount?.achData?.website ?? defaultWebsiteExample; - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.website && !ValidationUtils.isValidWebsite(values.website)) { - errors.website = translate('bankAccount.error.website'); - } - - return errors; - }; + if (values.website && !ValidationUtils.isValidWebsite(values.website)) { + errors.website = translate('bankAccount.error.website'); + } + return errors; + }, + [translate], + ); const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, onNext, diff --git a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx index 1e2f004b9c8d..71d7a80ab58b 100644 --- a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx +++ b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import CheckboxWithLabel from '@components/CheckboxWithLabel'; @@ -58,23 +58,26 @@ function ConfirmAgreements({onNext, reimbursementAccount}: ConfirmAgreementsProp certifyTrueInformation: reimbursementAccount?.achData?.certifyTrueInformation ?? false, acceptTermsAndConditions: reimbursementAccount?.achData?.acceptTermsAndConditions ?? false, }; - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (!ValidationUtils.isRequiredFulfilled(values.acceptTermsAndConditions)) { - errors.acceptTermsAndConditions = translate('common.error.acceptTerms'); - } + if (!ValidationUtils.isRequiredFulfilled(values.acceptTermsAndConditions)) { + errors.acceptTermsAndConditions = translate('common.error.acceptTerms'); + } - if (!ValidationUtils.isRequiredFulfilled(values.certifyTrueInformation)) { - errors.certifyTrueInformation = translate('completeVerificationStep.certifyTrueAndAccurateError'); - } + if (!ValidationUtils.isRequiredFulfilled(values.certifyTrueInformation)) { + errors.certifyTrueInformation = translate('completeVerificationStep.certifyTrueAndAccurateError'); + } - if (!ValidationUtils.isRequiredFulfilled(values.isAuthorizedToUseBankAccount)) { - errors.isAuthorizedToUseBankAccount = translate('completeVerificationStep.isAuthorizedToUseBankAccountError'); - } + if (!ValidationUtils.isRequiredFulfilled(values.isAuthorizedToUseBankAccount)) { + errors.isAuthorizedToUseBankAccount = translate('completeVerificationStep.isAuthorizedToUseBankAccountError'); + } - return errors; - }; + return errors; + }, + [translate], + ); return ( ): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.requestorAddressStreet && !ValidationUtils.isValidAddress(values.requestorAddressStreet)) { - errors.requestorAddressStreet = translate('bankAccount.error.addressStreet'); - } + if (values.requestorAddressStreet && !ValidationUtils.isValidAddress(values.requestorAddressStreet)) { + errors.requestorAddressStreet = translate('bankAccount.error.addressStreet'); + } - if (values.requestorAddressZipCode && !ValidationUtils.isValidZipCode(values.requestorAddressZipCode)) { - errors.requestorAddressZipCode = translate('bankAccount.error.zipCode'); - } + if (values.requestorAddressZipCode && !ValidationUtils.isValidZipCode(values.requestorAddressZipCode)) { + errors.requestorAddressZipCode = translate('bankAccount.error.zipCode'); + } - return errors; - }; + return errors; + }, + [translate], + ); const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx b/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx index c47139af8a90..6fe391bbe957 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx +++ b/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx @@ -1,5 +1,5 @@ import {subYears} from 'date-fns'; -import React from 'react'; +import React, {useCallback} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import DatePicker from '@components/DatePicker'; @@ -36,19 +36,22 @@ function DateOfBirth({reimbursementAccount, reimbursementAccountDraft, onNext, i const {translate} = useLocalize(); const styles = useThemeStyles(); - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.dob) { - if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { - errors.dob = translate('bankAccount.error.dob'); - } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { - errors.dob = translate('bankAccount.error.age'); + if (values.dob) { + if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.dob'); + } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.age'); + } } - } - return errors; - }; + return errors; + }, + [translate], + ); const dobDefaultValue = reimbursementAccount?.achData?.[PERSONAL_INFO_DOB_KEY] ?? reimbursementAccountDraft?.[PERSONAL_INFO_DOB_KEY] ?? ''; diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx b/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx index 79da5ea4c707..bab467707fd4 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx +++ b/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -36,17 +36,20 @@ function FullName({reimbursementAccount, onNext, isEditing}: FullNameProps) { lastName: reimbursementAccount?.achData?.[PERSONAL_INFO_STEP_KEY.LAST_NAME] ?? '', }; - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.firstName && !ValidationUtils.isValidLegalName(values.firstName)) { - errors.firstName = translate('bankAccount.error.firstName'); - } + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + if (values.firstName && !ValidationUtils.isValidLegalName(values.firstName)) { + errors.firstName = translate('bankAccount.error.firstName'); + } - if (values.lastName && !ValidationUtils.isValidLegalName(values.lastName)) { - errors.lastName = translate('bankAccount.error.lastName'); - } - return errors; - }; + if (values.lastName && !ValidationUtils.isValidLegalName(values.lastName)) { + errors.lastName = translate('bankAccount.error.lastName'); + } + return errors; + }, + [translate], + ); const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx b/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx index d33a0ac6243a..390880fa65f2 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx +++ b/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useCallback} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -34,15 +34,18 @@ function SocialSecurityNumber({reimbursementAccount, onNext, isEditing}: SocialS const defaultSsnLast4 = reimbursementAccount?.achData?.[PERSONAL_INFO_STEP_KEY.SSN_LAST_4] ?? ''; - const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.ssnLast4 && !ValidationUtils.isValidSSNLastFour(values.ssnLast4)) { - errors.ssnLast4 = translate('bankAccount.error.ssnLast4'); - } + if (values.ssnLast4 && !ValidationUtils.isValidSSNLastFour(values.ssnLast4)) { + errors.ssnLast4 = translate('bankAccount.error.ssnLast4'); + } - return errors; - }; + return errors; + }, + [translate], + ); const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: STEP_FIELDS, diff --git a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx index 4366f8ff284d..72358e909446 100644 --- a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx +++ b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx @@ -74,7 +74,7 @@ function NewContactMethodPage({loginList, route}: NewContactMethodPageProps) { // the loginList gets updated, causing this function to run again. // https://github.com/Expensify/App/issues/20610 // eslint-disable-next-line react-hooks/exhaustive-deps - [], + [translate], ); const onBackButtonPress = useCallback(() => { diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.tsx b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.tsx index 33484c2aee35..cf226655ce32 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.tsx @@ -3,6 +3,7 @@ import type {ForwardedRef, RefAttributes} from 'react'; import {withOnyx} from 'react-native-onyx'; import type {AutoCompleteVariant, MagicCodeInputHandle} from '@components/MagicCodeInput'; import MagicCodeInput from '@components/MagicCodeInput'; +import useLocalize from '@hooks/useLocalize'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; import * as Session from '@userActions/Session'; @@ -14,6 +15,7 @@ type BaseTwoFactorAuthFormProps = BaseTwoFactorAuthFormOnyxProps & { }; function BaseTwoFactorAuthForm({account, autoComplete}: BaseTwoFactorAuthFormProps, ref: ForwardedRef) { + const {translate} = useLocalize(); const [formError, setFormError] = useState<{twoFactorAuthCode?: string}>({}); const [twoFactorAuthCode, setTwoFactorAuthCode] = useState(''); const inputRef = useRef(null); @@ -41,18 +43,18 @@ function BaseTwoFactorAuthForm({account, autoComplete}: BaseTwoFactorAuthFormPro inputRef.current.blur(); } if (!twoFactorAuthCode.trim()) { - setFormError({twoFactorAuthCode: 'twoFactorAuthForm.error.pleaseFillTwoFactorAuth'}); + setFormError({twoFactorAuthCode: translate('twoFactorAuthForm.error.pleaseFillTwoFactorAuth')}); return; } if (!ValidationUtils.isValidTwoFactorCode(twoFactorAuthCode)) { - setFormError({twoFactorAuthCode: 'twoFactorAuthForm.error.incorrect2fa'}); + setFormError({twoFactorAuthCode: translate('twoFactorAuthForm.error.incorrect2fa')}); return; } setFormError({}); Session.validateTwoFactorAuth(twoFactorAuthCode); - }, [twoFactorAuthCode]); + }, [twoFactorAuthCode, translate]); useImperativeHandle(ref, () => ({ validateAndSubmitForm() { diff --git a/src/pages/workspace/tags/WorkspaceEditTagsPage.tsx b/src/pages/workspace/tags/WorkspaceEditTagsPage.tsx index 91883cc989b0..feae955b10fb 100644 --- a/src/pages/workspace/tags/WorkspaceEditTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceEditTagsPage.tsx @@ -36,13 +36,16 @@ function WorkspaceEditTagsPage({route, policyTags}: WorkspaceEditTagsPageProps) const taglistName = useMemo(() => PolicyUtils.getTagListName(policyTags, route.params.orderWeight), [policyTags, route.params.orderWeight]); const {inputCallbackRef} = useAutoFocusInput(); - const validateTagName = (values: FormOnyxValues) => { - const errors: FormInputErrors = {}; - if (!values[INPUT_IDS.POLICY_TAGS_NAME] && values[INPUT_IDS.POLICY_TAGS_NAME].trim() === '') { - errors[INPUT_IDS.POLICY_TAGS_NAME] = translate('common.error.fieldRequired'); - } - return errors; - }; + const validateTagName = useCallback( + (values: FormOnyxValues) => { + const errors: FormInputErrors = {}; + if (!values[INPUT_IDS.POLICY_TAGS_NAME] && values[INPUT_IDS.POLICY_TAGS_NAME].trim() === '') { + errors[INPUT_IDS.POLICY_TAGS_NAME] = translate('common.error.fieldRequired'); + } + return errors; + }, + [translate], + ); const updateTaglistName = useCallback( (values: FormOnyxValues) => { From 6f6b5aaa5f28db500df7bd843f1d9a447baeb442 Mon Sep 17 00:00:00 2001 From: nkdengineer <161821005+nkdengineer@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:26:09 +0700 Subject: [PATCH 14/24] Update src/components/MoneyRequestConfirmationList.tsx Co-authored-by: Fedi Rajhi --- src/components/MoneyRequestConfirmationList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 7a95f9d1b9a4..a75a16fcbc0d 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -813,7 +813,7 @@ function MoneyRequestConfirmationList({ )} From c8bb635e96daecb17f5b7aa7308aa39fec0c6875 Mon Sep 17 00:00:00 2001 From: nkdengineer <161821005+nkdengineer@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:27:39 +0700 Subject: [PATCH 15/24] Update src/components/AddressForm.tsx Co-authored-by: Fedi Rajhi --- src/components/AddressForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index 006550664f93..b428db2fc9dd 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -121,7 +121,7 @@ function AddressForm({ if (countrySpecificZipRegex) { if (!countrySpecificZipRegex.test(values.zipPostCode?.trim().toUpperCase())) { if (ValidationUtils.isRequiredFulfilled(values.zipPostCode?.trim())) { - errors.zipPostCode = [translate('privatePersonalDetails.error.incorrectZipFormat', countryZipFormat)]; + errors.zipPostCode = translate('privatePersonalDetails.error.incorrectZipFormat', countryZipFormat); } else { errors.zipPostCode = translate('common.error.fieldRequired'); } From 041629763a4c4c6a7bceccf6dba6ab570180b7b8 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 6 Jun 2024 15:59:42 +0700 Subject: [PATCH 16/24] remove func translateIfPhraseKey and clean code --- .../MoneyRequestConfirmationList.tsx | 4 --- src/libs/ErrorUtils.ts | 8 +++-- src/libs/Localize/index.ts | 29 +------------------ .../BusinessInfo/substeps/AddressBusiness.tsx | 6 ++-- .../ValidateCodeForm/BaseValidateCodeForm.tsx | 2 +- .../settings/Wallet/ExpensifyCardPage.tsx | 2 +- src/pages/workspace/WorkspaceNewRoomPage.tsx | 2 +- 7 files changed, 13 insertions(+), 40 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index a75a16fcbc0d..5b494fdcd4c2 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -351,10 +351,6 @@ function MoneyRequestConfirmationList({ const isCategoryRequired = !!policy?.requiresCategory; useEffect(() => { - if (shouldDisplayFieldError && hasSmartScanFailed) { - setFormError('iou.receiptScanningFailed'); - return; - } if (shouldDisplayFieldError && didConfirmSplit) { setFormError('iou.error.genericSmartscanFailureMessage'); return; diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index 8d0752660dd3..be917d8f32ad 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -37,13 +37,17 @@ function getAuthenticateErrorMessage(response: Response): keyof TranslationFlatO } /** - * Method used to get an error object with microsecond as the key. - * @param error - error key or message to be saved + * Creates an error object with a timestamp (in microseconds) as the key and the translated error message as the value. + * @param error - The translation key for the error message. */ function getMicroSecondOnyxErrorWithTranslationKey(error: TranslationPaths, errorKey?: number): Errors { return {[errorKey ?? DateUtils.getMicroseconds()]: Localize.translateLocal(error)}; } +/** + * Creates an error object with a timestamp (in microseconds) as the key and the error message as the value. + * @param error - The error message. + */ function getMicroSecondOnyxErrorWithMessage(error: string, errorKey?: number): Errors { return {[errorKey ?? DateUtils.getMicroseconds()]: error}; } diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index 8c13e1648d88..306831bebb55 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -9,7 +9,6 @@ import translations from '@src/languages/translations'; import type {TranslationFlatObject, TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Locale} from '@src/types/onyx'; -import type {ReceiptError} from '@src/types/onyx/Transaction'; import LocaleListener from './LocaleListener'; import BaseLocaleListener from './LocaleListener/BaseLocaleListener'; @@ -177,32 +176,6 @@ function translateLocal(phrase: TKey, ...variable type MaybePhraseKey = string | null | [string, Record & {isTranslated?: boolean}] | []; -/** - * Return translated string for given error. - */ -function translateIfPhraseKey(message: MaybePhraseKey): string; -function translateIfPhraseKey(message: ReceiptError): ReceiptError; -function translateIfPhraseKey(message: MaybePhraseKey | ReceiptError): string | ReceiptError; -function translateIfPhraseKey(message: MaybePhraseKey | ReceiptError): string | ReceiptError { - if (!message || (Array.isArray(message) && message.length === 0)) { - return ''; - } - - try { - // check if error message has a variable parameter - const [phrase, variables] = Array.isArray(message) ? message : [message]; - - // This condition checks if the error is already translated. For example, if there are multiple errors per input, we handle translation in ErrorUtils.addErrorMessage due to the inability to concatenate error keys. - if (variables?.isTranslated) { - return phrase; - } - - return translateLocal(phrase as TranslationPaths, variables as never); - } catch (error) { - return Array.isArray(message) ? message[0] : message; - } -} - function getPreferredListFormat(): Intl.ListFormat { if (!CONJUNCTION_LIST_FORMATS_FOR_LOCALES) { init(); @@ -254,5 +227,5 @@ function getDevicePreferredLocale(): Locale { return RNLocalize.findBestAvailableLanguage([CONST.LOCALES.EN, CONST.LOCALES.ES])?.languageTag ?? CONST.LOCALES.DEFAULT; } -export {translate, translateLocal, translateIfPhraseKey, formatList, formatMessageElementList, getDevicePreferredLocale}; +export {translate, translateLocal, formatList, formatMessageElementList, getDevicePreferredLocale}; export type {PhraseParameters, Phrase, MaybePhraseKey}; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx index 8454a82969e7..66cca41bd58c 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React,{useCallback} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -36,7 +36,7 @@ function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusin const {translate} = useLocalize(); const styles = useThemeStyles(); - const validate = (values: FormOnyxValues): FormInputErrors => { + const validate = useCallback((values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { @@ -52,7 +52,7 @@ function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusin } return errors; - }; + }, [translate]) const defaultValues = { street: reimbursementAccount?.achData?.addressStreet ?? '', diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.tsx index fc4ec0220b41..313a5a066496 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -206,7 +206,7 @@ function BaseValidateCodeForm({account = {}, contactMethod, hasMagicCodeBeenSent type="success" style={[styles.mt6, styles.flex0]} // eslint-disable-next-line @typescript-eslint/naming-convention - messages={{0: 'resendValidationForm.linkHasBeenResent'}} + messages={{0: translate('resendValidationForm.linkHasBeenResent')}} /> )} diff --git a/src/pages/settings/Wallet/ExpensifyCardPage.tsx b/src/pages/settings/Wallet/ExpensifyCardPage.tsx index 49686e19852c..fe41a250ea9b 100644 --- a/src/pages/settings/Wallet/ExpensifyCardPage.tsx +++ b/src/pages/settings/Wallet/ExpensifyCardPage.tsx @@ -173,7 +173,7 @@ function ExpensifyCardPage({ )} diff --git a/src/pages/workspace/WorkspaceNewRoomPage.tsx b/src/pages/workspace/WorkspaceNewRoomPage.tsx index 3693b7164025..8e11acf3f055 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.tsx +++ b/src/pages/workspace/WorkspaceNewRoomPage.tsx @@ -193,7 +193,7 @@ function WorkspaceNewRoomPage({policies, reports, formState, session, activePoli } if (!values.policyID) { - errors.policyID = 'newRoomPage.pleaseSelectWorkspace'; + errors.policyID = translate('newRoomPage.pleaseSelectWorkspace'); } return errors; From 727b30afd6795a12778d967d7ceba7cbca363f92 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 6 Jun 2024 16:16:09 +0700 Subject: [PATCH 17/24] fix lint --- .../BusinessInfo/substeps/AddressBusiness.tsx | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx index 66cca41bd58c..bd9524626a14 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx @@ -1,4 +1,4 @@ -import React,{useCallback} from 'react'; +import React, {useCallback} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; @@ -36,23 +36,26 @@ function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusin const {translate} = useLocalize(); const styles = useThemeStyles(); - const validate = useCallback((values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { - errors.addressStreet = translate('bankAccount.error.addressStreet'); - } + if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { + errors.addressStreet = translate('bankAccount.error.addressStreet'); + } - if (values.addressCity && !ValidationUtils.isValidAddress(values.addressCity)) { - errors.addressCity = translate('bankAccount.error.addressCity'); - } + if (values.addressCity && !ValidationUtils.isValidAddress(values.addressCity)) { + errors.addressCity = translate('bankAccount.error.addressCity'); + } - if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { - errors.addressZipCode = translate('bankAccount.error.zipCode'); - } + if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { + errors.addressZipCode = translate('bankAccount.error.zipCode'); + } - return errors; - }, [translate]) + return errors; + }, + [translate], + ); const defaultValues = { street: reimbursementAccount?.achData?.addressStreet ?? '', From 927288fc7ef9eb777b89e49efd38bbbd6ada7e18 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 7 Jun 2024 17:18:34 +0700 Subject: [PATCH 18/24] fix typecheck --- src/libs/actions/Policy/Member.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts index 14cebee27da1..ba32967e972e 100644 --- a/src/libs/actions/Policy/Member.ts +++ b/src/libs/actions/Policy/Member.ts @@ -617,7 +617,7 @@ function inviteMemberToWorkspace(policyID: string, inviterEmail: string) { { onyxMethod: Onyx.METHOD.MERGE, key: memberJoinKey, - value: {...failureMembersState, errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericEditFailureMessage')}, + value: {...failureMembersState, errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.common.genericEditFailureMessage')}, }, ]; From 506ac9a782413a16c6c5ef94fd9784d6ce724730 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 10 Jun 2024 16:41:16 +0700 Subject: [PATCH 19/24] fix ts error --- src/libs/actions/Policy/Member.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts index ba32967e972e..a92332bc9be1 100644 --- a/src/libs/actions/Policy/Member.ts +++ b/src/libs/actions/Policy/Member.ts @@ -617,7 +617,7 @@ function inviteMemberToWorkspace(policyID: string, inviterEmail: string) { { onyxMethod: Onyx.METHOD.MERGE, key: memberJoinKey, - value: {...failureMembersState, errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.common.genericEditFailureMessage')}, + value: {...failureMembersState, errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage')}, }, ]; From 15e9eba77a9d4df7d669390eb0f68af6aa130868 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 10 Jun 2024 16:52:48 +0700 Subject: [PATCH 20/24] fix lint --- src/types/onyx/OnyxCommon.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types/onyx/OnyxCommon.ts b/src/types/onyx/OnyxCommon.ts index c1a2ba81e7b4..ee60b6dbf1fd 100644 --- a/src/types/onyx/OnyxCommon.ts +++ b/src/types/onyx/OnyxCommon.ts @@ -23,6 +23,7 @@ type OnyxValueWithOfflineFeedback = keyof TO /** Mapping of form fields with errors */ type ErrorFields = Record; +/** Mapping of form fields with error translation keys and variables */ type Errors = Record; /** From d90a9df272fad3d446fb117a1e18ef452ea3af86 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 12 Jun 2024 16:05:22 +0700 Subject: [PATCH 21/24] fix: add missing translation --- src/libs/PolicyDistanceRatesUtils.ts | 2 +- src/libs/SidebarUtils.ts | 3 ++- src/pages/ReimbursementAccount/AddressFormFields.tsx | 2 +- src/pages/iou/request/step/IOURequestStepWaypoint.tsx | 2 +- src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx | 2 +- src/pages/settings/Subscription/SubscriptionSize/utils.ts | 3 ++- src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx | 2 +- 7 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libs/PolicyDistanceRatesUtils.ts b/src/libs/PolicyDistanceRatesUtils.ts index 132d8a6682c6..7e2c0bb83320 100644 --- a/src/libs/PolicyDistanceRatesUtils.ts +++ b/src/libs/PolicyDistanceRatesUtils.ts @@ -31,7 +31,7 @@ function validateTaxClaimableValue(values: FormOnyxValues, r const errors: FormInputErrors = {}; if (rate.rate && Number(values.taxClaimableValue) > rate.rate / 100) { - errors.taxClaimableValue = 'workspace.taxes.error.updateTaxClaimableFailureMessage'; + errors.taxClaimableValue = Localize.translateLocal('workspace.taxes.error.updateTaxClaimableFailureMessage'); } return errors; } diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index 119bbc3ba12a..43ca3b2b2f13 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -98,7 +98,8 @@ function getOrderedReportIDs( const isHidden = report.notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN; const isFocused = report.reportID === currentReportId; const allReportErrors = OptionsListUtils.getAllReportErrors(report, reportActions) ?? {}; - const hasErrorsOtherThanFailedReceipt = doesReportHaveViolations || Object.values(allReportErrors).some((error) => error?.[0] !== 'report.genericSmartscanFailureMessage'); + const hasErrorsOtherThanFailedReceipt = + doesReportHaveViolations || Object.values(allReportErrors).some((error) => error?.[0] !== Localize.translateLocal('iou.error.genericSmartscanFailureMessage')); const isSystemChat = ReportUtils.isSystemChat(report); const shouldOverrideHidden = hasErrorsOtherThanFailedReceipt || isFocused || isSystemChat || report.isPinned; if (isHidden && !shouldOverrideHidden) { diff --git a/src/pages/ReimbursementAccount/AddressFormFields.tsx b/src/pages/ReimbursementAccount/AddressFormFields.tsx index c586c71f3d47..a863d3cc5952 100644 --- a/src/pages/ReimbursementAccount/AddressFormFields.tsx +++ b/src/pages/ReimbursementAccount/AddressFormFields.tsx @@ -80,7 +80,7 @@ function AddressFormFields({shouldSaveDraft = false, defaultValues, values, erro value={values?.state as State} defaultValue={defaultValues?.state} onInputChange={(value) => onFieldChange?.({state: value})} - errorText={errors?.state ? 'bankAccount.error.addressState' : ''} + errorText={errors?.state ? translate('bankAccount.error.addressState') : ''} /> { textInput.current = e as unknown as TextInput; }} - hint={!isOffline ? 'distance.error.selectSuggestedAddress' : ''} + hint={!isOffline ? translate('distance.error.selectSuggestedAddress') : ''} containerStyles={[styles.mt4]} label={translate('distance.address')} defaultValue={waypointAddress} diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx index c5e725450264..99e9c910cbdf 100644 --- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx @@ -65,7 +65,7 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP if (!ValidationUtils.isValidLegalName(values.legalLastName)) { ErrorUtils.addErrorMessage(errors, 'legalLastName', translate('privatePersonalDetails.error.hasInvalidCharacter')); } else if (!values.legalLastName) { - errors.legalLastName = 'common.error.fieldRequired'; + errors.legalLastName = translate('common.error.fieldRequired'); } else if (values.legalLastName.length > CONST.LEGAL_NAME.MAX_LENGTH) { ErrorUtils.addErrorMessage( errors, diff --git a/src/pages/settings/Subscription/SubscriptionSize/utils.ts b/src/pages/settings/Subscription/SubscriptionSize/utils.ts index 4b0395d6cab2..30e9a685540d 100644 --- a/src/pages/settings/Subscription/SubscriptionSize/utils.ts +++ b/src/pages/settings/Subscription/SubscriptionSize/utils.ts @@ -1,5 +1,6 @@ import {addMonths, format, startOfMonth} from 'date-fns'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; +import * as Localize from '@libs/Localize'; import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import type ONYXKEYS from '@src/ONYXKEYS'; @@ -8,7 +9,7 @@ import INPUT_IDS from '@src/types/form/SubscriptionSizeForm'; const validate = (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.SUBSCRIPTION_SIZE]); if (values[INPUT_IDS.SUBSCRIPTION_SIZE] && !ValidationUtils.isValidSubscriptionSize(values[INPUT_IDS.SUBSCRIPTION_SIZE])) { - errors.subscriptionSize = 'subscription.subscriptionSize.error.size'; + errors.subscriptionSize = Localize.translateLocal('subscription.subscriptionSize.error.size'); } return errors; diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx index 7aaa5a03576b..523c89874f9c 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -303,7 +303,7 @@ function BaseValidateCodeForm({account, credentials, session, autoComplete, isUs onChangeText={(text) => onTextInput(text, 'recoveryCode')} maxLength={CONST.FORM_CHARACTER_LIMIT} label={translate('recoveryCodeForm.recoveryCode')} - errorText={formError?.recoveryCode ?? ''} + errorText={formError?.recoveryCode ? translate(formError?.recoveryCode) : ''} hasError={hasError} onSubmitEditing={validateAndSubmitForm} autoFocus From 174d97572ac836b0bec7c1bf1be2e33d396c8160 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 13 Jun 2024 10:20:28 +0700 Subject: [PATCH 22/24] fix type --- src/libs/ErrorUtils.ts | 2 +- src/libs/ReportActionsUtils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index 0a3b5704c4a6..cf852e533a20 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -70,7 +70,7 @@ type OnyxDataWithErrors = { errors?: Errors | null; }; -function getLatestErrorMessage(onyxData: TOnyxData | null): string { +function getLatestErrorMessage(onyxData: OnyxEntry | null): string { const errors = onyxData?.errors ?? {}; if (Object.keys(errors).length === 0) { diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index ec5c8d7c316d..2bb56c8f0e59 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -641,7 +641,7 @@ function replaceBaseURLInPolicyChangeLogAction(reportAction: ReportAction): Repo } function getLastVisibleAction(reportID: string, actionsToMerge: OnyxCollection | OnyxCollectionInputValue = {}): OnyxEntry { - const reportActions = Object.values(fastMerge(allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? {}, actionsToMerge ?? {}, true)) ; + const reportActions = Object.values(fastMerge(allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? {}, actionsToMerge ?? {}, true)); const visibleReportActions = Object.values(reportActions ?? {}).filter((action): action is ReportAction => shouldReportActionBeVisibleAsLastAction(action)); const sortedReportActions = getSortedReportActions(visibleReportActions, true); if (sortedReportActions.length === 0) { From b6b85d2cf2d89258e709b22d56b20ca6f97fdc8b Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 13 Jun 2024 22:51:09 +0700 Subject: [PATCH 23/24] fix lint --- src/libs/actions/Policy/Tag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index a6377a7d9a7d..82d5fbcf2dea 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -668,7 +668,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn required: policyTag.required, pendingFields: {required: null}, errorFields: { - required: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + required: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.tags.genericFailureMessage'), }, }, }, From 7603cb4016f93a82d6d257a17586e5fb09d6d716 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 14 Jun 2024 17:15:03 +0700 Subject: [PATCH 24/24] remove type MaybePhraseKey --- src/libs/Localize/index.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index 306831bebb55..c9eef3170245 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -174,8 +174,6 @@ function translateLocal(phrase: TKey, ...variable return translate(BaseLocaleListener.getPreferredLocale(), phrase, ...variables); } -type MaybePhraseKey = string | null | [string, Record & {isTranslated?: boolean}] | []; - function getPreferredListFormat(): Intl.ListFormat { if (!CONJUNCTION_LIST_FORMATS_FOR_LOCALES) { init(); @@ -228,4 +226,4 @@ function getDevicePreferredLocale(): Locale { } export {translate, translateLocal, formatList, formatMessageElementList, getDevicePreferredLocale}; -export type {PhraseParameters, Phrase, MaybePhraseKey}; +export type {PhraseParameters, Phrase};