Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
1e58e22
Define MergeTransaction Onyx type
hoangzinh Jul 7, 2025
7295875
Setup routes + pages for merge transaction steps
hoangzinh Jul 7, 2025
4745900
Run prettier
hoangzinh Jul 7, 2025
e86a0f2
Add merge option to secondary actions
hoangzinh Jul 8, 2025
259d883
Fetch transaction for merge and display skeleton view while fetching
hoangzinh Jul 8, 2025
a7f98ef
Display no eligible expenses view
hoangzinh Jul 8, 2025
06b510b
Split into separate files to manage easier
hoangzinh Jul 8, 2025
00ce3f1
Add localise for empty state
hoangzinh Jul 8, 2025
098b5ca
Support radio button
hoangzinh Jul 9, 2025
80d2bee
Display transaction list
hoangzinh Jul 9, 2025
ed4d0fb
Update merge icon
hoangzinh Jul 9, 2025
996d92f
Display custom skeleton screen for merge transaction
hoangzinh Jul 9, 2025
15841c4
Header content for merge expenses
hoangzinh Jul 9, 2025
c6ba2b0
Update empty state with design doc
hoangzinh Jul 9, 2025
1e072f6
Should not show error in merge transaction list
hoangzinh Jul 10, 2025
393e5a7
Update type of targetTransactionId
hoangzinh Jul 10, 2025
660aa23
Handle click confirm button on list page
hoangzinh Jul 10, 2025
f9d14a8
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 10, 2025
fcbe0e0
Lift up into utils
hoangzinh Jul 11, 2025
939033e
Display transaction merge receipts
hoangzinh Jul 11, 2025
99b90a5
Fix eligibleTransactions does not contain targetTransaction
hoangzinh Jul 12, 2025
8cf94ab
Move utils and action of merge transaction to its own file
hoangzinh Jul 12, 2025
8f061b5
Fix type error
hoangzinh Jul 12, 2025
1175033
Support query eligibleTransaction locally when network is offline
hoangzinh Jul 12, 2025
5e5defc
reset merge transaction when starting merging
hoangzinh Jul 12, 2025
a4f9e79
Display zoom button icon in receipt review
hoangzinh Jul 12, 2025
31d03eb
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 14, 2025
b1c56b0
Use new radio button style for transaction merge
hoangzinh Jul 14, 2025
8bca6b8
Resolve details conflict when merge transaction
hoangzinh Jul 14, 2025
a67e9a1
Fix styling in details page
hoangzinh Jul 16, 2025
e637c59
Store whole receipt object in order to display in Confirmation page
hoangzinh Jul 16, 2025
2aea62c
Refactor get value in the details review page
hoangzinh Jul 16, 2025
035f7ca
Implement confirmation page
hoangzinh Jul 16, 2025
687964f
Rename component file with suffix Page
hoangzinh Jul 17, 2025
0d91360
Select target and source transaction based on business logic
hoangzinh Jul 17, 2025
efe72bc
Add translations for other languages
hoangzinh Jul 17, 2025
3267cbf
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 17, 2025
29766f5
Fix type error
hoangzinh Jul 17, 2025
ceb5086
Fix spellcheck
hoangzinh Jul 17, 2025
eaf05e9
Support view receipt from merge transaction flow
hoangzinh Jul 17, 2025
cb0c7d6
Fix getMergeableDataAndConflictFields bug not handle boolean value co…
hoangzinh Jul 17, 2025
4852389
Add unit tests for merge transaction utils
hoangzinh Jul 17, 2025
5f9c35c
Add test for merge transaction action
hoangzinh Jul 17, 2025
76039ec
Run prettier
hoangzinh Jul 17, 2025
2632561
Revert debug code
hoangzinh Jul 17, 2025
1964746
Fix linter
hoangzinh Jul 17, 2025
099e0ba
Fix missing import
hoangzinh Jul 17, 2025
dd10ea9
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 18, 2025
f06c6c2
Implement getTransactionsForMergingLocally
hoangzinh Jul 18, 2025
b44cb63
Fix unable to select false when resolve conflict
hoangzinh Jul 18, 2025
0e7db86
Fix spellcheck error
hoangzinh Jul 18, 2025
b01059f
Support merge currency
hoangzinh Jul 20, 2025
169d3c1
Correct merge API and params
hoangzinh Jul 20, 2025
90441bf
Fix mergeable and add test for amount field
hoangzinh Jul 20, 2025
d97ac74
Allow merge in unreported expense
hoangzinh Jul 20, 2025
529dc68
Fix false value if not display as No in DetailsReview page
hoangzinh Jul 20, 2025
5e45a49
Display merge button base on user role
hoangzinh Jul 21, 2025
02a3dda
Only display merge button in transaction thread or selected transaction
hoangzinh Jul 21, 2025
eb05969
Update function to get eligibleTransaction locally bases on role
hoangzinh Jul 22, 2025
89a2008
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 22, 2025
197a8f4
Fix resolve conflict
hoangzinh Jul 22, 2025
e6aa5fa
Optimistic delete source report when it's a single expense
hoangzinh Jul 23, 2025
96568ba
Add unit test for utils in merge transaction utils
hoangzinh Jul 23, 2025
8bccee9
Add unit tests for isMoneyRequestReportEligibleForMerge
hoangzinh Jul 23, 2025
7d437e6
Add specs for setupMergeTransactionData and setMergeTransactionKey
hoangzinh Jul 23, 2025
b44b8e4
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 23, 2025
68e429e
Allow merge in expense report when there is a single expense
hoangzinh Jul 23, 2025
7023dd8
Fix bug not found when navigate to receipt from transaction of self DM
hoangzinh Jul 23, 2025
79848be
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 23, 2025
000494d
Fix unable to see unreported expenses in the list
hoangzinh Jul 24, 2025
58bd569
Fill missing receipt source for eligibleTransactions data
hoangzinh Jul 24, 2025
16ceac0
Fix unable to view receipt for unreported expenses in review receipt …
hoangzinh Jul 24, 2025
4f4a5d0
Fix type error
hoangzinh Jul 24, 2025
8356c37
Fix not found page when merging
hoangzinh Jul 24, 2025
3e2dcbe
Optimictic update receipt source URL
hoangzinh Jul 25, 2025
0ee8437
Update translation feedback for Spain
hoangzinh Jul 25, 2025
47c103e
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 25, 2025
9e9002c
Update MergeTransactionItem style with recent refactor on Transaction…
hoangzinh Jul 25, 2025
544c537
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 28, 2025
b42f9f3
Update translation for es
hoangzinh Jul 28, 2025
0f9be6b
Update es translation based on new feedbacks
hoangzinh Jul 28, 2025
6011d3a
Apply reviewer feedback
hoangzinh Jul 29, 2025
399e0a4
Apply reviewer suggestion
hoangzinh Jul 29, 2025
7e12d4f
Ensure continue button and select receipt page work consistency as ot…
hoangzinh Jul 29, 2025
ee743a4
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 29, 2025
2359f63
Clear the merge transaction data when select a new source transaction…
hoangzinh Jul 29, 2025
5bbb758
Update displayName for component MergeFieldReview
hoangzinh Jul 29, 2025
c8ba9e7
Fix refresh the merge transaction page sets the central pane report t…
hoangzinh Jul 29, 2025
7fe857e
Apply reviewer feedback on style
hoangzinh Jul 29, 2025
7f64667
Replace by new prop shouldUseNewStyle
hoangzinh Jul 29, 2025
5a1c644
Remove unnecessary code
hoangzinh Jul 29, 2025
2e48f2a
Address feedback in TransactionMergeReceipts
hoangzinh Jul 29, 2025
cb26f61
Fix display reportName for unreported expenses
hoangzinh Jul 29, 2025
927add3
Refactor merge pages and use isLoadingOnyx to ensure mergeTransaction…
hoangzinh Jul 29, 2025
97a8e27
Fix missed update for demark
hoangzinh Jul 29, 2025
2d7b4f3
Fix Incorrect English article
hoangzinh Jul 29, 2025
8de2a8a
Fix spellcheck on vowel list
hoangzinh Jul 29, 2025
54e7072
Remove AEIOU out of spellcheck
hoangzinh Jul 29, 2025
2ea2125
Apply suggestion from reviewer
hoangzinh Jul 29, 2025
3e6035a
Correct expense name and add hover affect receipt
hoangzinh Jul 29, 2025
7b67715
Remove unused localisation
hoangzinh Jul 30, 2025
e778639
Refactor code
hoangzinh Jul 30, 2025
e7b0c6f
Fix prettier
hoangzinh Jul 30, 2025
cf9f533
Fix type check
hoangzinh Jul 30, 2025
165f41d
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 30, 2025
8bba02d
Adjust border radius and selected background
hoangzinh Jul 30, 2025
a3c6ac6
Should navigate to the confirmation page when there is no conflict
hoangzinh Jul 30, 2025
5b0ab84
Fix unable to view receipt image when it's a PDF file
hoangzinh Jul 30, 2025
4fb2c4f
Fix unable to view receipt image for source transaction
hoangzinh Jul 30, 2025
b5b0b31
Do not highlight when a source transaction is selected
hoangzinh Jul 30, 2025
6990440
Run prettier
hoangzinh Jul 30, 2025
a63432d
Swap border radius
hoangzinh Jul 30, 2025
0924310
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Jul 30, 2025
940b5bf
Fix unable to load sourceTransaction when merge with card expense
hoangzinh Jul 31, 2025
af6e060
Ensure display positive amount number
hoangzinh Jul 31, 2025
2abc8f7
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Aug 1, 2025
0c5bc2d
Apply reviewer suggestion
hoangzinh Aug 1, 2025
666ba84
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Aug 5, 2025
07d285c
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Aug 5, 2025
0c37ce9
Fallback to get transaction from mergeTransaction
hoangzinh Aug 5, 2025
d268da4
Update comment feedback
hoangzinh Aug 5, 2025
7291742
Fix confirmation page doesn't show details when merge with a card tra…
hoangzinh Aug 5, 2025
19a2abb
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Aug 6, 2025
9881633
Display button spinner instead of full page loading when checking rep…
hoangzinh Aug 6, 2025
df2c95e
Merge branch 'main' into merge-expenses-phase-1
hoangzinh Aug 6, 2025
613de45
Ensure transaction thread report is loaded completely
hoangzinh Aug 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"ADDCOMMENT",
"Addendums",
"ADFS",
"aeiou",
"Aeroplan",
"águero",
"Aircall",
Expand Down
3 changes: 3 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@ const CONST = {
REOPEN: 'reopen',
EXPORT: 'export',
PAY: 'pay',
MERGE: 'merge',
},
PRIMARY_ACTIONS: {
SUBMIT: 'submit',
Expand Down Expand Up @@ -1115,6 +1116,7 @@ const CONST = {
SPLIT: 'split',
VIEW_DETAILS: 'viewDetails',
DELETE: 'delete',
MERGE: 'merge',
},
ADD_EXPENSE_OPTIONS: {
CREATE_NEW_EXPENSE: 'createNewExpense',
Expand Down Expand Up @@ -3107,6 +3109,7 @@ const CONST = {
FinancialForce: 'https://help.expensify.com/articles/expensify-classic/connections/certinia/Connect-To-Certinia',
'Sage Intacct': 'https://help.expensify.com/articles/new-expensify/connections/sage-intacct/Configure-Sage-Intacct',
Certinia: 'https://help.expensify.com/articles/expensify-classic/connections/certinia/Connect-To-Certinia',
MERGE_EXPENSES: 'https://help.expensify.com/articles/new-expensify/reports-and-expenses/Merging-expenses',
Comment thread
hoangzinh marked this conversation as resolved.
},

CUSTOM_UNITS: {
Expand Down
2 changes: 2 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ const ONYXKEYS = {
SKIP_CONFIRMATION: 'skipConfirmation_',
TRANSACTION_BACKUP: 'transactionsBackup_',
SPLIT_TRANSACTION_DRAFT: 'splitTransactionDraft_',
MERGE_TRANSACTION: 'mergeTransaction_',
PRIVATE_NOTES_DRAFT: 'privateNotesDraft_',
NEXT_STEP: 'reportNextStep_',

Expand Down Expand Up @@ -1008,6 +1009,7 @@ type OnyxCollectionValuesMapping = {
[ONYXKEYS.COLLECTION.TRANSACTION_BACKUP]: OnyxTypes.Transaction;
[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS]: OnyxTypes.TransactionViolations;
[ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT]: OnyxTypes.Transaction;
[ONYXKEYS.COLLECTION.MERGE_TRANSACTION]: OnyxTypes.MergeTransaction;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags;
[ONYXKEYS.COLLECTION.OLD_POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags;
[ONYXKEYS.COLLECTION.SELECTED_TAB]: OnyxTypes.SelectedTabRequest;
Expand Down
28 changes: 26 additions & 2 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2076,7 +2076,15 @@ const ROUTES = {

TRANSACTION_RECEIPT: {
route: 'r/:reportID/transaction/:transactionID/receipt/:action?/:iouType?',
getRoute: (reportID: string | undefined, transactionID: string | undefined, readonly = false, isFromReviewDuplicates = false, action?: IOUAction, iouType?: IOUType) => {
getRoute: (
reportID: string | undefined,
transactionID: string | undefined,
readonly = false,
isFromReviewDuplicates = false,
action?: IOUAction,
iouType?: IOUType,
mergeTransactionID?: string,
) => {
if (!reportID) {
Log.warn('Invalid reportID is used to build the TRANSACTION_RECEIPT route');
}
Expand All @@ -2085,7 +2093,7 @@ const ROUTES = {
}
return `r/${reportID}/transaction/${transactionID}/receipt${action ? `/${action}` : ''}${iouType ? `/${iouType}` : ''}?readonly=${readonly}${
isFromReviewDuplicates ? '&isFromReviewDuplicates=true' : ''
}` as const;
}${mergeTransactionID ? `&mergeTransactionID=${mergeTransactionID}` : ''}` as const;
},
},

Expand Down Expand Up @@ -2125,6 +2133,22 @@ const ROUTES = {
route: 'r/:threadReportID/duplicates/confirm',
getRoute: (threadReportID: string, backTo?: string) => getUrlWithBackToParam(`r/${threadReportID}/duplicates/confirm` as const, backTo),
},
MERGE_TRANSACTION_LIST_PAGE: {
route: 'r/:transactionID/merge',
getRoute: (transactionID: string | undefined, backTo?: string) => getUrlWithBackToParam(`r/${transactionID}/merge` as const, backTo),
},
MERGE_TRANSACTION_RECEIPT_PAGE: {
route: 'r/:transactionID/merge/receipt',
getRoute: (transactionID: string, backTo?: string) => getUrlWithBackToParam(`r/${transactionID}/merge/receipt` as const, backTo),
},
MERGE_TRANSACTION_DETAILS_PAGE: {
route: 'r/:transactionID/merge/details',
getRoute: (transactionID: string, backTo?: string) => getUrlWithBackToParam(`r/${transactionID}/merge/details` as const, backTo),
},
MERGE_TRANSACTION_CONFIRMATION_PAGE: {
route: 'r/:transactionID/merge/confirmation',
getRoute: (transactionID: string, backTo?: string) => getUrlWithBackToParam(`r/${transactionID}/merge/confirmation` as const, backTo),
},
POLICY_ACCOUNTING_XERO_IMPORT: {
route: 'workspaces/:policyID/accounting/xero/import',
getRoute: (policyID: string) => `workspaces/${policyID}/accounting/xero/import` as const,
Expand Down
8 changes: 8 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ const SCREENS = {
DEBUG: 'Debug',
ADD_UNREPORTED_EXPENSE: 'AddUnreportedExpense',
SCHEDULE_CALL: 'ScheduleCall',
MERGE_TRANSACTION: 'MergeTransaction',
},
PUBLIC_CONSOLE_DEBUG: 'Console_Debug',
ONBOARDING_MODAL: {
Expand Down Expand Up @@ -293,6 +294,13 @@ const SCREENS = {
CONFIRMATION: 'Transaction_Duplicate_Confirmation',
},

MERGE_TRANSACTION: {
LIST_PAGE: 'Merge_Transaction_List_Page',
RECEIPT_PAGE: 'Merge_Transaction_Receipt_Page',
DETAILS_PAGE: 'Merge_Transaction_Details_Page',
CONFIRMATION_PAGE: 'Merge_Transaction_Confirmation_Page',
},

IOU_SEND: {
ADD_BANK_ACCOUNT: 'IOU_Send_Add_Bank_Account',
ADD_DEBIT_CARD: 'IOU_Send_Add_Debit_Card',
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Illustrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import CreditCardsNew from '@assets/images/simple-illustrations/simple-illustrat
import CreditCardEyes from '@assets/images/simple-illustrations/simple-illustration__creditcardeyes.svg';
import CreditCardsNewGreen from '@assets/images/simple-illustrations/simple-illustration__creditcards--green.svg';
import EmailAddress from '@assets/images/simple-illustrations/simple-illustration__email-address.svg';
import EmptyShelves from '@assets/images/simple-illustrations/simple-illustration__empty-shelves.svg';
import EmptyState from '@assets/images/simple-illustrations/simple-illustration__empty-state.svg';
import Encryption from '@assets/images/simple-illustrations/simple-illustration__encryption.svg';
import EnvelopeReceipt from '@assets/images/simple-illustrations/simple-illustration__envelopereceipt.svg';
Expand Down Expand Up @@ -324,4 +325,5 @@ export {
ReceiptsStackedOnPin,
PaperAirplane,
CardReplacementSuccess,
EmptyShelves,
};
16 changes: 16 additions & 0 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSelectedTransactionsActions from '@hooks/useSelectedTransactionsActions';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {setupMergeTransactionData} from '@libs/actions/MergeTransaction';
import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
import {deleteAppReport, downloadReportPDF, exportReportToCSV, exportReportToPDF, exportToIntegration, markAsManuallyExported, openReport, openUnreportedExpense} from '@libs/actions/Report';
import {queueExportSearchWithTemplate} from '@libs/actions/Search';
Expand Down Expand Up @@ -306,6 +307,7 @@ function MoneyReportHeader({
allTransactionsLength: transactions.length,
session,
onExportFailed: () => setIsDownloadErrorModalVisible(true),
policy,
beginExportWithTemplate: (templateName, templateType, transactionIDList) => beginExportWithTemplate(templateName, templateType, transactionIDList),
});

Expand Down Expand Up @@ -891,6 +893,20 @@ function MoneyReportHeader({
initSplitExpense(currentTransaction);
},
},
[CONST.REPORT.SECONDARY_ACTIONS.MERGE]: {
text: translate('common.merge'),
icon: Expensicons.ArrowCollapse,
value: CONST.REPORT.SECONDARY_ACTIONS.MERGE,
onSelected: () => {
const currentTransaction = transactions.at(0);
if (!currentTransaction) {
return;
}

Comment thread
hoangzinh marked this conversation as resolved.
setupMergeTransactionData(currentTransaction.transactionID, {targetTransactionID: currentTransaction.transactionID});
Navigation.navigate(ROUTES.MERGE_TRANSACTION_LIST_PAGE.getRoute(currentTransaction.transactionID, Navigation.getActiveRoute()));
},
},
[CONST.REPORT.SECONDARY_ACTIONS.CHANGE_WORKSPACE]: {
text: translate('iou.changeWorkspace'),
icon: Expensicons.Buildings,
Expand Down
14 changes: 14 additions & 0 deletions src/components/MoneyRequestHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useTransactionViolations from '@hooks/useTransactionViolations';
import {deleteMoneyRequest, deleteTrackExpense, initSplitExpense} from '@libs/actions/IOU';
import {setupMergeTransactionData} from '@libs/actions/MergeTransaction';
import Navigation from '@libs/Navigation/Navigation';
import {getOriginalMessage, getReportActions, isMoneyRequestAction, isTrackExpenseAction} from '@libs/ReportActionsUtils';
import {getTransactionThreadPrimaryAction} from '@libs/ReportPrimaryActionUtils';
Expand Down Expand Up @@ -244,6 +245,19 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre
initSplitExpense(transaction);
},
},
[CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE]: {
text: translate('common.merge'),
icon: Expensicons.ArrowCollapse,
value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE,
onSelected: () => {
if (!transaction) {
return;
}

setupMergeTransactionData(transaction.transactionID, {targetTransactionID: transaction.transactionID});
Navigation.navigate(ROUTES.MERGE_TRANSACTION_LIST_PAGE.getRoute(transaction.transactionID, Navigation.getActiveRoute()));
},
},
[CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.VIEW_DETAILS]: {
value: CONST.REPORT.SECONDARY_ACTIONS.VIEW_DETAILS,
text: translate('iou.viewDetails'),
Expand Down
35 changes: 34 additions & 1 deletion src/components/RadioButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,45 @@ type RadioButtonProps = {

/** Should the input be disabled */
disabled?: boolean;

/** Whether to use new radio button style */
// See https://expensify.slack.com/archives/C07HPDRELLD/p1752500012040139?thread_ts=1751637205.950179&cid=C07HPDRELLD
shouldUseNewStyle?: boolean;
};

function RadioButton({isChecked, onPress, accessibilityLabel, hasError = false, disabled = false}: RadioButtonProps) {
function RadioButton({isChecked, onPress, accessibilityLabel, hasError = false, disabled = false, shouldUseNewStyle = false}: RadioButtonProps) {
const theme = useTheme();
const styles = useThemeStyles();

if (shouldUseNewStyle) {
return (
<PressableWithFeedback
disabled={disabled}
onPress={onPress}
hoverDimmingValue={1}
pressDimmingValue={1}
accessibilityLabel={accessibilityLabel}
role={CONST.ROLE.RADIO}
style={[
styles.newRadioButtonContainer,
hasError && styles.borderColorDanger,
disabled && styles.cursorDisabled,
isChecked && styles.checkedContainer,
isChecked && styles.borderColorFocus,
]}
>
{isChecked && (
<Icon
src={Expensicons.Checkmark}
fill={theme.textLight}
height={14}
width={14}
/>
)}
</PressableWithFeedback>
);
}

return (
<PressableWithFeedback
disabled={disabled}
Expand Down
29 changes: 24 additions & 5 deletions src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ import type {TransactionDetails} from '@libs/ReportUtils';
import {hasEnabledTags} from '@libs/TagsOptionsListUtils';
import {
didReceiptScanSucceed as didReceiptScanSucceedTransactionUtils,
getAmount,
getBillable,
getCurrency,
getDescription,
getDistanceInMeters,
getOriginalTransactionWithSplitInfo,
Expand Down Expand Up @@ -106,8 +108,11 @@ type MoneyRequestViewProps = {
/** whether or not this report is from review duplicates */
isFromReviewDuplicates?: boolean;

/** Updated transaction to show in duplicate transaction flow */
/** Updated transaction to show in duplicate & merge transaction flow */
updatedTransaction?: OnyxEntry<OnyxTypes.Transaction>;

/** Merge transaction ID to show in merge transaction flow */
mergeTransactionID?: string;
};

const receiptImageViolationNames: OnyxTypes.ViolationName[] = [
Expand All @@ -121,7 +126,16 @@ const receiptImageViolationNames: OnyxTypes.ViolationName[] = [

const receiptFieldViolationNames: OnyxTypes.ViolationName[] = [CONST.VIOLATIONS.MODIFIED_AMOUNT, CONST.VIOLATIONS.MODIFIED_DATE];

function MoneyRequestView({allReports, report, policy, shouldShowAnimatedBackground, readonly = false, updatedTransaction, isFromReviewDuplicates = false}: MoneyRequestViewProps) {
function MoneyRequestView({
allReports,
report,
policy,
shouldShowAnimatedBackground,
readonly = false,
updatedTransaction,
isFromReviewDuplicates = false,
mergeTransactionID,
}: MoneyRequestViewProps) {
const styles = useThemeStyles();
const {isOffline} = useNetwork();
const {translate, toLocaleDigit} = useLocalize();
Expand Down Expand Up @@ -181,9 +195,13 @@ function MoneyRequestView({allReports, report, policy, shouldShowAnimatedBackgro
const isTransactionScanning = isScanning(updatedTransaction ?? transaction);
const didReceiptScanSucceed = hasReceipt && didReceiptScanSucceedTransactionUtils(transaction);
const hasRoute = hasRouteTransactionUtils(transactionBackup ?? transaction, isDistanceRequest);
const shouldDisplayTransactionAmount = ((isDistanceRequest && hasRoute) || !!transactionAmount) && transactionAmount !== undefined;
const formattedTransactionAmount = shouldDisplayTransactionAmount ? convertToDisplayString(transactionAmount, transactionCurrency) : '';
const formattedPerAttendeeAmount = shouldDisplayTransactionAmount ? convertToDisplayString(transactionAmount / (transactionAttendees?.length ?? 1), transactionCurrency) : '';

const actualAmount = updatedTransaction ? getAmount(updatedTransaction) : transactionAmount;
const actualCurrency = updatedTransaction ? getCurrency(updatedTransaction) : transactionCurrency;
const shouldDisplayTransactionAmount = ((isDistanceRequest && hasRoute) || !!actualAmount) && actualAmount !== undefined;
const formattedTransactionAmount = shouldDisplayTransactionAmount ? convertToDisplayString(actualAmount, actualCurrency) : '';
const formattedPerAttendeeAmount = shouldDisplayTransactionAmount ? convertToDisplayString(actualAmount / (transactionAttendees?.length ?? 1), actualCurrency) : '';

const formattedOriginalAmount = transactionOriginalAmount && transactionOriginalCurrency && convertToDisplayString(transactionOriginalAmount, transactionOriginalCurrency);
const isCardTransaction = isCardTransactionTransactionUtils(transaction);
const cardProgramName = getCompanyCardDescription(transaction?.cardName, transaction?.cardID, cardList);
Expand Down Expand Up @@ -661,6 +679,7 @@ function MoneyRequestView({allReports, report, policy, shouldShowAnimatedBackgro
enablePreviewModal
readonly={readonly || !canEditReceipt}
isFromReviewDuplicates={isFromReviewDuplicates}
mergeTransactionID={mergeTransactionID}
/>
</View>
)}
Expand Down
14 changes: 13 additions & 1 deletion src/components/ReportActionItem/ReportActionItemImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ type ReportActionItemImageProps = {
/** whether or not this report is from review duplicates */
isFromReviewDuplicates?: boolean;

/** Merge transaction ID to show in merge transaction flow */
mergeTransactionID?: string;

/** Callback to be called on pressing the image */
onPress?: () => void;

Expand Down Expand Up @@ -88,6 +91,7 @@ function ReportActionItemImage({
readonly = false,
shouldMapHaveBorderRadius,
isFromReviewDuplicates = false,
mergeTransactionID,
onPress,
shouldUseFullHeight,
}: ReportActionItemImageProps) {
Expand Down Expand Up @@ -154,7 +158,15 @@ function ReportActionItemImage({
style={[styles.w100, styles.h100, styles.noOutline as ViewStyle]}
onPress={() =>
Navigation.navigate(
ROUTES.TRANSACTION_RECEIPT.getRoute(transactionThreadReport?.reportID ?? report?.reportID, transaction?.transactionID, readonly, isFromReviewDuplicates),
ROUTES.TRANSACTION_RECEIPT.getRoute(
transactionThreadReport?.reportID ?? report?.reportID,
transaction?.transactionID,
readonly,
isFromReviewDuplicates,
undefined,
undefined,
mergeTransactionID,
),
)
}
accessibilityLabel={translate('accessibilityHints.viewAttachment')}
Expand Down
3 changes: 2 additions & 1 deletion src/components/SelectionList/BaseSelectionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ function BaseSelectionList<TItem extends ListItem>(
listEmptyContent,
showScrollIndicator = true,
showLoadingPlaceholder = false,
LoadingPlaceholderComponent = OptionsListSkeletonView,
showConfirmButton = false,
isConfirmButtonDisabled = false,
shouldUseDefaultTheme = false,
Expand Down Expand Up @@ -681,7 +682,7 @@ function BaseSelectionList<TItem extends ListItem>(
const renderListEmptyContent = () => {
if (showLoadingPlaceholder) {
return (
<OptionsListSkeletonView
<LoadingPlaceholderComponent
fixedNumItems={fixedNumItemsForLoader}
shouldStyleAsTable={shouldUseUserSkeletonView}
speed={loaderSpeed}
Expand Down
9 changes: 9 additions & 0 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,12 @@ type Section<TItem extends ListItem> = {
shouldShow?: boolean;
};

type LoadingPlaceholderComponentProps = {
shouldStyleAsTable?: boolean;
fixedNumItems?: number;
speed?: number;
};

type SectionWithIndexOffset<TItem extends ListItem> = Section<TItem> & {
/** The initial index of this section given the total number of options in each section's data array */
indexOffset?: number;
Expand Down Expand Up @@ -661,6 +667,9 @@ type SelectionListProps<TItem extends ListItem> = Partial<ChildrenProps> & {
/** Whether to show the loading placeholder */
showLoadingPlaceholder?: boolean;

/** The component to show when the list is loading */
LoadingPlaceholderComponent?: React.ComponentType<LoadingPlaceholderComponentProps>;

/** Whether to show the default confirm button */
showConfirmButton?: boolean;

Expand Down
Loading
Loading