Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
1d645d6
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha May 16, 2025
002ea08
fix: add moved report action
getusha May 23, 2025
e96d135
fix: clean nvp on workspace removal
getusha May 23, 2025
d41eb48
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha May 23, 2025
6e5aaac
fix conflicts
getusha May 23, 2025
44c6ad6
fix lint and type check
getusha May 23, 2025
7a505e5
fix lint and type check
getusha May 23, 2025
4efa012
fix: bad merge
getusha May 23, 2025
26e1305
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha May 30, 2025
2daa594
revert a refactor for SettlementButton
getusha May 30, 2025
23f98cd
fix: bad merge
getusha May 30, 2025
17b36e4
fix: tests
getusha May 30, 2025
f7633dd
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 4, 2025
b943cbe
fix: lint
getusha Jun 4, 2025
fd59095
fix: spell checks
getusha Jun 4, 2025
39f7aa5
fix: dupe system message
getusha Jun 4, 2025
ab7b546
fix: spell checks
getusha Jun 4, 2025
3184c33
fix: fix bugs
getusha Jun 6, 2025
568fa47
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 6, 2025
9868662
fix: checks
getusha Jun 6, 2025
6f85ed4
fix: prettier
getusha Jun 6, 2025
cb4a736
revert submodule update
getusha Jun 6, 2025
cbd6691
fix: don't show BA details for personal account
getusha Jun 6, 2025
4eac6a3
fix: remove sorting of payment options
getusha Jun 6, 2025
202ba3b
fix: wrong payment options
getusha Jun 10, 2025
811a87d
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 10, 2025
df629a7
fix lint
getusha Jun 10, 2025
67e771a
revert submodule update
getusha Jun 10, 2025
685723a
fix lint temp
getusha Jun 10, 2025
147a3b6
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 11, 2025
3fc6d8f
fix: bad merge
getusha Jun 11, 2025
f350244
fix: lint
getusha Jun 11, 2025
dc365f5
fix: lint
getusha Jun 11, 2025
6af7ed9
fix: address bugs
getusha Jun 11, 2025
71cc5fa
fix: show amount on report header pay button
getusha Jun 12, 2025
9fa873f
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 19, 2025
75134d5
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 19, 2025
be681ee
fix: detonate mountain of bugs
getusha Jun 19, 2025
0a2ecf5
fix: add translations
getusha Jun 20, 2025
1bbc828
ref: remove outdated code
getusha Jun 20, 2025
d4cb7c5
fix: conflict
getusha Jun 20, 2025
c844aeb
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 23, 2025
134cba4
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 23, 2025
511bc42
fix: update submodule
getusha Jun 23, 2025
f1137c3
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 24, 2025
ff6e4b5
fix: lint n prettier
getusha Jun 24, 2025
a99b7d6
fix: update submodule
getusha Jun 24, 2025
3024410
fix: conflicts
getusha Jun 24, 2025
b3e5068
fix: update split style condition
getusha Jun 24, 2025
31ff632
fix: update split style condition
getusha Jun 24, 2025
c914862
Merge remote-tracking branch 'exfy/main' into feat-standardize-pay-bu…
getusha Jun 24, 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
6 changes: 3 additions & 3 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7191,9 +7191,9 @@ const CONST = {
},
LAST_PAYMENT_METHOD: {
LAST_USED: 'lastUsed',
IOU: 'Iou',
EXPENSE: 'Expense',
INVOICE: 'Invoice',
IOU: 'iou',
EXPENSE: 'expense',
INVOICE: 'invoice',
},
SKIPPABLE_COLLECTION_MEMBER_IDS: [String(DEFAULT_NUMBER_ID), '-1', 'undefined', 'null', 'NaN'] as string[],
SETUP_SPECIALIST_LOGIN: 'Setup Specialist',
Expand Down
14 changes: 13 additions & 1 deletion src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,19 @@ function Button(
const textComponent = secondLineText ? (
<View style={[styles.alignItemsCenter, styles.flexColumn, styles.flexShrink1]}>
{primaryText}
<Text style={[isLoading && styles.opacity0, styles.pointerEventsNone, styles.fontWeightNormal, styles.textDoubleDecker]}>{secondLineText}</Text>
<Text
style={[
isLoading && styles.opacity0,
styles.pointerEventsNone,
styles.fontWeightNormal,
styles.textDoubleDecker,
!!secondLineText && styles.textExtraSmallSupporting,
styles.textWhite,
styles.textBold,
]}
>
{secondLineText}
</Text>
</View>
) : (
primaryText
Expand Down
22 changes: 19 additions & 3 deletions src/components/ButtonWithDropdownMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ function ButtonWithDropdownMenu<IValueType>({
testID,
secondLineText = '',
icon,
shouldPopoverUseScrollView = false,
containerStyles,
shouldUseModalPaddingStyle = true,
}: ButtonWithDropdownMenuProps<IValueType>) {
const theme = useTheme();
Expand All @@ -73,6 +75,10 @@ function ButtonWithDropdownMenu<IValueType>({
const isButtonSizeLarge = buttonSize === CONST.DROPDOWN_BUTTON_SIZE.LARGE;
const nullCheckRef = (ref: RefObject<View | null>) => ref ?? null;

useEffect(() => {
setSelectedItemIndex(defaultSelectedIndex);
}, [defaultSelectedIndex]);

useEffect(() => {
if (!dropdownAnchor.current) {
return;
Expand Down Expand Up @@ -233,17 +239,27 @@ function ButtonWithDropdownMenu<IValueType>({
// eslint-disable-next-line react-compiler/react-compiler
anchorRef={nullCheckRef(dropdownAnchor)}
withoutOverlay
shouldUseScrollView
scrollContainerStyle={!shouldUseModalPaddingStyle && isSmallScreenWidth && styles.pv4}
shouldUseModalPaddingStyle={shouldUseModalPaddingStyle}
anchorAlignment={anchorAlignment}
shouldUseModalPaddingStyle={shouldUseModalPaddingStyle}
headerText={menuHeaderText}
shouldUseScrollView={shouldPopoverUseScrollView}
containerStyles={containerStyles}
menuItems={options.map((item, index) => ({
...item,
onSelected: item.onSelected
? () => item.onSelected?.()
? () => {
item.onSelected?.();
if (item.shouldUpdateSelectedIndex) {
setSelectedItemIndex(index);
}
}
: () => {
onOptionSelected?.(item);
if (!item.shouldUpdateSelectedIndex && typeof item.shouldUpdateSelectedIndex === 'boolean') {
return;
}

setSelectedItemIndex(index);
},
shouldCallAfterModalHide: true,
Expand Down
8 changes: 8 additions & 0 deletions src/components/ButtonWithDropdownMenu/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ type DropdownOption<TValueType> = {
descriptionTextStyle?: StyleProp<TextStyle>;
wrapperStyle?: StyleProp<ViewStyle>;
displayInDefaultIconColor?: boolean;
/** Whether the selected index should be updated when the option is selected even if we have onSelected callback */
shouldUpdateSelectedIndex?: boolean;
subMenuItems?: PopoverMenuItem[];
backButtonText?: string;
avatarSize?: ValueOf<typeof CONST.AVATAR_SIZE>;
Expand Down Expand Up @@ -140,6 +142,12 @@ type ButtonWithDropdownMenuProps<TValueType> = {
/** Icon for main button */
icon?: IconAsset;

/** Whether the popover content should be scrollable */
shouldPopoverUseScrollView?: boolean;

/** Container style to be applied to the popover of the dropdown menu */
containerStyles?: StyleProp<ViewStyle>;

/** Whether to use modal padding style for the popover menu */
shouldUseModalPaddingStyle?: boolean;
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/Icon/BankIcons/index.native.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import GenericBank from '@assets/images/bank-icons/generic-bank-account.svg';
import GenericBankCard from '@assets/images/cardicons/generic-bank-card.svg';
import type {BankIconParams} from '@components/Icon/BankIconsUtils';
import {getBankIconAsset, getBankNameKey} from '@components/Icon/BankIconsUtils';
import {Bank} from '@components/Icon/Expensicons';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type {BankIcon} from '@src/types/onyx/Bank';
Expand All @@ -11,7 +11,7 @@ import type {BankIcon} from '@src/types/onyx/Bank';
*/
export default function getBankIcon({styles, bankName, isCard = false}: BankIconParams): BankIcon {
const bankIcon: BankIcon = {
icon: isCard ? GenericBankCard : GenericBank,
icon: isCard ? GenericBankCard : Bank,
};
if (bankName) {
const bankNameKey = getBankNameKey(bankName.toLowerCase());
Expand Down
57 changes: 45 additions & 12 deletions src/components/KYCWall/BaseKYCWall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@ import type {EmitterSubscription, GestureResponderEvent, View} from 'react-nativ
import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu';
import useOnyx from '@hooks/useOnyx';
import {openPersonalBankAccountSetupView} from '@libs/actions/BankAccounts';
import {completePaymentOnboarding} from '@libs/actions/IOU';
import {completePaymentOnboarding, savePreferredPaymentMethod} from '@libs/actions/IOU';
import {moveIOUReportToPolicy, moveIOUReportToPolicyAndInviteSubmitter} from '@libs/actions/Report';
import getClickedTargetLocation from '@libs/getClickedTargetLocation';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import {hasExpensifyPaymentMethod} from '@libs/PaymentUtils';
import {isExpenseReport as isExpenseReportReportUtils, isIOUReport} from '@libs/ReportUtils';
import {getPolicyExpenseChat, isExpenseReport as isExpenseReportReportUtils, isIOUReport} from '@libs/ReportUtils';
import {kycWallRef} from '@userActions/PaymentMethods';
import {createWorkspaceFromIOUPayment} from '@userActions/Policy/Policy';
import {setKYCWallSource} from '@userActions/Wallet';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Policy} from '@src/types/onyx';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import viewRef from '@src/types/utils/viewRef';
import type {AnchorPosition, DomRect, KYCWallProps, PaymentMethod} from './types';
Expand Down Expand Up @@ -45,11 +47,11 @@ function KYCWall({
source,
shouldShowPersonalBankAccountOption = false,
}: KYCWallProps) {
const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET);
const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS);
const [fundList] = useOnyx(ONYXKEYS.FUND_LIST);
const [bankAccountList = {}] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET, {canBeMissing: true});
const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS, {canBeMissing: true});
const [fundList] = useOnyx(ONYXKEYS.FUND_LIST, {canBeMissing: true});
const [bankAccountList = {}] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST, {canBeMissing: true});
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {canBeMissing: true});

const anchorRef = useRef<HTMLDivElement | View>(null);
const transferBalanceButtonRef = useRef<HTMLDivElement | View | null>(null);
Expand Down Expand Up @@ -100,24 +102,48 @@ function KYCWall({
}, [getAnchorPosition]);

const selectPaymentMethod = useCallback(
(paymentMethod: PaymentMethod) => {
onSelectPaymentMethod(paymentMethod);
(paymentMethod?: PaymentMethod, policy?: Policy) => {
if (paymentMethod) {
onSelectPaymentMethod(paymentMethod);
}

if (paymentMethod === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) {
openPersonalBankAccountSetupView();
} else if (paymentMethod === CONST.PAYMENT_METHODS.DEBIT_CARD) {
Navigation.navigate(addDebitCardRoute ?? ROUTES.HOME);
} else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT) {
} else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT || policy) {
Comment thread
grgia marked this conversation as resolved.
if (iouReport && isIOUReport(iouReport)) {
if (policy) {
Comment thread
getusha marked this conversation as resolved.
const policyExpenseChatReportID = getPolicyExpenseChat(iouReport.ownerAccountID, policy.id)?.reportID;
if (!policyExpenseChatReportID) {
const {policyExpenseChatReportID: newPolicyExpenseChatReportID} = moveIOUReportToPolicyAndInviteSubmitter(iouReport.reportID, policy.id) ?? {};
savePreferredPaymentMethod(iouReport.policyID, policy.id, CONST.LAST_PAYMENT_METHOD.IOU);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(newPolicyExpenseChatReportID));
} else {
moveIOUReportToPolicy(iouReport.reportID, policy.id, true);
savePreferredPaymentMethod(iouReport.policyID, policy.id, CONST.LAST_PAYMENT_METHOD.IOU);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(policyExpenseChatReportID));
}

if (policy?.achAccount) {
return;
}
// Navigate to the bank account set up flow for this specific policy
Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute(policy.id));
return;
}

const {policyID, workspaceChatReportID, reportPreviewReportActionID, adminsChatReportID} = createWorkspaceFromIOUPayment(iouReport) ?? {};
if (policyID) {
savePreferredPaymentMethod(iouReport.policyID, policyID, CONST.LAST_PAYMENT_METHOD.IOU);
}
completePaymentOnboarding(CONST.PAYMENT_SELECTED.BBA, adminsChatReportID, policyID);
if (workspaceChatReportID) {
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(workspaceChatReportID, reportPreviewReportActionID));
}

// Navigate to the bank account set up flow for this specific policy
Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute(policyID));

return;
}
Navigation.navigate(addBankAccountRoute);
Expand All @@ -133,7 +159,7 @@ function KYCWall({
*
*/
const continueAction = useCallback(
(event?: GestureResponderEvent | KeyboardEvent, iouPaymentType?: PaymentMethodType) => {
(event?: GestureResponderEvent | KeyboardEvent, iouPaymentType?: PaymentMethodType, paymentMethod?: PaymentMethod, policy?: Policy) => {
const currentSource = walletTerms?.source ?? source;

/**
Expand Down Expand Up @@ -170,6 +196,13 @@ function KYCWall({
const clickedElementLocation = getClickedTargetLocation(targetElement as HTMLDivElement);
const position = getAnchorPosition(clickedElementLocation);

// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
if (paymentMethod || policy) {
setShouldShowAddPaymentMenu(false);
selectPaymentMethod(paymentMethod, policy);
return;
}

setPositionAddPaymentMenu(position);
setShouldShowAddPaymentMenu(true);

Expand Down
5 changes: 4 additions & 1 deletion src/components/KYCWall/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type CONST from '@src/CONST';
import type {Route} from '@src/ROUTES';
import type {Report} from '@src/types/onyx';
import type {Policy, Report} from '@src/types/onyx';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import type AnchorAlignment from '@src/types/utils/AnchorAlignment';

Expand Down Expand Up @@ -63,6 +63,9 @@ type KYCWallProps = {

/** Children to build the KYC */
children: (continueAction: (event: GestureResponderEvent | KeyboardEvent | undefined, method?: PaymentMethodType) => void, anchorRef: RefObject<View | null>) => void;

/** The policy used for payment */
policy?: Policy;
};

export type {AnchorPosition, KYCWallProps, PaymentMethod, DomRect, PaymentMethodType, Source};
3 changes: 2 additions & 1 deletion src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ function MoneyReportHeader({
payInvoice(type, chatReport, moneyRequestReport, payAsBusiness, methodID, paymentMethod);
} else {
startAnimation();
payMoneyRequest(type, chatReport, moneyRequestReport, true);
payMoneyRequest(type, chatReport, moneyRequestReport, undefined, true);
}
},
[chatReport, isAnyTransactionOnHold, isDelegateAccessRestricted, showDelegateNoAccessModal, isInvoiceReport, moneyRequestReport, startAnimation],
Expand Down Expand Up @@ -525,6 +525,7 @@ function MoneyReportHeader({
isPaidAnimationRunning={isPaidAnimationRunning}
isApprovedAnimationRunning={isApprovedAnimationRunning}
onAnimationFinish={stopAnimation}
formattedAmount={totalAmount}
canIOUBePaid
onlyShowPayElsewhere={onlyShowPayElsewhere}
currency={moneyRequestReport?.currency}
Expand Down
11 changes: 4 additions & 7 deletions src/components/PopoverMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,10 @@ function PopoverMenu({
}
setFocusedIndex(menuIndex);
}}
wrapperStyle={StyleUtils.getItemBackgroundColorStyle(
!!item.isSelected,
focusedIndex === menuIndex,
item.disabled ?? false,
theme.activeComponentBG,
theme.hoverComponentBG,
)}
wrapperStyle={[
StyleUtils.getItemBackgroundColorStyle(!!item.isSelected, focusedIndex === menuIndex, item.disabled ?? false, theme.activeComponentBG, theme.hoverComponentBG),
shouldUseScrollView && StyleUtils.getOptionMargin(menuIndex, currentMenuItems.length - 1),
]}
shouldRemoveHoverBackground={item.isSelected}
titleStyle={StyleSheet.flatten([styles.flex1, item.titleStyle])}
// Spread other props dynamically
Expand Down
10 changes: 5 additions & 5 deletions src/components/ProcessMoneyReportHoldMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import Navigation from '@libs/Navigation/Navigation';
import {isLinkedTransactionHeld} from '@libs/ReportActionsUtils';
import * as IOU from '@userActions/IOU';
import {approveMoneyRequest, payMoneyRequest} from '@userActions/IOU';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
Expand Down Expand Up @@ -69,15 +69,15 @@ function ProcessMoneyReportHoldMenu({
if (startAnimation) {
startAnimation();
}
IOU.approveMoneyRequest(moneyRequestReport, full);
if (!full && isLinkedTransactionHeld(Navigation.getTopmostReportActionId() ?? '-1', moneyRequestReport?.reportID ?? '')) {
Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(moneyRequestReport?.reportID ?? ''));
approveMoneyRequest(moneyRequestReport, full);
if (!full && isLinkedTransactionHeld(Navigation.getTopmostReportActionId(), moneyRequestReport?.reportID)) {
Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(moneyRequestReport?.reportID));
}
} else if (chatReport && paymentType) {
if (startAnimation) {
startAnimation();
}
IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport, full);
payMoneyRequest(paymentType, chatReport, moneyRequestReport, undefined, full);
}
onClose();
};
Expand Down
23 changes: 17 additions & 6 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,34 +79,45 @@ function mapTransactionItemToSelectedEntry(item: TransactionListItemType, report
];
}

function mapToTransactionItemWithAdditionalInfo(item: TransactionListItemType, selectedTransactions: SelectedTransactions, canSelectMultiple: boolean, shouldAnimateInHighlight: boolean) {
return {...item, shouldAnimateInHighlight, isSelected: selectedTransactions[item.keyForList]?.isSelected && canSelectMultiple};
function mapToTransactionItemWithAdditionalInfo(
item: TransactionListItemType,
selectedTransactions: SelectedTransactions,
canSelectMultiple: boolean,
shouldAnimateInHighlight: boolean,
hash?: number,
) {
return {...item, shouldAnimateInHighlight, isSelected: selectedTransactions[item.keyForList]?.isSelected && canSelectMultiple, hash};
}

function mapToItemWithAdditionalInfo(item: SearchListItem, selectedTransactions: SelectedTransactions, canSelectMultiple: boolean, shouldAnimateInHighlight: boolean) {
function mapToItemWithAdditionalInfo(item: SearchListItem, selectedTransactions: SelectedTransactions, canSelectMultiple: boolean, shouldAnimateInHighlight: boolean, hash?: number) {
if (isTaskListItemType(item)) {
return {
...item,
shouldAnimateInHighlight,
hash,
};
}

if (isReportActionListItemType(item)) {
return {
...item,
shouldAnimateInHighlight,
hash,
};
}

return isTransactionListItemType(item)
? mapToTransactionItemWithAdditionalInfo(item, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight)
? mapToTransactionItemWithAdditionalInfo(item, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight, hash)
: {
...item,
shouldAnimateInHighlight,
transactions: item.transactions?.map((transaction) => mapToTransactionItemWithAdditionalInfo(transaction, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight)),
transactions: item.transactions?.map((transaction) =>
mapToTransactionItemWithAdditionalInfo(transaction, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight, hash),
),
isSelected:
item?.transactions?.length > 0 &&
item.transactions?.filter((t) => !isTransactionPendingDelete(t)).every((transaction) => selectedTransactions[transaction.keyForList]?.isSelected && canSelectMultiple),
hash,
};
}

Expand Down Expand Up @@ -507,7 +518,7 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS
// Determine if either the base key or any transaction key matches
const shouldAnimateInHighlight = isBaseKeyMatch || isAnyTransactionMatch;

return mapToItemWithAdditionalInfo(item, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight);
return mapToItemWithAdditionalInfo(item, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight, hash);
});

const hasErrors = Object.keys(searchResults?.errors ?? {}).length > 0 && !isOffline;
Expand Down
Loading
Loading