From 635797b413815948a398e87e5fa8de9410a1cd42 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 00:48:01 +0530 Subject: [PATCH 01/18] feat: update confirmation and rate selection UX for date-aware mileage rates Signed-off-by: krishna2323 --- .../MoneyRequestConfirmationList.tsx | 13 ++- .../DistanceRequestController.tsx | 14 ++- .../sections/RateField.tsx | 106 +++++++++++------- .../fieldGroupTypes.ts | 1 + .../fieldGroups/TransactionDetailsFields.tsx | 1 + src/languages/en.ts | 4 + src/libs/DistanceRequestUtils.ts | 25 +++++ .../step/IOURequestStepDistanceRate.tsx | 5 +- 8 files changed, 126 insertions(+), 43 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 9a8e7d9420d9..eeed18f61e7d 100644 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -256,6 +256,17 @@ function MoneyRequestConfirmationList({ const previousTransactionCurrency = usePrevious(transaction?.currency); const customUnitRateID = getRateID(transaction); + const [prevCreatedForTooltip, setPrevCreatedForTooltip] = useState(transaction?.created); + const [prevRateIDForTooltip, setPrevRateIDForTooltip] = useState(customUnitRateID); + const [shouldShowRateAutoUpdatedTooltip, setShouldShowRateAutoUpdatedTooltip] = useState(false); + if (prevCreatedForTooltip !== transaction?.created || prevRateIDForTooltip !== customUnitRateID) { + const dateChanged = prevCreatedForTooltip !== transaction?.created; + const rateChanged = prevRateIDForTooltip !== customUnitRateID; + setShouldShowRateAutoUpdatedTooltip(isDistanceRequest && dateChanged && rateChanged && !!prevCreatedForTooltip && !!prevRateIDForTooltip); + setPrevCreatedForTooltip(transaction?.created); + setPrevRateIDForTooltip(customUnitRateID); + } + const subRates = transaction?.comment?.customUnit?.subRates ?? []; const prevSubRates = usePrevious(subRates); @@ -545,7 +556,7 @@ function MoneyRequestConfirmationList({ isPolicyExpenseChat={isPolicyExpenseChat} expenseMode={{isDistance: isDistanceRequest, isTime: isTimeRequest, isInvoice: isTypeInvoice, isPerDiem: isPerDiemRequest}} distanceFlags={{isManualDistanceRequest, isOdometerDistanceRequest, isGPSDistanceRequest}} - distanceData={{distance, hasRoute, unit, rate, distanceRateName: mileageRate.name, distanceRateCurrency: currency}} + distanceData={{distance, hasRoute, unit, rate, distanceRateName: mileageRate.name, distanceRateCurrency: currency, shouldShowRateAutoUpdatedTooltip}} amountDisplay={{amount: amountToBeUsed, formattedAmount, formattedAmountPerAttendee}} requiredFlags={{isCategoryRequired, isMerchantRequired, isDescriptionRequired}} visibilityFlags={{ diff --git a/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx b/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx index 94e3a9de782e..187625ee1c3f 100644 --- a/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx +++ b/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx @@ -177,7 +177,19 @@ function DistanceRequestController({ return; } - setCustomUnitRateID(transactionID, lastSelectedRate, transaction, policy); + let rateToUse = lastSelectedRate; + const expenseDate = transaction?.created; + if (expenseDate) { + const mileageRates = DistanceRequestUtils.getMileageRates(policy); + const lastRate = lastSelectedRate ? mileageRates[lastSelectedRate] : undefined; + if (lastRate && !DistanceRequestUtils.isRateEligibleForDate(lastRate, expenseDate)) { + const bestRate = DistanceRequestUtils.getBestEligibleRate(mileageRates, expenseDate); + if (bestRate?.customUnitRateID) { + rateToUse = bestRate.customUnitRateID; + } + } + } + setCustomUnitRateID(transactionID, rateToUse, transaction, policy); }, [customUnitRateID, transactionID, lastSelectedRate, isDistanceRequest, isPolicyExpenseChat, isMovingTransactionFromTrackExpense, transaction, policy, selectedParticipants]); useEffect(() => { diff --git a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx index 46c64a8dafdb..ac70f535c7ef 100644 --- a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx +++ b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx @@ -1,6 +1,9 @@ -import React from 'react'; +import React, {useCallback} from 'react'; +import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import Text from '@components/Text'; +import EducationalTooltip from '@components/Tooltip/EducationalTooltip'; import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -30,6 +33,7 @@ type RateFieldProps = { formError: string; shouldNavigateToUpgradePath: boolean; shouldSelectPolicy: boolean; + shouldShowRateAutoUpdatedTooltip?: boolean; }; function RateField({ @@ -49,6 +53,7 @@ function RateField({ formError, shouldNavigateToUpgradePath, shouldSelectPolicy, + shouldShowRateAutoUpdatedTooltip, }: RateFieldProps) { const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); @@ -59,47 +64,68 @@ function RateField({ const isTrackExpense = iouType === CONST.IOU.TYPE.TRACK; const isRateInteractive = !!rate && !isReadOnly && iouType !== CONST.IOU.TYPE.SPLIT; - return ( - { - if (!transactionID) { - return; - } + const renderTooltipContent = useCallback( + () => ( + + {translate('iou.rateAutoUpdatedTooltip')} + + ), + [styles, translate], + ); - if ((!isPolicyExpenseChat && !isTrackExpense) || (shouldNavigateToUpgradePath && isTrackExpense)) { - Navigation.navigate( - ROUTES.MONEY_REQUEST_UPGRADE.getRoute({ - action, - iouType, - transactionID, - reportID, - upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES, - backTo: Navigation.getActiveRoute(), - shouldSubmitExpense: !isTrackExpense, - }), - ); - } else if (!policy && shouldSelectPolicy && isTrackExpense) { - Navigation.navigate( - ROUTES.SET_DEFAULT_WORKSPACE.getRoute( - ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID), - ), - ); - } else { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID)); - } + return ( + + wrapperStyle={styles.productTrainingTooltipWrapper} + shouldHideOnNavigate + shiftVertical={-8} + > + + { + if (!transactionID) { + return; + } + + if ((!isPolicyExpenseChat && !isTrackExpense) || (shouldNavigateToUpgradePath && isTrackExpense)) { + Navigation.navigate( + ROUTES.MONEY_REQUEST_UPGRADE.getRoute({ + action, + iouType, + transactionID, + reportID, + upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES, + backTo: Navigation.getActiveRoute(), + shouldSubmitExpense: !isTrackExpense, + }), + ); + } else if (!policy && shouldSelectPolicy && isTrackExpense) { + Navigation.navigate( + ROUTES.SET_DEFAULT_WORKSPACE.getRoute( + ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID), + ), + ); + } else { + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID)); + } + }} + brickRoadIndicator={shouldDisplayDistanceRateError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + disabled={didConfirm} + interactive={isRateInteractive} + sentryLabel={CONST.SENTRY_LABEL.REQUEST_CONFIRMATION_LIST.RATE_FIELD} + /> + + ); } diff --git a/src/components/MoneyRequestConfirmationListFooter/fieldGroupTypes.ts b/src/components/MoneyRequestConfirmationListFooter/fieldGroupTypes.ts index ac8c36dfae68..462298a94da6 100644 --- a/src/components/MoneyRequestConfirmationListFooter/fieldGroupTypes.ts +++ b/src/components/MoneyRequestConfirmationListFooter/fieldGroupTypes.ts @@ -16,6 +16,7 @@ type DistanceData = { rate: number | undefined; distanceRateName: string | undefined; distanceRateCurrency: string; + shouldShowRateAutoUpdatedTooltip?: boolean; }; /** Distance-mode discriminators (manual / odometer / GPS) */ diff --git a/src/components/MoneyRequestConfirmationListFooter/fieldGroups/TransactionDetailsFields.tsx b/src/components/MoneyRequestConfirmationListFooter/fieldGroups/TransactionDetailsFields.tsx index 5fb7255ee0ae..2d407b19b366 100644 --- a/src/components/MoneyRequestConfirmationListFooter/fieldGroups/TransactionDetailsFields.tsx +++ b/src/components/MoneyRequestConfirmationListFooter/fieldGroups/TransactionDetailsFields.tsx @@ -166,6 +166,7 @@ function TransactionDetailsFields({ formError={errorState.formError} shouldNavigateToUpgradePath={shouldNavigateToUpgradePath} shouldSelectPolicy={shouldSelectPolicy} + shouldShowRateAutoUpdatedTooltip={distanceData.shouldShowRateAutoUpdatedTooltip} /> )} diff --git a/src/languages/en.ts b/src/languages/en.ts index 0790bc189b09..f627e2342ee3 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1619,6 +1619,10 @@ const translations = { removed: 'removed', transactionPending: 'Transaction pending.', chooseARate: 'Select a workspace reimbursement rate per mile or kilometer', + rateAutoUpdatedTooltip: 'We updated the rate based on your travel date.', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `Valid ${startDate} - ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `Valid from ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `Valid until ${endDate}`, unapprove: 'Unapprove', unapproveReport: 'Unapprove report', headsUp: 'Heads up!', diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index cc34091925b7..45029ef4697b 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -1,3 +1,4 @@ +import {format, parseISO} from 'date-fns'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {CurrencyListActionsContextType} from '@components/CurrencyListContextProvider'; @@ -633,6 +634,29 @@ function prepareTextForDisplay(text: string): string { return text.replaceAll(/[^0-9., ]/g, '').replace(/^0+(?=\d)/, ''); } +function getRateDateLabel(rate: MileageRate, translate: LocaleContextProps['translate']): string { + const dateFormat = CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT; + + try { + if (rate.startDate && rate.endDate) { + return translate('iou.rateValidDateRange', { + startDate: format(parseISO(rate.startDate), dateFormat), + endDate: format(parseISO(rate.endDate), dateFormat), + }); + } + if (rate.startDate) { + return translate('iou.rateValidFrom', {startDate: format(parseISO(rate.startDate), dateFormat)}); + } + if (rate.endDate) { + return translate('iou.rateValidUntil', {endDate: format(parseISO(rate.endDate), dateFormat)}); + } + } catch { + return ''; + } + + return ''; +} + export default { getDefaultMileageRate, getDistanceMerchant, @@ -657,6 +681,7 @@ export default { prepareTextForDisplay, isRateEligibleForDate, getBestEligibleRate, + getRateDateLabel, }; export type {MileageRate}; diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 641d74e65c29..fe8084bf569b 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -137,9 +137,12 @@ function IOURequestStepDistanceRate({ ? effectiveRateID === rate.customUnitRateID && !hasUnitMismatchForMovingTrackExpense : DistanceRequestUtils.getDefaultMileageRate(policy)?.customUnitRateID === rate.customUnitRateID; const rateForDisplay = DistanceRequestUtils.getFormattedRateValue(unit, rate.rate, isSelected ? transactionCurrency : rate.currency, translate, toLocaleDigit, getCurrencySymbol); + const dateLabel = DistanceRequestUtils.getRateDateLabel(rate, translate); + const baseAlternateText = rate.name ? rateForDisplay : ''; + const alternateText = dateLabel ? [baseAlternateText, dateLabel].filter(Boolean).join(' • ') : baseAlternateText; return { text: rate.name ?? rateForDisplay, - alternateText: rate.name ? rateForDisplay : '', + alternateText, keyForList: rate.customUnitRateID ?? rateForDisplay, value: rate.customUnitRateID, isDisabled: !rate.enabled, From 8105844adf76fa404814272c4b5751dd3133e93e Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 01:06:46 +0530 Subject: [PATCH 02/18] migrate rate tooltip to ProductTrainingContext pattern Signed-off-by: krishna2323 --- src/CONST/index.ts | 1 + .../sections/RateField.tsx | 108 ++++++++---------- .../ProductTrainingContext/TOOLTIPS.ts | 10 +- .../ProductTrainingContext/index.tsx | 1 + src/languages/en.ts | 2 +- src/types/onyx/DismissedProductTraining.ts | 18 ++- 6 files changed, 74 insertions(+), 66 deletions(-) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 086acf144cdc..4674f54774cc 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -8321,6 +8321,7 @@ const CONST = { MULTI_SCAN_EDUCATIONAL_MODAL: 'multiScanEducationalModal', GPS_TOOLTIP: 'gpsTooltip', HAS_FILTER_NEGATION: 'hasFilterNegation', + MILEAGE_RATE_AUTO_UPDATED: 'mileageRateAutoUpdated', }, CHANGE_POLICY_TRAINING_MODAL: 'changePolicyModal', AGENTS_WORKFLOWS_BANNER: 'agentsWorkflowsBanner', diff --git a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx index ac70f535c7ef..5a60dcbe885b 100644 --- a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx +++ b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx @@ -1,9 +1,7 @@ -import React, {useCallback} from 'react'; -import {View} from 'react-native'; +import React from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; -import Text from '@components/Text'; -import EducationalTooltip from '@components/Tooltip/EducationalTooltip'; +import {useProductTrainingContext} from '@components/ProductTrainingContext'; import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -64,68 +62,54 @@ function RateField({ const isTrackExpense = iouType === CONST.IOU.TYPE.TRACK; const isRateInteractive = !!rate && !isReadOnly && iouType !== CONST.IOU.TYPE.SPLIT; - const renderTooltipContent = useCallback( - () => ( - - {translate('iou.rateAutoUpdatedTooltip')} - - ), - [styles, translate], + const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip} = useProductTrainingContext( + CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.MILEAGE_RATE_AUTO_UPDATED, + !!shouldShowRateAutoUpdatedTooltip, ); return ( - - - { - if (!transactionID) { - return; - } + { + if (!transactionID) { + return; + } - if ((!isPolicyExpenseChat && !isTrackExpense) || (shouldNavigateToUpgradePath && isTrackExpense)) { - Navigation.navigate( - ROUTES.MONEY_REQUEST_UPGRADE.getRoute({ - action, - iouType, - transactionID, - reportID, - upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES, - backTo: Navigation.getActiveRoute(), - shouldSubmitExpense: !isTrackExpense, - }), - ); - } else if (!policy && shouldSelectPolicy && isTrackExpense) { - Navigation.navigate( - ROUTES.SET_DEFAULT_WORKSPACE.getRoute( - ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID), - ), - ); - } else { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID)); - } - }} - brickRoadIndicator={shouldDisplayDistanceRateError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - disabled={didConfirm} - interactive={isRateInteractive} - sentryLabel={CONST.SENTRY_LABEL.REQUEST_CONFIRMATION_LIST.RATE_FIELD} - /> - - + if ((!isPolicyExpenseChat && !isTrackExpense) || (shouldNavigateToUpgradePath && isTrackExpense)) { + Navigation.navigate( + ROUTES.MONEY_REQUEST_UPGRADE.getRoute({ + action, + iouType, + transactionID, + reportID, + upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES, + backTo: Navigation.getActiveRoute(), + shouldSubmitExpense: !isTrackExpense, + }), + ); + } else if (!policy && shouldSelectPolicy && isTrackExpense) { + Navigation.navigate( + ROUTES.SET_DEFAULT_WORKSPACE.getRoute( + ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID), + ), + ); + } else { + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID)); + } + }} + brickRoadIndicator={shouldDisplayDistanceRateError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + disabled={didConfirm} + interactive={isRateInteractive} + sentryLabel={CONST.SENTRY_LABEL.REQUEST_CONFIRMATION_LIST.RATE_FIELD} + shouldRenderTooltip={shouldShowProductTrainingTooltip} + renderTooltipContent={renderProductTrainingTooltip} + tooltipWrapperStyle={styles.productTrainingTooltipWrapper} + tooltipAnchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM}} + /> ); } diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts index e47bf9396fb9..f5b7c13c2747 100644 --- a/src/components/ProductTrainingContext/TOOLTIPS.ts +++ b/src/components/ProductTrainingContext/TOOLTIPS.ts @@ -3,7 +3,8 @@ import {dismissProductTraining} from '@libs/actions/Welcome'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; -const {CONCIERGE_LHN_GBR, RENAME_SAVED_SEARCH, OUTSTANDING_FILTER, ACCOUNT_SWITCHER, SCAN_TEST_DRIVE_CONFIRMATION, GPS_TOOLTIP, HAS_FILTER_NEGATION} = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; +const {CONCIERGE_LHN_GBR, RENAME_SAVED_SEARCH, OUTSTANDING_FILTER, ACCOUNT_SWITCHER, SCAN_TEST_DRIVE_CONFIRMATION, GPS_TOOLTIP, HAS_FILTER_NEGATION, MILEAGE_RATE_AUTO_UPDATED} = + CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; type ProductTrainingTooltipName = Exclude, typeof CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.MULTI_SCAN_EDUCATIONAL_MODAL>; @@ -75,6 +76,13 @@ const TOOLTIPS: Record = { priority: 1000, shouldShow: () => true, }, + [MILEAGE_RATE_AUTO_UPDATED]: { + content: 'productTrainingTooltip.mileageRateAutoUpdated', + onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(MILEAGE_RATE_AUTO_UPDATED, isDismissedUsingCloseButton), + name: MILEAGE_RATE_AUTO_UPDATED, + priority: 800, + shouldShow: () => true, + }, }; export default TOOLTIPS; diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx index d87310027d4a..32bd75136558 100644 --- a/src/components/ProductTrainingContext/index.tsx +++ b/src/components/ProductTrainingContext/index.tsx @@ -143,6 +143,7 @@ function ProductTrainingContextProvider({children}: ChildrenProps) { tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_DRIVE_CONFIRMATION && tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GPS_TOOLTIP && tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.HAS_FILTER_NEGATION && + tooltipName !== CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.MILEAGE_RATE_AUTO_UPDATED && isModalVisible ) { return false; diff --git a/src/languages/en.ts b/src/languages/en.ts index f627e2342ee3..8b2122e46ff7 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1619,7 +1619,6 @@ const translations = { removed: 'removed', transactionPending: 'Transaction pending.', chooseARate: 'Select a workspace reimbursement rate per mile or kilometer', - rateAutoUpdatedTooltip: 'We updated the rate based on your travel date.', rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `Valid ${startDate} - ${endDate}`, rateValidFrom: ({startDate}: {startDate: string}) => `Valid from ${startDate}`, rateValidUntil: ({endDate}: {endDate: string}) => `Valid until ${endDate}`, @@ -9463,6 +9462,7 @@ const translations = { scanTestDriveTooltip: 'Send this receipt to\ncomplete the test drive!', gpsTooltip: "GPS tracking in progress! When you're done, stop tracking below.", hasFilterNegation: 'Search for expenses without receipts using -has:receipt.', + mileageRateAutoUpdated: 'We updated the rate based on your travel date.', }, discardChangesConfirmation: { title: 'Discard changes?', diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts index 1a186f0534c1..ee5529be2b80 100644 --- a/src/types/onyx/DismissedProductTraining.ts +++ b/src/types/onyx/DismissedProductTraining.ts @@ -1,7 +1,16 @@ import CONST from '@src/CONST'; -const {CONCIERGE_LHN_GBR, RENAME_SAVED_SEARCH, OUTSTANDING_FILTER, ACCOUNT_SWITCHER, SCAN_TEST_DRIVE_CONFIRMATION, MULTI_SCAN_EDUCATIONAL_MODAL, GPS_TOOLTIP, HAS_FILTER_NEGATION} = - CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; +const { + CONCIERGE_LHN_GBR, + RENAME_SAVED_SEARCH, + OUTSTANDING_FILTER, + ACCOUNT_SWITCHER, + SCAN_TEST_DRIVE_CONFIRMATION, + MULTI_SCAN_EDUCATIONAL_MODAL, + GPS_TOOLTIP, + HAS_FILTER_NEGATION, + MILEAGE_RATE_AUTO_UPDATED, +} = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; /** * This type is used to store the timestamp of when the user dismisses a product training ui elements. @@ -78,6 +87,11 @@ type DismissedProductTraining = { * When user dismisses the Has filter negation tooltip, we store the timestamp here. */ [HAS_FILTER_NEGATION]: DismissedProductTrainingElement; + + /** + * When user dismisses the mileage rate auto-updated tooltip, we store the timestamp here. + */ + [MILEAGE_RATE_AUTO_UPDATED]: DismissedProductTrainingElement; }; export default DismissedProductTraining; From 577fb2231ef6096580164715778a6e554e959c75 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 01:15:16 +0530 Subject: [PATCH 03/18] extract tooltip shift values to style variables Signed-off-by: krishna2323 --- .../MoneyRequestConfirmationList/sections/RateField.tsx | 3 +++ src/styles/variables.ts | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx index 5a60dcbe885b..433571dd1ad6 100644 --- a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx +++ b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx @@ -8,6 +8,7 @@ import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import Navigation from '@libs/Navigation/Navigation'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; import type {IOUAction, IOUType} from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -109,6 +110,8 @@ function RateField({ renderTooltipContent={renderProductTrainingTooltip} tooltipWrapperStyle={styles.productTrainingTooltipWrapper} tooltipAnchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM}} + tooltipShiftHorizontal={variables.mileageRateTooltipShiftHorizontal} + tooltipShiftVertical={variables.mileageRateTooltipShiftVertical} /> ); } diff --git a/src/styles/variables.ts b/src/styles/variables.ts index f78b02fa7ded..a6c105d9e303 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -354,6 +354,8 @@ export default { hasFilterNegationTooltipShiftHorizontal: -16, hasFilterNegationTooltipShiftVertical: 40, hasFilterNegationTooltipMaxWidth: 260, + mileageRateTooltipShiftHorizontal: 12, + mileageRateTooltipShiftVertical: 4, inlineImagePreviewMinSize: 64, inlineImagePreviewMaxSize: 148, From 58c08b1d7807a3daae70240e7a8afb0de880e976 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 01:20:31 +0530 Subject: [PATCH 04/18] restore comment. Signed-off-by: krishna2323 --- .../MoneyRequestConfirmationList/sections/RateField.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx index 433571dd1ad6..cbf01353a1d9 100644 --- a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx +++ b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx @@ -71,6 +71,8 @@ function RateField({ return ( Date: Mon, 8 Jun 2026 01:29:43 +0530 Subject: [PATCH 05/18] align rate display and tooltip with design doc Signed-off-by: krishna2323 --- src/languages/en.ts | 2 +- src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 8b2122e46ff7..f23a44ad6769 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1619,7 +1619,7 @@ const translations = { removed: 'removed', transactionPending: 'Transaction pending.', chooseARate: 'Select a workspace reimbursement rate per mile or kilometer', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `Valid ${startDate} - ${endDate}`, + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} to ${endDate}`, rateValidFrom: ({startDate}: {startDate: string}) => `Valid from ${startDate}`, rateValidUntil: ({endDate}: {endDate: string}) => `Valid until ${endDate}`, unapprove: 'Unapprove', diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index fe8084bf569b..125bbecfc5ed 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -138,8 +138,7 @@ function IOURequestStepDistanceRate({ : DistanceRequestUtils.getDefaultMileageRate(policy)?.customUnitRateID === rate.customUnitRateID; const rateForDisplay = DistanceRequestUtils.getFormattedRateValue(unit, rate.rate, isSelected ? transactionCurrency : rate.currency, translate, toLocaleDigit, getCurrencySymbol); const dateLabel = DistanceRequestUtils.getRateDateLabel(rate, translate); - const baseAlternateText = rate.name ? rateForDisplay : ''; - const alternateText = dateLabel ? [baseAlternateText, dateLabel].filter(Boolean).join(' • ') : baseAlternateText; + const alternateText = dateLabel ? [rateForDisplay, dateLabel].filter(Boolean).join(' • ') : rateForDisplay; return { text: rate.name ?? rateForDisplay, alternateText, From 8358365f893c1021a278ac25152e557fac697bac Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 01:35:47 +0530 Subject: [PATCH 06/18] dismiss tooltip on press Signed-off-by: krishna2323 --- .../MoneyRequestConfirmationList/sections/RateField.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx index cbf01353a1d9..820c3945f36a 100644 --- a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx +++ b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx @@ -63,7 +63,7 @@ function RateField({ const isTrackExpense = iouType === CONST.IOU.TYPE.TRACK; const isRateInteractive = !!rate && !isReadOnly && iouType !== CONST.IOU.TYPE.SPLIT; - const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip} = useProductTrainingContext( + const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext( CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.MILEAGE_RATE_AUTO_UPDATED, !!shouldShowRateAutoUpdatedTooltip, ); @@ -114,6 +114,7 @@ function RateField({ tooltipAnchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM}} tooltipShiftHorizontal={variables.mileageRateTooltipShiftHorizontal} tooltipShiftVertical={variables.mileageRateTooltipShiftVertical} + onEducationTooltipPress={hideProductTrainingTooltip} /> ); } From 2b4f30e018c4c7e1b8e3e648d5402d7c9daf8c71 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 01:55:55 +0530 Subject: [PATCH 07/18] fix: add default rate fallback in date-aware auto-selection Signed-off-by: krishna2323 --- .../DistanceRequestController.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx b/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx index 187625ee1c3f..d96c5e45403e 100644 --- a/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx +++ b/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx @@ -182,15 +182,13 @@ function DistanceRequestController({ if (expenseDate) { const mileageRates = DistanceRequestUtils.getMileageRates(policy); const lastRate = lastSelectedRate ? mileageRates[lastSelectedRate] : undefined; - if (lastRate && !DistanceRequestUtils.isRateEligibleForDate(lastRate, expenseDate)) { + if (!lastRate || !DistanceRequestUtils.isRateEligibleForDate(lastRate, expenseDate)) { const bestRate = DistanceRequestUtils.getBestEligibleRate(mileageRates, expenseDate); - if (bestRate?.customUnitRateID) { - rateToUse = bestRate.customUnitRateID; - } + rateToUse = bestRate?.customUnitRateID ?? defaultMileageRateCustomUnitRateID ?? lastSelectedRate; } } setCustomUnitRateID(transactionID, rateToUse, transaction, policy); - }, [customUnitRateID, transactionID, lastSelectedRate, isDistanceRequest, isPolicyExpenseChat, isMovingTransactionFromTrackExpense, transaction, policy, selectedParticipants]); + }, [customUnitRateID, transactionID, lastSelectedRate, isDistanceRequest, isPolicyExpenseChat, isMovingTransactionFromTrackExpense, transaction, policy, selectedParticipants, defaultMileageRateCustomUnitRateID]); useEffect(() => { if (!isDistanceRequest || !transactionID || isReadOnly) { From 331cedcbd3b8e5443c441ce020a7ab6062599549 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 02:04:01 +0530 Subject: [PATCH 08/18] simplify tooltip detection with usePrevious Signed-off-by: krishna2323 --- src/components/MoneyRequestConfirmationList.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index eeed18f61e7d..0ef97977223e 100644 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -256,15 +256,16 @@ function MoneyRequestConfirmationList({ const previousTransactionCurrency = usePrevious(transaction?.currency); const customUnitRateID = getRateID(transaction); - const [prevCreatedForTooltip, setPrevCreatedForTooltip] = useState(transaction?.created); - const [prevRateIDForTooltip, setPrevRateIDForTooltip] = useState(customUnitRateID); + const prevCreated = usePrevious(transaction?.created); + const prevRateID = usePrevious(customUnitRateID); const [shouldShowRateAutoUpdatedTooltip, setShouldShowRateAutoUpdatedTooltip] = useState(false); - if (prevCreatedForTooltip !== transaction?.created || prevRateIDForTooltip !== customUnitRateID) { - const dateChanged = prevCreatedForTooltip !== transaction?.created; - const rateChanged = prevRateIDForTooltip !== customUnitRateID; - setShouldShowRateAutoUpdatedTooltip(isDistanceRequest && dateChanged && rateChanged && !!prevCreatedForTooltip && !!prevRateIDForTooltip); - setPrevCreatedForTooltip(transaction?.created); - setPrevRateIDForTooltip(customUnitRateID); + const dateChanged = prevCreated !== undefined && prevCreated !== transaction?.created; + const rateChanged = prevRateID !== undefined && prevRateID !== customUnitRateID; + if (dateChanged || rateChanged) { + const newShouldShow = isDistanceRequest && dateChanged && rateChanged; + if (newShouldShow !== shouldShowRateAutoUpdatedTooltip) { + setShouldShowRateAutoUpdatedTooltip(newShouldShow); + } } const subRates = transaction?.comment?.customUnit?.subRates ?? []; From aab29667f80e166f1c9bb43d2e5d8fd4356259df Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 13:30:17 +0530 Subject: [PATCH 09/18] update translations. Signed-off-by: krishna2323 --- src/languages/de.ts | 4 ++++ src/languages/es.ts | 4 ++++ src/languages/fr.ts | 4 ++++ src/languages/it.ts | 4 ++++ src/languages/ja.ts | 4 ++++ src/languages/nl.ts | 4 ++++ src/languages/pl.ts | 4 ++++ src/languages/pt-BR.ts | 4 ++++ src/languages/zh-hans.ts | 4 ++++ 9 files changed, 36 insertions(+) diff --git a/src/languages/de.ts b/src/languages/de.ts index 32c68c42a5b1..382508d81b1a 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -1689,6 +1689,9 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Sie können bis zu ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} Ausgaben gleichzeitig duplizieren. Bitte wählen Sie weniger Ausgaben aus und versuchen Sie es erneut.`, deleted: 'Gelöscht', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} bis ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `Gültig ab ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `Gültig bis ${endDate}`, }, transactionMerge: { listPage: { @@ -9414,6 +9417,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc scanTestDriveTooltip: 'Sende diese Quittung, um\ndie Probefahrt abzuschließen!', gpsTooltip: 'GPS-Tracking läuft! Wenn du fertig bist, stoppe die Aufzeichnung unten.', hasFilterNegation: 'Suchen Sie nach Ausgaben ohne Belege mit -has:receipt.', + mileageRateAutoUpdated: 'Wir haben den Kurs basierend auf Ihrem Reisedatum aktualisiert.', }, discardChangesConfirmation: { title: 'Änderungen verwerfen?', diff --git a/src/languages/es.ts b/src/languages/es.ts index a776b7479367..b2ba49e02f87 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1645,6 +1645,9 @@ const translations: TranslationDeepObject = { prompt: 'Habilita el seguimiento de impuestos en el espacio de trabajo para editar los detalles del gasto o eliminar el impuesto de este gasto.', confirmText: 'Eliminar impuesto', }, + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} a ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `Válido desde ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `Válido hasta ${endDate}`, }, transactionMerge: { listPage: { @@ -9575,6 +9578,7 @@ ${amount} para ${merchant} - ${date}`, scanTestDriveTooltip: '¡Envía este recibo para\ncompletar la prueba!', gpsTooltip: '¡Seguimiento por GPS en curso! Cuando termines, detén el seguimiento a continuación.', hasFilterNegation: 'Busca gastos sin recibos usando -has:receipt.', + mileageRateAutoUpdated: 'Hemos actualizado la tasa según tu fecha de viaje.', }, discardChangesConfirmation: { title: '¿Descartar cambios?', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 7ba2b143d6e2..b4e6506006ff 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -1695,6 +1695,9 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Vous pouvez dupliquer jusqu’à ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} dépenses à la fois. Veuillez sélectionner moins de dépenses et réessayer.`, deleted: 'Supprimé', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} au ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `Valide à partir du ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `Valide jusqu’au ${endDate}`, }, transactionMerge: { listPage: { @@ -9446,6 +9449,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e scanTestDriveTooltip: 'Envoyez ce reçu pour\nterminer l’essai !', gpsTooltip: 'Suivi GPS en cours ! Lorsque vous avez terminé, arrêtez le suivi ci-dessous.', hasFilterNegation: 'Recherchez les dépenses sans reçus à l’aide de -has:receipt.', + mileageRateAutoUpdated: 'Nous avons mis à jour le taux en fonction de votre date de voyage.', }, discardChangesConfirmation: { title: 'Ignorer les modifications ?', diff --git a/src/languages/it.ts b/src/languages/it.ts index 16c336b978b3..78cd4ebbd84d 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -1687,6 +1687,9 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Puoi duplicare fino a ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} spese alla volta. Seleziona meno spese e riprova.`, deleted: 'Eliminato', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `dal ${startDate} al ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `Valido dal ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `Valido fino al ${endDate}`, }, transactionMerge: { listPage: { @@ -9402,6 +9405,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`, scanTestDriveTooltip: 'Invia questa ricevuta per\ncompletare il test drive!', gpsTooltip: 'Tracciamento GPS in corso! Quando hai finito, interrompi il tracciamento qui sotto.', hasFilterNegation: 'Cerca le spese senza ricevute usando -has:receipt.', + mileageRateAutoUpdated: 'Abbiamo aggiornato il tasso in base alla tua data di viaggio.', }, discardChangesConfirmation: { title: 'Scartare le modifiche?', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 2b1a926f2547..b399d6bb21ca 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -1667,6 +1667,9 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `一度に複製できる経費は最大で ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} 件です。経費の数を減らして、もう一度お試しください。`, deleted: '削除済み', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} 〜 ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `有効期間:${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `${endDate} まで有効`, }, transactionMerge: { listPage: { @@ -9280,6 +9283,7 @@ ${reportName} scanTestDriveTooltip: 'このレシートを送信して\n試用を完了しましょう!', gpsTooltip: 'GPS追跡を実行中です!完了したら、下で追跡を停止してください。', hasFilterNegation: '-has:receipt を使って、レシートのない経費を検索します。', + mileageRateAutoUpdated: '出張日にもとづいてレートを更新しました。', }, discardChangesConfirmation: { title: '変更を破棄しますか?', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 58c0c33708d9..e1340817da1a 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -1682,6 +1682,9 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Je kunt maximaal ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} uitgaven tegelijk dupliceren. Selecteer minder uitgaven en probeer het opnieuw.`, deleted: 'Verwijderd', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} tot ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `Geldig vanaf ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `Geldig tot ${endDate}`, }, transactionMerge: { listPage: { @@ -9369,6 +9372,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`, scanTestDriveTooltip: 'Stuur deze bon om\nde proefrit te voltooien!', gpsTooltip: 'GPS-tracking bezig! Als je klaar bent, stop dan hieronder met bijhouden.', hasFilterNegation: 'Zoek naar uitgaven zonder bonnen met -has:receipt.', + mileageRateAutoUpdated: 'We hebben het tarief bijgewerkt op basis van je reisdatum.', }, discardChangesConfirmation: { title: 'Wijzigingen negeren?', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index ae2c2b5fa0a2..bd0881395200 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -1683,6 +1683,9 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Możesz jednocześnie zduplikować maksymalnie ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} wydatków. Wybierz mniej wydatków i spróbuj ponownie.`, deleted: 'Usunięto', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} do ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `Ważne od ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `Ważne do ${endDate}`, }, transactionMerge: { listPage: { @@ -9353,6 +9356,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`, scanTestDriveTooltip: 'Wyślij ten paragon, aby\nzakończyć jazdę próbną!', gpsTooltip: 'Śledzenie GPS w toku! Gdy skończysz, zatrzymaj śledzenie poniżej.', hasFilterNegation: 'Wyszukaj wydatki bez paragonów za pomocą -has:receipt.', + mileageRateAutoUpdated: 'Zaktualizowaliśmy stawkę na podstawie daty twojej podróży.', }, discardChangesConfirmation: { title: 'Odrzucić zmiany?', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index de0e271772de..b28f257a960f 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -1680,6 +1680,9 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Você pode duplicar até ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} despesas por vez. Selecione menos despesas e tente novamente.`, deleted: 'Excluído', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} a ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `Válido a partir de ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `Válido até ${endDate}`, }, transactionMerge: { listPage: { @@ -9361,6 +9364,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`, scanTestDriveTooltip: 'Envie este recibo para\nconcluir o test drive!', gpsTooltip: 'Rastreamento por GPS em andamento! Quando terminar, pare o rastreamento abaixo.', hasFilterNegation: 'Pesquise despesas sem recibos usando -has:receipt.', + mileageRateAutoUpdated: 'Nós atualizamos a taxa com base na sua data de viagem.', }, discardChangesConfirmation: { title: 'Descartar alterações?', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 1df8087de864..4cb40f2a46a1 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -1628,6 +1628,9 @@ const translations: TranslationDeepObject = { taxDisabledAlert: {title: '税费已禁用', prompt: '请在工作区中启用税费跟踪,以便编辑此报销的详细信息或从该报销中删除税费。', confirmText: '删除税费'}, bulkDuplicateLimit: `您一次最多可以复制 ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} 笔报销。请减少选择的报销数量后重试。`, deleted: '已删除', + rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} 至 ${endDate}`, + rateValidFrom: ({startDate}: {startDate: string}) => `有效期自 ${startDate}`, + rateValidUntil: ({endDate}: {endDate: string}) => `有效期至 ${endDate}`, }, transactionMerge: { listPage: { @@ -9108,6 +9111,7 @@ ${reportName} scanTestDriveTooltip: '发送此收据以\n完成试用体验!', gpsTooltip: '正在进行 GPS 跟踪!完成后,请在下方停止跟踪。', hasFilterNegation: '使用 -has:receipt 搜索没有收据的报销。', + mileageRateAutoUpdated: '我们已根据您的出行日期更新了汇率。', }, discardChangesConfirmation: { title: '放弃更改?', From a2ddca225deb0c231df0ab6454f9c43b2cd8f5e8 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 14:00:05 +0530 Subject: [PATCH 10/18] fix prettier. Signed-off-by: krishna2323 --- .../DistanceRequestController.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx b/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx index d96c5e45403e..0b01b27e66f9 100644 --- a/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx +++ b/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx @@ -188,7 +188,18 @@ function DistanceRequestController({ } } setCustomUnitRateID(transactionID, rateToUse, transaction, policy); - }, [customUnitRateID, transactionID, lastSelectedRate, isDistanceRequest, isPolicyExpenseChat, isMovingTransactionFromTrackExpense, transaction, policy, selectedParticipants, defaultMileageRateCustomUnitRateID]); + }, [ + customUnitRateID, + transactionID, + lastSelectedRate, + isDistanceRequest, + isPolicyExpenseChat, + isMovingTransactionFromTrackExpense, + transaction, + policy, + selectedParticipants, + defaultMileageRateCustomUnitRateID, + ]); useEffect(() => { if (!isDistanceRequest || !transactionID || isReadOnly) { From 5c57e41c9595ac874352654563a5e2dfd22e4da2 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 18:01:52 +0530 Subject: [PATCH 11/18] address Codex review for tooltip and rate list display Signed-off-by: krishna2323 --- src/components/MoneyRequestConfirmationList.tsx | 13 ++++++++++++- .../iou/request/step/IOURequestStepDistanceRate.tsx | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 0ef97977223e..f0ceb8bfa55f 100644 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -258,14 +258,25 @@ function MoneyRequestConfirmationList({ const prevCreated = usePrevious(transaction?.created); const prevRateID = usePrevious(customUnitRateID); + const [pendingDateChange, setPendingDateChange] = useState(false); const [shouldShowRateAutoUpdatedTooltip, setShouldShowRateAutoUpdatedTooltip] = useState(false); const dateChanged = prevCreated !== undefined && prevCreated !== transaction?.created; const rateChanged = prevRateID !== undefined && prevRateID !== customUnitRateID; + + if (dateChanged && !pendingDateChange) { + setPendingDateChange(true); + } + if (dateChanged || rateChanged) { - const newShouldShow = isDistanceRequest && dateChanged && rateChanged; + const newShouldShow = isDistanceRequest && rateChanged && (dateChanged || pendingDateChange); + if (newShouldShow && pendingDateChange) { + setPendingDateChange(false); + } if (newShouldShow !== shouldShowRateAutoUpdatedTooltip) { setShouldShowRateAutoUpdatedTooltip(newShouldShow); } + } else if (pendingDateChange) { + setPendingDateChange(false); } const subRates = transaction?.comment?.customUnit?.subRates ?? []; diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 125bbecfc5ed..1556f97f32c4 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -138,7 +138,8 @@ function IOURequestStepDistanceRate({ : DistanceRequestUtils.getDefaultMileageRate(policy)?.customUnitRateID === rate.customUnitRateID; const rateForDisplay = DistanceRequestUtils.getFormattedRateValue(unit, rate.rate, isSelected ? transactionCurrency : rate.currency, translate, toLocaleDigit, getCurrencySymbol); const dateLabel = DistanceRequestUtils.getRateDateLabel(rate, translate); - const alternateText = dateLabel ? [rateForDisplay, dateLabel].filter(Boolean).join(' • ') : rateForDisplay; + const alternateTextWithoutDate = rate.name ? rateForDisplay : ''; + const alternateText = dateLabel ? [rateForDisplay, dateLabel].filter(Boolean).join(' • ') : alternateTextWithoutDate; return { text: rate.name ?? rateForDisplay, alternateText, From 229bb5c4c875db3f356655108f12f530735e568f Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 18:20:13 +0530 Subject: [PATCH 12/18] fix: prevent tooltip render loop and unnamed rate duplicate Signed-off-by: krishna2323 --- src/components/MoneyRequestConfirmationList.tsx | 4 ++-- src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index f0ceb8bfa55f..e923e43fc09e 100644 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -263,13 +263,13 @@ function MoneyRequestConfirmationList({ const dateChanged = prevCreated !== undefined && prevCreated !== transaction?.created; const rateChanged = prevRateID !== undefined && prevRateID !== customUnitRateID; - if (dateChanged && !pendingDateChange) { + if (dateChanged && !rateChanged && !pendingDateChange) { setPendingDateChange(true); } if (dateChanged || rateChanged) { const newShouldShow = isDistanceRequest && rateChanged && (dateChanged || pendingDateChange); - if (newShouldShow && pendingDateChange) { + if (newShouldShow && pendingDateChange && !dateChanged) { setPendingDateChange(false); } if (newShouldShow !== shouldShowRateAutoUpdatedTooltip) { diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 1556f97f32c4..e6b3bc53dd7e 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -139,7 +139,10 @@ function IOURequestStepDistanceRate({ const rateForDisplay = DistanceRequestUtils.getFormattedRateValue(unit, rate.rate, isSelected ? transactionCurrency : rate.currency, translate, toLocaleDigit, getCurrencySymbol); const dateLabel = DistanceRequestUtils.getRateDateLabel(rate, translate); const alternateTextWithoutDate = rate.name ? rateForDisplay : ''; - const alternateText = dateLabel ? [rateForDisplay, dateLabel].filter(Boolean).join(' • ') : alternateTextWithoutDate; + let alternateText = alternateTextWithoutDate; + if (dateLabel) { + alternateText = rate.name ? [rateForDisplay, dateLabel].filter(Boolean).join(' • ') : dateLabel; + } return { text: rate.name ?? rateForDisplay, alternateText, From 6d4c6e279398ccea77b64bb466d93a53cc88c71f Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 8 Jun 2026 19:21:52 +0530 Subject: [PATCH 13/18] hide tooltip on scroll. Signed-off-by: krishna2323 --- .../MoneyRequestConfirmationList/sections/RateField.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx index 820c3945f36a..67e79746da1f 100644 --- a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx +++ b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx @@ -115,6 +115,7 @@ function RateField({ tooltipShiftHorizontal={variables.mileageRateTooltipShiftHorizontal} tooltipShiftVertical={variables.mileageRateTooltipShiftVertical} onEducationTooltipPress={hideProductTrainingTooltip} + shouldHideOnScroll /> ); } From 70a5daf9b33661f1a05a032e4af574e786cde17b Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 10 Jun 2026 00:00:59 +0530 Subject: [PATCH 14/18] address review comment. Signed-off-by: krishna2323 --- .../MoneyRequestConfirmationList.tsx | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 90c5f2a1d9a8..6217717c846a 100644 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -258,26 +258,30 @@ function MoneyRequestConfirmationList({ const prevCreated = usePrevious(transaction?.created); const prevRateID = usePrevious(customUnitRateID); - const [pendingDateChange, setPendingDateChange] = useState(false); + const pendingDateChangeRef = useRef(false); const [shouldShowRateAutoUpdatedTooltip, setShouldShowRateAutoUpdatedTooltip] = useState(false); - const dateChanged = prevCreated !== undefined && prevCreated !== transaction?.created; - const rateChanged = prevRateID !== undefined && prevRateID !== customUnitRateID; - if (dateChanged && !rateChanged && !pendingDateChange) { - setPendingDateChange(true); - } + useEffect(() => { + if (!isDistanceRequest) { + return; + } + + const dateJustChanged = prevCreated !== undefined && prevCreated !== transaction?.created; + const rateJustChanged = prevRateID !== undefined && prevRateID !== customUnitRateID; - if (dateChanged || rateChanged) { - const newShouldShow = isDistanceRequest && rateChanged && (dateChanged || pendingDateChange); - if (newShouldShow && pendingDateChange && !dateChanged) { - setPendingDateChange(false); + if (dateJustChanged && !rateJustChanged) { + pendingDateChangeRef.current = true; + return; } - if (newShouldShow !== shouldShowRateAutoUpdatedTooltip) { - setShouldShowRateAutoUpdatedTooltip(newShouldShow); + + if (rateJustChanged) { + const wasDateTriggered = dateJustChanged || pendingDateChangeRef.current; + pendingDateChangeRef.current = false; + if (wasDateTriggered) { + setShouldShowRateAutoUpdatedTooltip(true); + } } - } else if (pendingDateChange) { - setPendingDateChange(false); - } + }, [isDistanceRequest, prevCreated, prevRateID, transaction?.created, customUnitRateID]); const subRates = transaction?.comment?.customUnit?.subRates ?? []; const prevSubRates = usePrevious(subRates); From 44ea7f3ed8bb85df05387f026424693513795ecb Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 10 Jun 2026 02:01:50 +0530 Subject: [PATCH 15/18] fix: signal rate auto-update via Onyx flag instead of render-phase tracking Signed-off-by: krishna2323 --- .../MoneyRequestConfirmationList.tsx | 27 +------------------ src/libs/actions/IOU/MoneyRequest.ts | 4 ++- .../iou/request/step/IOURequestStepDate.tsx | 3 ++- src/types/onyx/Transaction.ts | 3 +++ 4 files changed, 9 insertions(+), 28 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 6217717c846a..89f825bbe90e 100644 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -256,32 +256,7 @@ function MoneyRequestConfirmationList({ const previousTransactionCurrency = usePrevious(transaction?.currency); const customUnitRateID = getRateID(transaction); - const prevCreated = usePrevious(transaction?.created); - const prevRateID = usePrevious(customUnitRateID); - const pendingDateChangeRef = useRef(false); - const [shouldShowRateAutoUpdatedTooltip, setShouldShowRateAutoUpdatedTooltip] = useState(false); - - useEffect(() => { - if (!isDistanceRequest) { - return; - } - - const dateJustChanged = prevCreated !== undefined && prevCreated !== transaction?.created; - const rateJustChanged = prevRateID !== undefined && prevRateID !== customUnitRateID; - - if (dateJustChanged && !rateJustChanged) { - pendingDateChangeRef.current = true; - return; - } - - if (rateJustChanged) { - const wasDateTriggered = dateJustChanged || pendingDateChangeRef.current; - pendingDateChangeRef.current = false; - if (wasDateTriggered) { - setShouldShowRateAutoUpdatedTooltip(true); - } - } - }, [isDistanceRequest, prevCreated, prevRateID, transaction?.created, customUnitRateID]); + const shouldShowRateAutoUpdatedTooltip = isDistanceRequest && !!transaction?.comment?.customUnit?.rateAutoUpdated; const subRates = transaction?.comment?.customUnit?.subRates ?? []; const prevSubRates = usePrevious(subRates); diff --git a/src/libs/actions/IOU/MoneyRequest.ts b/src/libs/actions/IOU/MoneyRequest.ts index 27a1fcebba6a..2b70b63cf287 100644 --- a/src/libs/actions/IOU/MoneyRequest.ts +++ b/src/libs/actions/IOU/MoneyRequest.ts @@ -609,7 +609,7 @@ function setMoneyRequestTimeCount(transactionID: string, count: number, isDraft: * if passed transaction previously had it to make sure that transaction does not have inconsistent * states (for example distanceUnit not matching distance unit of the new customUnitRateID) */ -function setCustomUnitRateID(transactionID: string, customUnitRateID: string | undefined, transaction: OnyxEntry, policy: OnyxEntry) { +function setCustomUnitRateID(transactionID: string, customUnitRateID: string | undefined, transaction: OnyxEntry, policy: OnyxEntry, rateAutoUpdated = false) { const isFakeP2PRate = customUnitRateID === CONST.CUSTOM_UNITS.FAKE_P2P_ID; let newDistanceUnit: Unit | undefined; @@ -646,6 +646,7 @@ function setCustomUnitRateID(transactionID: string, customUnitRateID: string | u ...(!isFakeP2PRate && {defaultP2PRate: null}), distanceUnit: newDistanceUnit, quantity: newQuantity, + rateAutoUpdated, }, }, }); @@ -727,6 +728,7 @@ function setMoneyRequestDistanceRate(currentTransaction: OnyxEntry, ...(!!policy && {defaultP2PRate: null}), ...(newDistanceUnit && {distanceUnit: newDistanceUnit}), ...(newDistance && {quantity: newDistance}), + rateAutoUpdated: false, }, }, }); diff --git a/src/pages/iou/request/step/IOURequestStepDate.tsx b/src/pages/iou/request/step/IOURequestStepDate.tsx index ff0606010102..bae93cf06184 100644 --- a/src/pages/iou/request/step/IOURequestStepDate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDate.tsx @@ -134,7 +134,8 @@ function IOURequestStepDate({ isTrackDistanceExpense: isTrackExpense, expenseDate: newCreated, }); - setCustomUnitRateID(transactionID, rateID, transaction, effectivePolicy); + const currentRateID = transaction?.comment?.customUnit?.customUnitRateID; + setCustomUnitRateID(transactionID, rateID, transaction, effectivePolicy, rateID !== currentRateID); } } diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index c43e09063466..d77e296e680b 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -189,6 +189,9 @@ type TransactionCustomUnit = { /** The unit for the distance/quantity */ distanceUnit?: Unit; + /** Whether the rate was auto-updated due to a date change (used for tooltip display) */ + rateAutoUpdated?: boolean; + /** * The distance in meters from the route Mapbox or Google Maps chose through the user supplied waypoints. * It is used to track when the user has manually increased the distance above the system-calculated route distance. From 4358237d662cea794076812b70b70c647f491a6b Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 10 Jun 2026 03:17:19 +0530 Subject: [PATCH 16/18] fix lint errors. Signed-off-by: krishna2323 --- src/libs/DebugUtils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/DebugUtils.ts b/src/libs/DebugUtils.ts index baaf409bff38..901c774b39bc 100644 --- a/src/libs/DebugUtils.ts +++ b/src/libs/DebugUtils.ts @@ -1069,6 +1069,7 @@ function validateTransactionDraftProperty(key: keyof Transaction, value: string) name: CONST.RED_BRICK_ROAD_PENDING_ACTION, defaultP2PRate: CONST.RED_BRICK_ROAD_PENDING_ACTION, distanceUnit: CONST.RED_BRICK_ROAD_PENDING_ACTION, + rateAutoUpdated: CONST.RED_BRICK_ROAD_PENDING_ACTION, odometerStart: CONST.RED_BRICK_ROAD_PENDING_ACTION, odometerEnd: CONST.RED_BRICK_ROAD_PENDING_ACTION, odometerStartImage: CONST.RED_BRICK_ROAD_PENDING_ACTION, From 0bcf63a962240594768543321a4d3122ec26cea1 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Fri, 12 Jun 2026 19:21:59 +0530 Subject: [PATCH 17/18] Simplify alternateText construction for distance rate options Signed-off-by: krishna2323 --- src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index b085195cf3b5..2f3fceaf60d6 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -141,11 +141,7 @@ function IOURequestStepDistanceRate({ : DistanceRequestUtils.getDefaultMileageRate(policy)?.customUnitRateID === rate.customUnitRateID; const rateForDisplay = DistanceRequestUtils.getFormattedRateValue(unit, rate.rate, isSelected ? transactionCurrency : rate.currency, translate, toLocaleDigit, getCurrencySymbol); const dateLabel = DistanceRequestUtils.getRateDateLabel(rate, translate); - const alternateTextWithoutDate = rate.name ? rateForDisplay : ''; - let alternateText = alternateTextWithoutDate; - if (dateLabel) { - alternateText = rate.name ? [rateForDisplay, dateLabel].filter(Boolean).join(' • ') : dateLabel; - } + const alternateText = [rate.name ? rateForDisplay : '', dateLabel].filter(Boolean).join(' • '); return { text: rate.name ?? rateForDisplay, alternateText, From 08eccad0ba85e6d7d9e7c5db6040d34b0907c7d1 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Fri, 12 Jun 2026 21:15:25 +0530 Subject: [PATCH 18/18] Remove duplicate translation entries for rateValid keys Signed-off-by: krishna2323 --- src/languages/de.ts | 3 --- src/languages/es.ts | 3 --- src/languages/fr.ts | 3 --- src/languages/it.ts | 3 --- src/languages/ja.ts | 3 --- src/languages/nl.ts | 3 --- src/languages/pl.ts | 3 --- src/languages/pt-BR.ts | 3 --- src/languages/zh-hans.ts | 3 --- 9 files changed, 27 deletions(-) diff --git a/src/languages/de.ts b/src/languages/de.ts index ac38be6d6a58..7f17af13fc7a 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -1706,9 +1706,6 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Sie können bis zu ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} Ausgaben gleichzeitig duplizieren. Bitte wählen Sie weniger Ausgaben aus und versuchen Sie es erneut.`, deleted: 'Gelöscht', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} bis ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `Gültig ab ${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `Gültig bis ${endDate}`, }, transactionMerge: { listPage: { diff --git a/src/languages/es.ts b/src/languages/es.ts index bf57a2d65a1d..2d0cbfa1f5ac 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1664,9 +1664,6 @@ const translations: TranslationDeepObject = { prompt: 'Habilita el seguimiento de impuestos en el espacio de trabajo para editar los detalles del gasto o eliminar el impuesto de este gasto.', confirmText: 'Eliminar impuesto', }, - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} a ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `Válido desde ${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `Válido hasta ${endDate}`, }, transactionMerge: { listPage: { diff --git a/src/languages/fr.ts b/src/languages/fr.ts index da73297f046b..f3bab8972d18 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -1711,9 +1711,6 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Vous pouvez dupliquer jusqu’à ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} dépenses à la fois. Veuillez sélectionner moins de dépenses et réessayer.`, deleted: 'Supprimé', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} au ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `Valide à partir du ${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `Valide jusqu’au ${endDate}`, }, transactionMerge: { listPage: { diff --git a/src/languages/it.ts b/src/languages/it.ts index 58dffbed4522..a4a5852f773b 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -1704,9 +1704,6 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Puoi duplicare fino a ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} spese alla volta. Seleziona meno spese e riprova.`, deleted: 'Eliminato', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `dal ${startDate} al ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `Valido dal ${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `Valido fino al ${endDate}`, }, transactionMerge: { listPage: { diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 9a0a5c3de566..9ae25d19eb92 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -1687,9 +1687,6 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `一度に複製できる経費は最大で ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} 件です。経費の数を減らして、もう一度お試しください。`, deleted: '削除済み', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} 〜 ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `有効期間:${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `${endDate} まで有効`, }, transactionMerge: { listPage: { diff --git a/src/languages/nl.ts b/src/languages/nl.ts index d8366ecd7e61..98f1cc7d8045 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -1699,9 +1699,6 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Je kunt maximaal ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} uitgaven tegelijk dupliceren. Selecteer minder uitgaven en probeer het opnieuw.`, deleted: 'Verwijderd', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} tot ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `Geldig vanaf ${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `Geldig tot ${endDate}`, }, transactionMerge: { listPage: { diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 79b0d47429ec..424f72d7f0f9 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -1700,9 +1700,6 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Możesz jednocześnie zduplikować maksymalnie ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} wydatków. Wybierz mniej wydatków i spróbuj ponownie.`, deleted: 'Usunięto', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} do ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `Ważne od ${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `Ważne do ${endDate}`, }, transactionMerge: { listPage: { diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 00ba3daebff3..30448e6ce369 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -1697,9 +1697,6 @@ const translations: TranslationDeepObject = { }, bulkDuplicateLimit: `Você pode duplicar até ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} despesas por vez. Selecione menos despesas e tente novamente.`, deleted: 'Excluído', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} a ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `Válido a partir de ${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `Válido até ${endDate}`, }, transactionMerge: { listPage: { diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 67318ff3afe1..336586a421f4 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -1648,9 +1648,6 @@ const translations: TranslationDeepObject = { taxDisabledAlert: {title: '税费已禁用', prompt: '请在工作区中启用税费跟踪,以便编辑此报销的详细信息或从该报销中删除税费。', confirmText: '删除税费'}, bulkDuplicateLimit: `您一次最多可以复制 ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} 笔报销。请减少选择的报销数量后重试。`, deleted: '已删除', - rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} 至 ${endDate}`, - rateValidFrom: ({startDate}: {startDate: string}) => `有效期自 ${startDate}`, - rateValidUntil: ({endDate}: {endDate: string}) => `有效期至 ${endDate}`, }, transactionMerge: { listPage: {