diff --git a/src/components/CurrencyListContextProvider/default.ts b/src/components/CurrencyListContextProvider/default.ts index 5405f78b5285..ad111ce10a58 100644 --- a/src/components/CurrencyListContextProvider/default.ts +++ b/src/components/CurrencyListContextProvider/default.ts @@ -10,6 +10,7 @@ const defaultCurrencyListActionsContextValue: CurrencyListActionsContextType = { getCurrencySymbol: () => undefined, getCurrencyDecimals: () => 2, convertToDisplayString: () => '', + convertToDisplayStringWithoutCurrency: () => '', }; export {defaultCurrencyListStateContextValue, defaultCurrencyListActionsContextValue}; diff --git a/src/components/CurrencyListContextProvider/index.tsx b/src/components/CurrencyListContextProvider/index.tsx index 085617becbd4..ae0924d2c393 100644 --- a/src/components/CurrencyListContextProvider/index.tsx +++ b/src/components/CurrencyListContextProvider/index.tsx @@ -2,7 +2,7 @@ import React, {createContext, useCallback, useContext, useMemo} from 'react'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import {convertToFrontendAmountAsInteger} from '@libs/CurrencyUtils'; -import {format} from '@libs/NumberFormatUtils'; +import {format, formatToParts} from '@libs/NumberFormatUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {CurrencyList} from '@src/types/onyx'; @@ -54,6 +54,32 @@ function CurrencyListContextProvider({children}: React.PropsWithChildren) { [getCurrencyDecimals, preferredLocale], ); + const convertToDisplayStringWithoutCurrency = useCallback( + (amountInCents: number, currencyCode: string | undefined): string => { + const decimals = getCurrencyDecimals(currencyCode); + const convertedAmount = convertToFrontendAmountAsInteger(amountInCents, decimals); + let currencyWithFallback = currencyCode; + if (!currencyCode) { + currencyWithFallback = CONST.CURRENCY.USD; + } + return formatToParts(preferredLocale, convertedAmount, { + style: 'currency', + currency: currencyWithFallback, + + // We are forcing the number of decimals because we override the default number of decimals in the backend for some currencies + // See: https://github.com/Expensify/PHP-Libs/pull/834 + minimumFractionDigits: decimals, + // For currencies that have decimal places > 2, floor to 2 instead as we don't support more than 2 decimal places. + maximumFractionDigits: 2, + }) + .filter((x) => x.type !== 'currency') + .filter((x) => x.type !== 'literal' || x.value.trim().length !== 0) + .map((x) => x.value) + .join(''); + }, + [getCurrencyDecimals, preferredLocale], + ); + const stateValue = useMemo( () => ({ currencyList, @@ -66,8 +92,9 @@ function CurrencyListContextProvider({children}: React.PropsWithChildren) { getCurrencySymbol, getCurrencyDecimals, convertToDisplayString, + convertToDisplayStringWithoutCurrency, }), - [getCurrencySymbol, getCurrencyDecimals, convertToDisplayString], + [getCurrencySymbol, getCurrencyDecimals, convertToDisplayString, convertToDisplayStringWithoutCurrency], ); return ( diff --git a/src/components/CurrencyListContextProvider/types.ts b/src/components/CurrencyListContextProvider/types.ts index de152eb74dab..575c74f017f2 100644 --- a/src/components/CurrencyListContextProvider/types.ts +++ b/src/components/CurrencyListContextProvider/types.ts @@ -14,6 +14,9 @@ type CurrencyListActionsContextType = { /** Function to convert amount in cents to display string based on the currency and locale */ convertToDisplayString: (amount: number | undefined, currencyCode: string | undefined) => string; + + /** Function to convert amount in cents to display string without currency symbol */ + convertToDisplayStringWithoutCurrency: (amount: number, currencyCode: string | undefined) => string; }; export type {CurrencyListStateContextType, CurrencyListActionsContextType}; diff --git a/src/components/MoneyRequestConfirmationList/hooks/useSplitParticipants.tsx b/src/components/MoneyRequestConfirmationList/hooks/useSplitParticipants.tsx index acfb7ebd3090..3279fef0bc97 100644 --- a/src/components/MoneyRequestConfirmationList/hooks/useSplitParticipants.tsx +++ b/src/components/MoneyRequestConfirmationList/hooks/useSplitParticipants.tsx @@ -8,7 +8,7 @@ import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {resetSplitShares, setIndividualShare} from '@libs/actions/IOU/Split'; -import {convertToBackendAmount, convertToDisplayStringWithoutCurrency} from '@libs/CurrencyUtils'; +import {convertToBackendAmount} from '@libs/CurrencyUtils'; import {calculateAmount} from '@libs/IOUUtils'; import {getIOUConfirmationOptionsFromPayeePersonalDetail} from '@libs/OptionsListUtils'; import CONST from '@src/CONST'; @@ -54,7 +54,7 @@ type UseSplitParticipantsParams = { function useSplitParticipants({isTypeSplit, shouldShowReadOnlySplits, payeePersonalDetails, selectedParticipants, transaction, iouAmount, iouCurrencyCode}: UseSplitParticipantsParams) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const {convertToDisplayString, getCurrencySymbol} = useCurrencyListActions(); + const {convertToDisplayString, convertToDisplayStringWithoutCurrency, getCurrencySymbol} = useCurrencyListActions(); const transactionID = transaction?.transactionID; const onSplitShareChange = (accountID: number, value: number) => { diff --git a/src/components/PerDiemEReceipt.tsx b/src/components/PerDiemEReceipt.tsx index c5f685e2f53d..b78868086810 100644 --- a/src/components/PerDiemEReceipt.tsx +++ b/src/components/PerDiemEReceipt.tsx @@ -6,7 +6,7 @@ import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import {convertAmountToDisplayString, convertToDisplayStringWithoutCurrency} from '@libs/CurrencyUtils'; +import {convertAmountToDisplayString} from '@libs/CurrencyUtils'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import {getTransactionDetails} from '@libs/ReportUtils'; import variables from '@styles/variables'; @@ -53,7 +53,7 @@ function PerDiemEReceipt({transactionID}: PerDiemEReceiptProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); - const {getCurrencySymbol} = useCurrencyListActions(); + const {getCurrencySymbol, convertToDisplayStringWithoutCurrency} = useCurrencyListActions(); const icons = useMemoizedLazyExpensifyIcons(['ExpensifyWordmark']); const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(transactionID)}`); diff --git a/src/components/Search/SearchPageHeader/useSearchFiltersBar.tsx b/src/components/Search/SearchPageHeader/useSearchFiltersBar.tsx index 01227e6d2fb9..5d34bc00eb25 100644 --- a/src/components/Search/SearchPageHeader/useSearchFiltersBar.tsx +++ b/src/components/Search/SearchPageHeader/useSearchFiltersBar.tsx @@ -18,6 +18,7 @@ import UserSelectPopup from '@components/Search/FilterDropdowns/UserSelectPopup' import WorkspaceSelectPopup from '@components/Search/FilterDropdowns/WorkspaceSelectPopup'; import {useSearchStateContext} from '@components/Search/SearchContext'; import type {ReportFieldKey, SearchAmountFilterKeys, SearchDateFilterKeys, SearchFilterKey, SearchQueryJSON} from '@components/Search/types'; +import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; @@ -154,6 +155,7 @@ function useSearchFiltersBar(queryJSON: SearchQueryJSON): UseSearchFiltersBarRes const type = queryJSON.type; const styles = useThemeStyles(); const {translate, localeCompare} = useLocalize(); + const {convertToDisplayStringWithoutCurrency} = useCurrencyListActions(); const {isOffline} = useNetwork(); const {shouldShowFiltersBarLoading, currentSearchResults} = useSearchStateContext(); @@ -191,202 +193,210 @@ function useSearchFiltersBar(queryJSON: SearchQueryJSON): UseSearchFiltersBarRes }); }; - const filters = mapFiltersFormToLabelValueList(searchAdvancedFiltersForm, queryJSON.policyID, SKIPPED_FILTERS, translate, localeCompare, (filterKey) => { - const groupConfig = FILTER_GROUP_MAP[filterKey]; - if (groupConfig) { - if (isAmountFilterKey(groupConfig.syntax)) { - return makeAmountFilterItem(groupConfig.syntax, translate(groupConfig.label), searchAdvancedFiltersForm, updateFilterForm); + const filters = mapFiltersFormToLabelValueList( + searchAdvancedFiltersForm, + queryJSON.policyID, + SKIPPED_FILTERS, + translate, + localeCompare, + convertToDisplayStringWithoutCurrency, + (filterKey) => { + const groupConfig = FILTER_GROUP_MAP[filterKey]; + if (groupConfig) { + if (isAmountFilterKey(groupConfig.syntax)) { + return makeAmountFilterItem(groupConfig.syntax, translate(groupConfig.label), searchAdvancedFiltersForm, updateFilterForm); + } + return makeDateFilterItem(groupConfig.syntax, groupConfig.label, searchAdvancedFiltersForm, updateFilterForm); } - return makeDateFilterItem(groupConfig.syntax, groupConfig.label, searchAdvancedFiltersForm, updateFilterForm); - } - - if (filterKey.startsWith(CONST.SEARCH.REPORT_FIELD.GLOBAL_PREFIX)) { - return { - PopoverComponent: ({closeOverlay, setPopoverWidth}) => ( - - ), - sentryLabel: getFilterSentryLabel(filterKey), - }; - } - const label = FILTER_LABEL_MAP[filterKey]; - if (!label) { - return {PopoverComponent: () => null}; - } - - switch (filterKey) { - case FILTER_KEYS.IN: - case FILTER_KEYS.TAX_RATE: - case FILTER_KEYS.EXPORTED_TO: - case FILTER_KEYS.TAG: - case FILTER_KEYS.CATEGORY: { - const PopupComponent = { - [FILTER_KEYS.TAX_RATE]: TaxRateSelectPopup, - [FILTER_KEYS.EXPORTED_TO]: ExportedToSelectPopup, - [FILTER_KEYS.TAG]: TagSelectPopup, - [FILTER_KEYS.CATEGORY]: CategorySelectPopup, - [FILTER_KEYS.IN]: InSelectPopup, - }[filterKey]; + if (filterKey.startsWith(CONST.SEARCH.REPORT_FIELD.GLOBAL_PREFIX)) { return { - PopoverComponent: ({closeOverlay}) => ( - ( + - ), - sentryLabel: getFilterSentryLabel(filterKey), - }; - } - case FILTER_KEYS.CARD_ID: { - return { - PopoverComponent: ({closeOverlay, isExpanded}) => ( - ), sentryLabel: getFilterSentryLabel(filterKey), }; } - case FILTER_KEYS.FEED: { - return { - PopoverComponent: ({closeOverlay, isExpanded}) => ( - - ), - sentryLabel: getFilterSentryLabel(filterKey), - }; + + const label = FILTER_LABEL_MAP[filterKey]; + if (!label) { + return {PopoverComponent: () => null}; } - case FILTER_KEYS.MERCHANT: - case FILTER_KEYS.DESCRIPTION: - case FILTER_KEYS.REPORT_ID: - case FILTER_KEYS.KEYWORD: - case FILTER_KEYS.TITLE: - case FILTER_KEYS.WITHDRAWAL_ID: { - return { - PopoverComponent: ({closeOverlay}) => ( - ( + + ), + sentryLabel: getFilterSentryLabel(filterKey), + }; + } + case FILTER_KEYS.CARD_ID: { + return { + PopoverComponent: ({closeOverlay, isExpanded}) => ( + + ), + sentryLabel: getFilterSentryLabel(filterKey), + }; + } + case FILTER_KEYS.FEED: { + return { + PopoverComponent: ({closeOverlay, isExpanded}) => ( + + ), + sentryLabel: getFilterSentryLabel(filterKey), + }; + } + case FILTER_KEYS.MERCHANT: + case FILTER_KEYS.DESCRIPTION: + case FILTER_KEYS.REPORT_ID: + case FILTER_KEYS.KEYWORD: + case FILTER_KEYS.TITLE: + case FILTER_KEYS.WITHDRAWAL_ID: { + return { + PopoverComponent: ({closeOverlay}) => ( + updateFilterForm({[filterKey]: value})} + /> + ), + sentryLabel: getFilterSentryLabel(filterKey), + }; + } + case FILTER_KEYS.CURRENCY: + case FILTER_KEYS.PURCHASE_CURRENCY: { + return { + PopoverComponent: ({closeOverlay}) => ( + { + const update: Partial = {}; + update[filterKey] = selectedItems.map((item) => item.value); + updateFilterForm(update); + }} + /> + ), + sentryLabel: getFilterSentryLabel(filterKey), + }; + } + case FILTER_KEYS.BILLABLE: + case FILTER_KEYS.REIMBURSABLE: + case FILTER_KEYS.WITHDRAWAL_TYPE: { + const formValue = searchAdvancedFiltersForm[filterKey]; + const items = getSingleSelectFilterOptions(filterKey, translate); + const value = items.find((option) => option.value === formValue) ?? null; + const singleSelectComponent = ({closeOverlay}: PopoverComponentProps) => ( + updateFilterForm({[filterKey]: value})} + onChange={(item) => updateFilterForm({[filterKey]: item?.value})} /> - ), - sentryLabel: getFilterSentryLabel(filterKey), - }; - } - case FILTER_KEYS.CURRENCY: - case FILTER_KEYS.PURCHASE_CURRENCY: { - return { - PopoverComponent: ({closeOverlay}) => ( - { - const update: Partial = {}; - update[filterKey] = selectedItems.map((item) => item.value); - updateFilterForm(update); - }} - /> - ), - sentryLabel: getFilterSentryLabel(filterKey), - }; - } - case FILTER_KEYS.BILLABLE: - case FILTER_KEYS.REIMBURSABLE: - case FILTER_KEYS.WITHDRAWAL_TYPE: { - const formValue = searchAdvancedFiltersForm[filterKey]; - const items = getSingleSelectFilterOptions(filterKey, translate); - const value = items.find((option) => option.value === formValue) ?? null; - const singleSelectComponent = ({closeOverlay}: PopoverComponentProps) => ( - updateFilterForm({[filterKey]: item?.value})} - /> - ); - return {PopoverComponent: singleSelectComponent, sentryLabel: getFilterSentryLabel(filterKey)}; - } - case FILTER_KEYS.HAS: - case FILTER_KEYS.IS: - case FILTER_KEYS.EXPENSE_TYPE: - case FILTER_KEYS.STATUS: { - let formValues = searchAdvancedFiltersForm[filterKey] ?? []; - - if (filterKey === FILTER_KEYS.STATUS) { - formValues = Array.isArray(formValues) ? formValues : formValues.split(','); + ); + return {PopoverComponent: singleSelectComponent, sentryLabel: getFilterSentryLabel(filterKey)}; } + case FILTER_KEYS.HAS: + case FILTER_KEYS.IS: + case FILTER_KEYS.EXPENSE_TYPE: + case FILTER_KEYS.STATUS: { + let formValues = searchAdvancedFiltersForm[filterKey] ?? []; - const items = getMultiSelectFilterOptions(filterKey, type, translate); - const value = items.filter((item) => formValues.includes(item.value)); + if (filterKey === FILTER_KEYS.STATUS) { + formValues = Array.isArray(formValues) ? formValues : formValues.split(','); + } - const multiSelectComponent = ({closeOverlay}: PopoverComponentProps) => ( - { - if (filterKey === FILTER_KEYS.STATUS) { - updateFilterForm({status: selectedItems.length ? selectedItems.map((item) => item.value) : CONST.SEARCH.STATUS.EXPENSE.ALL}); - return; - } - const update: Partial = {}; - update[filterKey] = selectedItems.map((item) => item.value) as ExpenseTypeValues & HasFilterValues & IsFilterValues; - updateFilterForm(update); - }} - /> - ); + const items = getMultiSelectFilterOptions(filterKey, type, translate); + const value = items.filter((item) => formValues.includes(item.value)); - return {PopoverComponent: multiSelectComponent, sentryLabel: getFilterSentryLabel(filterKey)}; - } - case FILTER_KEYS.ASSIGNEE: - case FILTER_KEYS.ATTENDEE: - case FILTER_KEYS.TO: - case FILTER_KEYS.FROM: - return { - PopoverComponent: ({closeOverlay}) => ( - ( + { + translationKey={label} + items={items} + value={value} + onChangeCallback={(selectedItems) => { + if (filterKey === FILTER_KEYS.STATUS) { + updateFilterForm({status: selectedItems.length ? selectedItems.map((item) => item.value) : CONST.SEARCH.STATUS.EXPENSE.ALL}); + return; + } const update: Partial = {}; - update[filterKey] = selectedUsers; + update[filterKey] = selectedItems.map((item) => item.value) as ExpenseTypeValues & HasFilterValues & IsFilterValues; updateFilterForm(update); }} /> - ), - sentryLabel: getFilterSentryLabel(filterKey), - }; - case FILTER_KEYS.POLICY_ID: - return { - PopoverComponent: ({closeOverlay}) => ( - - ), - sentryLabel: getFilterSentryLabel(filterKey), - }; - default: - // This should be unreachable - return {PopoverComponent: () => null}; - } - }); + ); + + return {PopoverComponent: multiSelectComponent, sentryLabel: getFilterSentryLabel(filterKey)}; + } + case FILTER_KEYS.ASSIGNEE: + case FILTER_KEYS.ATTENDEE: + case FILTER_KEYS.TO: + case FILTER_KEYS.FROM: + return { + PopoverComponent: ({closeOverlay}) => ( + { + const update: Partial = {}; + update[filterKey] = selectedUsers; + updateFilterForm(update); + }} + /> + ), + sentryLabel: getFilterSentryLabel(filterKey), + }; + case FILTER_KEYS.POLICY_ID: + return { + PopoverComponent: ({closeOverlay}) => ( + + ), + sentryLabel: getFilterSentryLabel(filterKey), + }; + default: + // This should be unreachable + return {PopoverComponent: () => null}; + } + }, + ); return { filters, diff --git a/src/components/SelectionList/ListItem/SplitListItem.tsx b/src/components/SelectionList/ListItem/SplitListItem.tsx index 318ea0e323d7..f9bed8c0c2c2 100644 --- a/src/components/SelectionList/ListItem/SplitListItem.tsx +++ b/src/components/SelectionList/ListItem/SplitListItem.tsx @@ -7,12 +7,12 @@ import Text from '@components/Text'; import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle'; import useAutoFocusInput from '@hooks/useAutoFocusInput'; +import {useCurrencyListActions} from '@hooks/useCurrencyList'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {getDecodedCategoryName} from '@libs/CategoryUtils'; -import {convertToDisplayStringWithoutCurrency} from '@libs/CurrencyUtils'; import {getCommaSeparatedTagNameWithSanitizedColons} from '@libs/PolicyUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; @@ -37,6 +37,7 @@ function SplitListItem({ const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); + const {convertToDisplayStringWithoutCurrency} = useCurrencyListActions(); const splitItem = item as unknown as SplitListItemType; const formattedOriginalAmount = convertToDisplayStringWithoutCurrency(splitItem.originalAmount, splitItem.currency); diff --git a/src/components/SelectionList/ListItem/SplitListItem/SplitAmountDisplay.tsx b/src/components/SelectionList/ListItem/SplitListItem/SplitAmountDisplay.tsx index 5120e1e6ca73..e76f09f82e35 100644 --- a/src/components/SelectionList/ListItem/SplitListItem/SplitAmountDisplay.tsx +++ b/src/components/SelectionList/ListItem/SplitListItem/SplitAmountDisplay.tsx @@ -2,8 +2,8 @@ import React, {useState} from 'react'; import {View} from 'react-native'; import type {SplitListItemType} from '@components/SelectionList/ListItem/types'; import Text from '@components/Text'; +import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useThemeStyles from '@hooks/useThemeStyles'; -import {convertToDisplayStringWithoutCurrency} from '@libs/CurrencyUtils'; import CONST from '@src/CONST'; type SplitAmountDisplayProps = { @@ -17,6 +17,7 @@ type SplitAmountDisplayProps = { function SplitAmountDisplay({splitItem, contentWidth = '100%', shouldRemoveSpacing = false}: SplitAmountDisplayProps) { const styles = useThemeStyles(); + const {convertToDisplayStringWithoutCurrency} = useCurrencyListActions(); const [prefixCharacterMargin, setPrefixCharacterMargin] = useState(CONST.CHARACTER_WIDTH); return ( diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index bdf78a8ef060..0680c1c8d3a4 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -99,7 +99,7 @@ import type {CardFeedForDisplay} from './CardFeedUtils'; import {getCardFeedsForDisplay} from './CardFeedUtils'; import {getCardDescriptionForSearchTable, getFeedNameForDisplay} from './CardUtils'; import {getDecodedCategoryName} from './CategoryUtils'; -import {convertToDisplayString, convertToDisplayStringWithoutCurrency} from './CurrencyUtils'; +import {convertToDisplayString} from './CurrencyUtils'; import DateUtils from './DateUtils'; import interceptAnonymousUser from './interceptAnonymousUser'; import isSearchTopmostFullScreenRoute from './Navigation/helpers/isSearchTopmostFullScreenRoute'; @@ -4783,12 +4783,17 @@ function getDateDisplayValue(syntaxKey: SearchDateFilterKeys, form: Partial, translate: LocalizedTranslate): string | undefined { +function getAmountDisplayValue( + syntaxKey: SearchAmountFilterKeys, + form: Partial, + translate: LocalizedTranslate, + convertToDisplayStringWithoutCurrency: CurrencyListActionsContextType['convertToDisplayStringWithoutCurrency'], +): string | undefined { const lessThan = form[`${syntaxKey}${CONST.SEARCH.AMOUNT_MODIFIERS.LESS_THAN}`]; const greaterThan = form[`${syntaxKey}${CONST.SEARCH.AMOUNT_MODIFIERS.GREATER_THAN}`]; const equalTo = form[`${syntaxKey}${CONST.SEARCH.AMOUNT_MODIFIERS.EQUAL_TO}`]; - const formatAmount = (val: string) => convertToDisplayStringWithoutCurrency(Number(val)); + const formatAmount = (val: string) => convertToDisplayStringWithoutCurrency(Number(val), CONST.CURRENCY.USD); if (equalTo) { return translate('search.filters.amount.equalTo', formatAmount(equalTo)); @@ -4947,6 +4952,7 @@ function mapFiltersFormToLabelValueList>( skipFilters: Set | undefined, translate: LocalizedTranslate, localeCompare: LocaleContextProps['localeCompare'], + convertToDisplayStringWithoutCurrency: CurrencyListActionsContextType['convertToDisplayStringWithoutCurrency'], mapper?: (filterKey: SearchAdvancedFiltersKey) => T, ): Array { const filters: Array = []; @@ -4969,7 +4975,7 @@ function mapFiltersFormToLabelValueList>( } const displayValue = isAmountFilterKey(groupConfig.syntax) - ? getAmountDisplayValue(groupConfig.syntax, searchAdvancedFiltersForm, translate) + ? getAmountDisplayValue(groupConfig.syntax, searchAdvancedFiltersForm, translate, convertToDisplayStringWithoutCurrency) : getDateDisplayValue(groupConfig.syntax, searchAdvancedFiltersForm, translate); if (displayValue) { diff --git a/src/pages/Search/AdvancedSearchFilters.tsx b/src/pages/Search/AdvancedSearchFilters.tsx index 6172c7b51361..4cdf81e793ab 100644 --- a/src/pages/Search/AdvancedSearchFilters.tsx +++ b/src/pages/Search/AdvancedSearchFilters.tsx @@ -11,6 +11,8 @@ import type {SearchAmountFilterKeys, SearchDateFilterKeys, SearchFilterKey} from import SpacerView from '@components/SpacerView'; import Text from '@components/Text'; import useAdvancedSearchFilters from '@hooks/useAdvancedSearchFilters'; +import {useCurrencyListActions} from '@hooks/useCurrencyList'; +import type {CurrencyListActionsContextType} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useSingleExecution from '@hooks/useSingleExecution'; @@ -19,7 +21,6 @@ import useWaitForNavigation from '@hooks/useWaitForNavigation'; import type {WorkspaceListItem} from '@hooks/useWorkspaceList'; import {createCardFeedKey, getCardFeedKey, getCardFeedNamesWithType, getFeedCountryForDisplay, getWorkspaceCardFeedKey} from '@libs/CardFeedUtils'; import {getCardDescription} from '@libs/CardUtils'; -import {convertToDisplayStringWithoutCurrency} from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; import {createDisplayName} from '@libs/PersonalDetailsUtils'; import {getCleanedTagName} from '@libs/PolicyUtils'; @@ -312,6 +313,7 @@ function getFilterDisplayTitle( filterKey: SearchFilterKey, translate: LocaleContextProps['translate'], localeCompare: LocaleContextProps['localeCompare'], + convertToDisplayStringWithoutCurrency: CurrencyListActionsContextType['convertToDisplayStringWithoutCurrency'], ) { let key: SearchFilterKey = filterKey; @@ -359,16 +361,20 @@ function getFilterDisplayTitle( const equalTo = filters[equalToKey]; if (equalTo) { - return translate('search.filters.amount.equalTo', convertToDisplayStringWithoutCurrency(Number(equalTo))); + return translate('search.filters.amount.equalTo', convertToDisplayStringWithoutCurrency(Number(equalTo), CONST.CURRENCY.USD)); } if (lessThan && greaterThan) { - return translate('search.filters.amount.between', convertToDisplayStringWithoutCurrency(Number(greaterThan)), convertToDisplayStringWithoutCurrency(Number(lessThan))); + return translate( + 'search.filters.amount.between', + convertToDisplayStringWithoutCurrency(Number(greaterThan), CONST.CURRENCY.USD), + convertToDisplayStringWithoutCurrency(Number(lessThan), CONST.CURRENCY.USD), + ); } if (lessThan) { - return translate('search.filters.amount.lessThan', convertToDisplayStringWithoutCurrency(Number(lessThan))); + return translate('search.filters.amount.lessThan', convertToDisplayStringWithoutCurrency(Number(lessThan), CONST.CURRENCY.USD)); } if (greaterThan) { - return translate('search.filters.amount.greaterThan', convertToDisplayStringWithoutCurrency(Number(greaterThan))); + return translate('search.filters.amount.greaterThan', convertToDisplayStringWithoutCurrency(Number(greaterThan), CONST.CURRENCY.USD)); } // Will never happen return; @@ -585,6 +591,7 @@ function getFilterInDisplayTitle( function AdvancedSearchFilters() { const {translate, localeCompare, formatPhoneNumber} = useLocalize(); + const {convertToDisplayStringWithoutCurrency} = useCurrencyListActions(); const styles = useThemeStyles(); const {singleExecution} = useSingleExecution(); const waitForNavigate = useWaitForNavigation(); @@ -636,7 +643,7 @@ function AdvancedSearchFilters() { } else if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.STATUS) { filterTitle = baseFilterConfig[key].getTitle(searchAdvancedFilters, currentType, translate); } else { - filterTitle = baseFilterConfig[key].getTitle(searchAdvancedFilters, key, translate, localeCompare); + filterTitle = baseFilterConfig[key].getTitle(searchAdvancedFilters, key, translate, localeCompare, convertToDisplayStringWithoutCurrency); } return { diff --git a/src/pages/Search/SearchEditMultiple/SearchEditMultiplePage.tsx b/src/pages/Search/SearchEditMultiple/SearchEditMultiplePage.tsx index de90ce7d79f5..effffb484872 100644 --- a/src/pages/Search/SearchEditMultiple/SearchEditMultiplePage.tsx +++ b/src/pages/Search/SearchEditMultiple/SearchEditMultiplePage.tsx @@ -8,12 +8,12 @@ import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import {useSearchActionsContext, useSearchStateContext} from '@components/Search/SearchContext'; import Text from '@components/Text'; +import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; import {clearBulkEditDraftTransaction, updateMultipleMoneyRequests} from '@libs/actions/IOU/BulkEdit'; -import {convertToDisplayStringWithoutCurrency} from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; import {hasEnabledOptions} from '@libs/OptionsListUtils'; import {getCleanedTagName, getTagLists, hasDependentTags as hasDependentTagsPolicyUtils} from '@libs/PolicyUtils'; @@ -38,6 +38,7 @@ import { function SearchEditMultiplePage() { const {translate} = useLocalize(); + const {convertToDisplayStringWithoutCurrency} = useCurrencyListActions(); const styles = useThemeStyles(); const {currentSearchHash, currentSearchResults} = useSearchStateContext(); const {clearSelectedTransactions} = useSearchActionsContext(); diff --git a/src/pages/Search/SearchSavePage.tsx b/src/pages/Search/SearchSavePage.tsx index d26d8acba4ec..eb63cfef1305 100644 --- a/src/pages/Search/SearchSavePage.tsx +++ b/src/pages/Search/SearchSavePage.tsx @@ -16,6 +16,7 @@ import type {SearchQueryJSON} from '@components/Search/types'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useAutoFocusInput from '@hooks/useAutoFocusInput'; +import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -135,6 +136,7 @@ function getAppliedDisplays(searchAdvancedFiltersForm: Partial>()] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM); const [name, setName] = useState(''); @@ -151,7 +153,7 @@ function SearchSavePage() { Navigation.goBack(); }; - const appliedFilters = mapFiltersFormToLabelValueList(searchAdvancedFiltersForm, undefined, undefined, translate, localeCompare); + const appliedFilters = mapFiltersFormToLabelValueList(searchAdvancedFiltersForm, undefined, undefined, translate, localeCompare, convertToDisplayStringWithoutCurrency); const appliedDisplays = getAppliedDisplays(searchAdvancedFiltersForm, currentSearchQueryJSON, translate); const {inputCallbackRef} = useAutoFocusInput(); diff --git a/src/pages/workspace/perDiem/WorkspacePerDiemDetailsPage.tsx b/src/pages/workspace/perDiem/WorkspacePerDiemDetailsPage.tsx index 6ad7d1a428ec..da951a692d4b 100644 --- a/src/pages/workspace/perDiem/WorkspacePerDiemDetailsPage.tsx +++ b/src/pages/workspace/perDiem/WorkspacePerDiemDetailsPage.tsx @@ -12,7 +12,6 @@ import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePrevious from '@hooks/usePrevious'; import useThemeStyles from '@hooks/useThemeStyles'; -import {convertToDisplayStringWithoutCurrency} from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import {getPerDiemCustomUnit} from '@libs/PolicyUtils'; @@ -36,7 +35,7 @@ function WorkspacePerDiemDetailsPage({route}: WorkspacePerDiemDetailsPageProps) const styles = useThemeStyles(); const {translate} = useLocalize(); const {showConfirmModal} = useConfirmModal(); - const {getCurrencySymbol} = useCurrencyListActions(); + const {getCurrencySymbol, convertToDisplayStringWithoutCurrency} = useCurrencyListActions(); const customUnit = getPerDiemCustomUnit(policy); const selectedRate = customUnit?.rates?.[rateID]; @@ -46,7 +45,7 @@ function WorkspacePerDiemDetailsPage({route}: WorkspacePerDiemDetailsPageProps) const selectedSubRate = fetchedSubRate ?? previousFetchedSubRate; - const amountValue = selectedSubRate?.rate ? convertToDisplayStringWithoutCurrency(Number(selectedSubRate.rate)) : undefined; + const amountValue = selectedSubRate?.rate ? convertToDisplayStringWithoutCurrency(Number(selectedSubRate.rate), CONST.CURRENCY.USD) : undefined; const currencyValue = selectedRate?.currency ? `${selectedRate.currency} - ${getCurrencySymbol(selectedRate.currency)}` : undefined; const handleDeletePerDiemRate = () => { diff --git a/tests/unit/hooks/useSplitParticipants.test.tsx b/tests/unit/hooks/useSplitParticipants.test.tsx index 9568af77efcd..40dabffc8da0 100644 --- a/tests/unit/hooks/useSplitParticipants.test.tsx +++ b/tests/unit/hooks/useSplitParticipants.test.tsx @@ -26,6 +26,7 @@ jest.mock('@hooks/useThemeStyles', () => ({ jest.mock('@hooks/useCurrencyList', () => ({ useCurrencyListActions: () => ({ convertToDisplayString: (amount?: number, currency?: string) => `${currency ?? 'USD'} ${(amount ?? 0).toFixed(2)}`, + convertToDisplayStringWithoutCurrency: (amount: number) => `${(amount ?? 0).toFixed(2)}`, getCurrencySymbol: () => '$', }), }));