From 0823ea5505034203ab4e70529728772f9c6af660 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Mon, 16 Jun 2025 13:12:22 +0200 Subject: [PATCH 1/4] Fix computing receiver and payer for IOU transaction preview --- .../MoneyRequestReportPreview/index.tsx | 4 +- .../TransactionPreviewContent.tsx | 70 +++++++++++-------- .../TransactionPreview/index.tsx | 12 ++-- .../TransactionPreview/types.ts | 10 +-- src/libs/TransactionPreviewUtils.ts | 25 ++++--- .../MoneyRequestReportPreview.stories.tsx | 2 +- .../TransactionPreviewContent.stories.tsx | 6 +- 7 files changed, 74 insertions(+), 55 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/index.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/index.tsx index 9e8674bfcde1..d3b3064b207e 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/index.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/index.tsx @@ -64,7 +64,7 @@ function MoneyRequestReportPreview({ [StyleUtils, currentWidth, currentWrapperWidth, shouldUseNarrowLayout, transactions.length], ); - const shouldShowIOUData = useMemo(() => { + const shouldShowPayerAndReceiver = useMemo(() => { if (!isIOUReport(iouReport) && action.childType !== CONST.REPORT.TYPE.IOU) { return false; } @@ -101,7 +101,7 @@ function MoneyRequestReportPreview({ transactionID={item.transactionID} reportPreviewAction={action} onPreviewPressed={openReportFromPreview} - shouldShowIOUData={shouldShowIOUData} + shouldShowPayerAndReceiver={shouldShowPayerAndReceiver} /> ); diff --git a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx index e2474a68a911..992988fabe04 100644 --- a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx +++ b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx @@ -24,10 +24,10 @@ import {getCleanedTagName} from '@libs/PolicyUtils'; import {getThumbnailAndImageURIs} from '@libs/ReceiptUtils'; import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils'; import type {TransactionDetails} from '@libs/ReportUtils'; -import {canEditMoneyRequest, getTransactionDetails, getWorkspaceIcon, isIOUReport, isPolicyExpenseChat, isReportApproved, isSettled} from '@libs/ReportUtils'; +import {canEditMoneyRequest, getTransactionDetails, getWorkspaceIcon, isPolicyExpenseChat, isReportApproved, isSettled} from '@libs/ReportUtils'; import StringUtils from '@libs/StringUtils'; import type {TranslationPathOrText} from '@libs/TransactionPreviewUtils'; -import {createTransactionPreviewConditionals, getIOUData, getTransactionPreviewTextAndTranslationPaths} from '@libs/TransactionPreviewUtils'; +import {createTransactionPreviewConditionals, getIOUPayerAndReceiver, getTransactionPreviewTextAndTranslationPaths} from '@libs/TransactionPreviewUtils'; import {isScanning} from '@libs/TransactionUtils'; import ViolationsUtils from '@libs/Violations/ViolationsUtils'; import variables from '@styles/variables'; @@ -41,7 +41,7 @@ function TransactionPreviewContent({ isHovered, chatReport, personalDetails, - iouReport, + report, transaction, violations, offlineWithFeedbackOnClose, @@ -53,7 +53,7 @@ function TransactionPreviewContent({ walletTermsErrors, reportPreviewAction, shouldHideOnDelete = true, - shouldShowIOUData, + shouldShowPayerAndReceiver, navigateToReviewFields, isReviewDuplicateTransactionPage = false, }: TransactionPreviewContentProps) { @@ -61,24 +61,25 @@ function TransactionPreviewContent({ const styles = useThemeStyles(); const {translate} = useLocalize(); - const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${iouReport?.policyID}`, {canBeMissing: true}); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`, {canBeMissing: true}); const transactionDetails = useMemo>(() => getTransactionDetails(transaction, undefined, policy) ?? {}, [transaction, policy]); - const managerID = iouReport?.managerID ?? reportPreviewAction?.childManagerAccountID ?? CONST.DEFAULT_NUMBER_ID; - const ownerAccountID = iouReport?.ownerAccountID ?? reportPreviewAction?.childOwnerAccountID ?? CONST.DEFAULT_NUMBER_ID; + const {amount, comment: requestComment, merchant, tag, category, currency: requestCurrency} = transactionDetails; + + const managerID = report?.managerID ?? reportPreviewAction?.childManagerAccountID ?? CONST.DEFAULT_NUMBER_ID; + const ownerAccountID = report?.ownerAccountID ?? reportPreviewAction?.childOwnerAccountID ?? CONST.DEFAULT_NUMBER_ID; const isReportAPolicyExpenseChat = isPolicyExpenseChat(chatReport); - const {amount: requestAmount, comment: requestComment, merchant, tag, category, currency: requestCurrency} = transactionDetails; - const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(iouReport?.reportID)}`, {canBeMissing: true}); + const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(report?.reportID)}`, {canBeMissing: true}); const transactionPreviewCommonArguments = useMemo( () => ({ - iouReport, + iouReport: report, transaction, action, isBillSplit, violations, transactionDetails, }), - [action, iouReport, isBillSplit, transaction, transactionDetails, violations], + [action, report, isBillSplit, transaction, transactionDetails, violations], ); const conditionals = useMemo( @@ -118,19 +119,15 @@ function TransactionPreviewContent({ const displayAmountText = getTranslatedText(previewText.displayAmountText); const displayDeleteAmountText = getTranslatedText(previewText.displayDeleteAmountText); - const iouData = shouldShowIOUData - ? getIOUData(managerID, ownerAccountID, isIOUReport(iouReport) || reportPreviewAction?.childType === CONST.REPORT.TYPE.IOU, personalDetails, requestAmount ?? 0) - : undefined; - const {from, to} = iouData ?? {from: null, to: null}; const isDeleted = action?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || transaction?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; const shouldShowCategoryOrTag = shouldShowCategory || shouldShowTag; const shouldShowMerchantOrDescription = shouldShowDescription || shouldShowMerchant; - const shouldShowIOUHeader = !!from && !!to; + const description = truncate(StringUtils.lineBreaksToSpaces(Parser.htmlToText(requestComment ?? '')), {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); const requestMerchant = truncate(merchant, {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); - const isApproved = isReportApproved({report: iouReport}); - const isIOUSettled = isSettled(iouReport?.reportID); - const isSettlementOrApprovalPartial = !!iouReport?.pendingFields?.partial; + const isApproved = isReportApproved({report}); + const isIOUSettled = isSettled(report?.reportID); + const isSettlementOrApprovalPartial = !!report?.pendingFields?.partial; const isTransactionScanning = isScanning(transaction); const displayAmount = isDeleted ? displayDeleteAmountText : displayAmountText; const receiptImages = [{...getThumbnailAndImageURIs(transaction), transaction}]; @@ -142,23 +139,36 @@ function TransactionPreviewContent({ sortedParticipantAvatars.push(getWorkspaceIcon(chatReport)); } + // Compute the from/to data only for IOU reports + const {from, to} = useMemo(() => { + if (!shouldShowPayerAndReceiver) { + return { + from: undefined, + to: undefined, + }; + } + + // For IOU, we want the unprocessed amount, because it is important whether the amount was positive or negative + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const transactionRawAmount = (transaction?.modifiedAmount || transaction?.amount) ?? 0; + const payerAndReceiver = getIOUPayerAndReceiver(managerID, ownerAccountID, personalDetails, transactionRawAmount); + + return { + from: payerAndReceiver.from, + to: payerAndReceiver.to, + }; + }, [managerID, ownerAccountID, personalDetails, shouldShowPayerAndReceiver, transaction?.amount, transaction?.modifiedAmount]); + + const shouldShowIOUHeader = !!from && !!to; + // If available, retrieve the split share from the splits object of the transaction, if not, display an even share. const splitShare = useMemo( () => shouldShowSplitShare ? (transaction?.comment?.splits?.find((split) => split.accountID === sessionAccountID)?.amount ?? - calculateAmount(isReportAPolicyExpenseChat ? 1 : participantAccountIDs.length - 1, requestAmount ?? 0, requestCurrency ?? '', action?.actorAccountID === sessionAccountID)) + calculateAmount(isReportAPolicyExpenseChat ? 1 : participantAccountIDs.length - 1, amount ?? 0, requestCurrency ?? '', action?.actorAccountID === sessionAccountID)) : 0, - [ - shouldShowSplitShare, - isReportAPolicyExpenseChat, - action?.actorAccountID, - participantAccountIDs.length, - transaction?.comment?.splits, - requestAmount, - requestCurrency, - sessionAccountID, - ], + [shouldShowSplitShare, isReportAPolicyExpenseChat, action?.actorAccountID, participantAccountIDs.length, transaction?.comment?.splits, amount, requestCurrency, sessionAccountID], ); const shouldWrapDisplayAmount = !(isBillSplit || shouldShowMerchantOrDescription || isTransactionScanning); diff --git a/src/components/ReportActionItem/TransactionPreview/index.tsx b/src/components/ReportActionItem/TransactionPreview/index.tsx index 4590fa3d0002..795e065180da 100644 --- a/src/components/ReportActionItem/TransactionPreview/index.tsx +++ b/src/components/ReportActionItem/TransactionPreview/index.tsx @@ -41,9 +41,9 @@ function TransactionPreview(props: TransactionPreviewProps) { contextAction, } = props; - const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, {canBeMissing: true}); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, {canBeMissing: true}); const route = useRoute>(); - const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params?.threadReportID}`, {canBeMissing: true}); + const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params?.threadReportID}`, {canBeMissing: true}); const isMoneyRequestAction = isMoneyRequestActionReportActionsUtils(action); const transactionID = transactionIDFromProps ?? (isMoneyRequestAction ? getOriginalMessage(action)?.IOUTransactionID : null); const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {canBeMissing: true}); @@ -75,8 +75,8 @@ function TransactionPreview(props: TransactionPreviewProps) { }, [chatReportID]); const navigateToReviewFields = useCallback(() => { - Navigation.navigate(getReviewNavigationRoute(route, report, transaction, duplicates)); - }, [duplicates, report, route, transaction]); + Navigation.navigate(getReviewNavigationRoute(route, transactionThreadReport, transaction, duplicates)); + }, [duplicates, transactionThreadReport, route, transaction]); let transactionPreview = transaction; @@ -112,7 +112,7 @@ function TransactionPreview(props: TransactionPreviewProps) { chatReport={chatReport} personalDetails={personalDetails} transaction={transactionPreview} - iouReport={iouReport} + report={report} violations={violations} offlineWithFeedbackOnClose={offlineWithFeedbackOnClose} navigateToReviewFields={navigateToReviewFields} @@ -135,7 +135,7 @@ function TransactionPreview(props: TransactionPreviewProps) { chatReport={chatReport} personalDetails={personalDetails} transaction={originalTransaction} - iouReport={iouReport} + report={report} violations={violations} offlineWithFeedbackOnClose={offlineWithFeedbackOnClose} navigateToReviewFields={navigateToReviewFields} diff --git a/src/components/ReportActionItem/TransactionPreview/types.ts b/src/components/ReportActionItem/TransactionPreview/types.ts index f2f911d26995..03de9f6c6616 100644 --- a/src/components/ReportActionItem/TransactionPreview/types.ts +++ b/src/components/ReportActionItem/TransactionPreview/types.ts @@ -11,7 +11,7 @@ type TransactionPreviewStyleType = { }; type TransactionPreviewProps = { - /** The active IOUReport, used for Onyx subscription */ + /** The active reportID linked to the transaction */ iouReportID: string | undefined; /** The associated chatReport */ @@ -65,7 +65,7 @@ type TransactionPreviewProps = { reportPreviewAction?: ReportAction; /** Whether to show payer/receiver data in the preview */ - shouldShowIOUData?: boolean; + shouldShowPayerAndReceiver?: boolean; /** In case we want to override context menu action */ contextAction?: OnyxEntry; @@ -93,8 +93,8 @@ type TransactionPreviewContentProps = { /** Records any errors related to wallet terms. */ walletTermsErrors: Errors | undefined; - /** Represents the IOU report entry from Onyx */ - iouReport: OnyxEntry; + /** Represents the report linked to the transaction */ + report: OnyxEntry; /** Flag to determine if a transaction involves a bill split among multiple parties. */ isBillSplit: boolean; @@ -130,7 +130,7 @@ type TransactionPreviewContentProps = { reportPreviewAction?: ReportAction; /** Whether to show payer/receiver data in the preview */ - shouldShowIOUData?: boolean; + shouldShowPayerAndReceiver?: boolean; /** Is this component used during duplicate review flow */ isReviewDuplicateTransactionPage?: boolean; diff --git a/src/libs/TransactionPreviewUtils.ts b/src/libs/TransactionPreviewUtils.ts index b4ba1e71f866..7300a4a7858b 100644 --- a/src/libs/TransactionPreviewUtils.ts +++ b/src/libs/TransactionPreviewUtils.ts @@ -42,7 +42,11 @@ const emptyPersonalDetails: OnyxTypes.PersonalDetails = { login: undefined, }; -function getIOUData(managerID: number, ownerAccountID: number, isIOUReport: boolean, personalDetails: OnyxTypes.PersonalDetailsList | undefined, amount: number) { +/** + * Returns the data for displaying payer and receiver (`from` and `to`) values for given ids and amount. + * In IOU transactions we can deduce who is the payer and receiver based on sign (positive/negative) of the amount. + */ +function getIOUPayerAndReceiver(managerID: number, ownerAccountID: number, personalDetails: OnyxTypes.PersonalDetailsList | undefined, amount: number) { let fromID = ownerAccountID; let toID = managerID; @@ -51,12 +55,10 @@ function getIOUData(managerID: number, ownerAccountID: number, isIOUReport: bool toID = ownerAccountID; } - return fromID && toID && isIOUReport - ? { - from: personalDetails ? personalDetails[fromID] : emptyPersonalDetails, - to: personalDetails ? personalDetails[toID] : emptyPersonalDetails, - } - : undefined; + return { + from: personalDetails ? personalDetails[fromID] : emptyPersonalDetails, + to: personalDetails ? personalDetails[toID] : emptyPersonalDetails, + }; } const getReviewNavigationRoute = ( @@ -344,5 +346,12 @@ function createTransactionPreviewConditionals({ }; } -export {getReviewNavigationRoute, getIOUData, getTransactionPreviewTextAndTranslationPaths, createTransactionPreviewConditionals, getViolationTranslatePath, getUniqueActionErrors}; +export { + getReviewNavigationRoute, + getIOUPayerAndReceiver, + getTransactionPreviewTextAndTranslationPaths, + createTransactionPreviewConditionals, + getViolationTranslatePath, + getUniqueActionErrors, +}; export type {TranslationPathOrText}; diff --git a/src/stories/MoneyRequestReportPreview.stories.tsx b/src/stories/MoneyRequestReportPreview.stories.tsx index 4ddcdfa467bb..233405102197 100644 --- a/src/stories/MoneyRequestReportPreview.stories.tsx +++ b/src/stories/MoneyRequestReportPreview.stories.tsx @@ -41,7 +41,7 @@ const mockRenderItem: ListRenderItem = ({item}) => ( isHovered={false} chatReport={chatReportR14932} personalDetails={personalDetails} - iouReport={iouReportR14932} + report={iouReportR14932} transaction={item} violations={item.errors ? violationsR14932 : []} offlineWithFeedbackOnClose={() => undefined} diff --git a/src/stories/TransactionPreviewContent.stories.tsx b/src/stories/TransactionPreviewContent.stories.tsx index dec9767558ef..30853d8c5b84 100644 --- a/src/stories/TransactionPreviewContent.stories.tsx +++ b/src/stories/TransactionPreviewContent.stories.tsx @@ -102,7 +102,7 @@ const story: Meta = { isHovered: false, chatReport: chatReportR14932, personalDetails, - iouReport: iouReportR14932, + report: iouReportR14932, transaction: transactionR14932, violations: [], offlineWithFeedbackOnClose(): void {}, @@ -118,7 +118,7 @@ const story: Meta = { }, argTypes: { ...disabledProperties, - iouReport: generateArgTypes(iouReportMap), + report: generateArgTypes(iouReportMap), transaction: generateArgTypes(transactionsMap), violations: generateArgTypes(violationsMap), action: generateArgTypes(actionMap), @@ -179,7 +179,7 @@ KeepButtonSplitRBRCategoriesAndTag.args = { KeepButtonIOURbrCategoriesAndTag.args = { ...KeepButtonRBRCategoriesAndTag.args, - iouReport: iouReportWithModifiedType(CONST.REPORT.TYPE.IOU), + report: iouReportWithModifiedType(CONST.REPORT.TYPE.IOU), }; DeletedKeepButtonSplitRBRCategoriesAndTag.args = { From 7204740723317f649aca35d07b37760f853db0b9 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Mon, 16 Jun 2025 14:11:36 +0200 Subject: [PATCH 2/4] Remove unneeded TransactionUtils storybook mock --- .storybook/webpackMockPaths.ts | 1 - .../TransactionPreviewContent.tsx | 2 +- src/libs/__mocks__/TransactionPreviewUtils.ts | 40 ------------------- 3 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 src/libs/__mocks__/TransactionPreviewUtils.ts diff --git a/.storybook/webpackMockPaths.ts b/.storybook/webpackMockPaths.ts index 78a6b8dbda90..ee142a684013 100644 --- a/.storybook/webpackMockPaths.ts +++ b/.storybook/webpackMockPaths.ts @@ -6,6 +6,5 @@ export default { 'react-native$': 'react-native-web', '@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.ts'), '@react-navigation/native': path.resolve(__dirname, '../__mocks__/@react-navigation/native'), - '@libs/TransactionPreviewUtils': path.resolve(__dirname, '../src/libs/__mocks__/TransactionPreviewUtils.ts'), }; /* eslint-enable @typescript-eslint/naming-convention */ diff --git a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx index 992988fabe04..1a43ea278ecd 100644 --- a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx +++ b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx @@ -148,7 +148,7 @@ function TransactionPreviewContent({ }; } - // For IOU, we want the unprocessed amount, because it is important whether the amount was positive or negative + // For IOU, we want the unprocessed amount because it is important whether the amount was positive or negative // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const transactionRawAmount = (transaction?.modifiedAmount || transaction?.amount) ?? 0; const payerAndReceiver = getIOUPayerAndReceiver(managerID, ownerAccountID, personalDetails, transactionRawAmount); diff --git a/src/libs/__mocks__/TransactionPreviewUtils.ts b/src/libs/__mocks__/TransactionPreviewUtils.ts deleted file mode 100644 index b4d6662ae05b..000000000000 --- a/src/libs/__mocks__/TransactionPreviewUtils.ts +++ /dev/null @@ -1,40 +0,0 @@ -import CONST from '@src/CONST'; -import type * as OnyxTypes from '@src/types/onyx'; - -const chooseIdBasedOnAmount = (amount: number, negativeId: number, positiveId: number) => (amount < 0 ? negativeId : positiveId); - -const emptyPersonalDetails: OnyxTypes.PersonalDetails = { - accountID: CONST.REPORT.OWNER_ACCOUNT_ID_FAKE, - avatar: '', - displayName: undefined, - login: undefined, -}; - -function getIOUData( - managerID: number, - ownerAccountID: number, - reportOrID: OnyxTypes.OnyxInputOrEntry | string | undefined, - personalDetails: OnyxTypes.PersonalDetailsList | undefined, - amount: number, -) { - const fromID = chooseIdBasedOnAmount(amount, managerID, ownerAccountID); - const toID = chooseIdBasedOnAmount(amount, ownerAccountID, managerID); - - const from = personalDetails ? personalDetails[fromID] : emptyPersonalDetails; - const to = personalDetails ? personalDetails[toID] : emptyPersonalDetails; - - if (reportOrID && (typeof reportOrID === 'string' || reportOrID.type === CONST.REPORT.TYPE.IOU)) { - return {from, to}; - } - - return undefined; -} - -export { - getTransactionPreviewTextAndTranslationPaths, - createTransactionPreviewConditionals, - getReviewNavigationRoute, - getViolationTranslatePath, - getUniqueActionErrors, -} from '../TransactionPreviewUtils'; -export {getIOUData}; From b6c9fcee7b1e26d7fea491be41262d51034623c8 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Wed, 25 Jun 2025 13:31:04 +0200 Subject: [PATCH 3/4] Fix displaying sender/receiver for split money request preview --- .../TransactionPreview/TransactionPreviewContent.tsx | 7 +++---- .../ReportActionItem/TransactionPreview/index.tsx | 6 ++++++ .../ReportActionItem/TransactionPreview/types.ts | 4 ++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx index 1a43ea278ecd..7afb85b1a567 100644 --- a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx +++ b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx @@ -44,6 +44,7 @@ function TransactionPreviewContent({ report, transaction, violations, + transactionRawAmount, offlineWithFeedbackOnClose, containerStyles, transactionPreviewWidth, @@ -148,16 +149,14 @@ function TransactionPreviewContent({ }; } - // For IOU, we want the unprocessed amount because it is important whether the amount was positive or negative - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const transactionRawAmount = (transaction?.modifiedAmount || transaction?.amount) ?? 0; + // For IOU or Split, we want the unprocessed amount because it is important whether the amount was positive or negative const payerAndReceiver = getIOUPayerAndReceiver(managerID, ownerAccountID, personalDetails, transactionRawAmount); return { from: payerAndReceiver.from, to: payerAndReceiver.to, }; - }, [managerID, ownerAccountID, personalDetails, shouldShowPayerAndReceiver, transaction?.amount, transaction?.modifiedAmount]); + }, [managerID, ownerAccountID, personalDetails, shouldShowPayerAndReceiver, transactionRawAmount]); const shouldShowIOUHeader = !!from && !!to; diff --git a/src/components/ReportActionItem/TransactionPreview/index.tsx b/src/components/ReportActionItem/TransactionPreview/index.tsx index 795e065180da..48d4baad8c27 100644 --- a/src/components/ReportActionItem/TransactionPreview/index.tsx +++ b/src/components/ReportActionItem/TransactionPreview/index.tsx @@ -86,6 +86,10 @@ function TransactionPreview(props: TransactionPreviewProps) { transactionPreview = originalTransaction; } + // See description of `transactionRawAmount` prop for more context + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const transactionRawAmount = (transaction?.modifiedAmount || transaction?.amount) ?? 0; + const iouAction = isBillSplit && originalTransaction ? (getIOUActionForReportID(chatReportID, originalTransaction.transactionID) ?? action) : action; const shouldDisableOnPress = isBillSplit && isEmptyObject(transaction); @@ -112,6 +116,7 @@ function TransactionPreview(props: TransactionPreviewProps) { chatReport={chatReport} personalDetails={personalDetails} transaction={transactionPreview} + transactionRawAmount={transactionRawAmount} report={report} violations={violations} offlineWithFeedbackOnClose={offlineWithFeedbackOnClose} @@ -135,6 +140,7 @@ function TransactionPreview(props: TransactionPreviewProps) { chatReport={chatReport} personalDetails={personalDetails} transaction={originalTransaction} + transactionRawAmount={transactionRawAmount} report={report} violations={violations} offlineWithFeedbackOnClose={offlineWithFeedbackOnClose} diff --git a/src/components/ReportActionItem/TransactionPreview/types.ts b/src/components/ReportActionItem/TransactionPreview/types.ts index 03de9f6c6616..4a73fcd3a154 100644 --- a/src/components/ReportActionItem/TransactionPreview/types.ts +++ b/src/components/ReportActionItem/TransactionPreview/types.ts @@ -102,6 +102,10 @@ type TransactionPreviewContentProps = { /** Holds the transaction data entry from Onyx */ transaction: OnyxEntry; + /** The original amount value on the transaction. This is used to deduce who is the sender and who is the receiver of the money request + * In case of Splits the property `transaction` is actually an original transaction (for the whole split) and it does not have the data required to deduce who is the sender */ + transactionRawAmount: number; + /** Represents the action entry from Onyx */ action: OnyxEntry; From c5ce6a04fbd6a636791c9b7b36d71d4af234e189 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Wed, 25 Jun 2025 13:39:21 +0200 Subject: [PATCH 4/4] Fix MoneyRequestReportPreview.stories.tsx --- src/stories/MoneyRequestReportPreview.stories.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stories/MoneyRequestReportPreview.stories.tsx b/src/stories/MoneyRequestReportPreview.stories.tsx index 233405102197..f314889c4bd9 100644 --- a/src/stories/MoneyRequestReportPreview.stories.tsx +++ b/src/stories/MoneyRequestReportPreview.stories.tsx @@ -43,6 +43,7 @@ const mockRenderItem: ListRenderItem = ({item}) => ( personalDetails={personalDetails} report={iouReportR14932} transaction={item} + transactionRawAmount={item.amount} violations={item.errors ? violationsR14932 : []} offlineWithFeedbackOnClose={() => undefined} navigateToReviewFields={() => undefined}