Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {saveLastSearchParams} from '@userActions/ReportNavigation';
import {search} from '@userActions/Search';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {isActionLoadingSetSelector} from '@src/selectors/ReportMetaData';

type MoneyRequestReportNavigationProps = {
reportID?: string;
Expand All @@ -25,6 +26,7 @@ function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: Mo
const [currentSearchResults] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${lastSearchQuery?.queryJSON?.hash}`, {canBeMissing: true});
const currentUserDetails = useCurrentUserPersonalDetails();
const {localeCompare, formatPhoneNumber} = useLocalize();
const [isActionLoadingSet = new Set<string>()] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}`, {canBeMissing: true, selector: isActionLoadingSetSelector});

const [exportReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS, {
canEvict: false,
Expand All @@ -37,17 +39,18 @@ function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: Mo
const {type, status, sortBy, sortOrder, groupBy} = lastSearchQuery?.queryJSON ?? {};
let results: Array<string | undefined> = [];
if (!!type && !!currentSearchResults?.data && !!currentSearchResults?.search) {
const searchData = getSections(
const searchData = getSections({
type,
currentSearchResults.data,
currentUserDetails.accountID,
currentUserDetails.email ?? '',
data: currentSearchResults.data,
currentAccountID: currentUserDetails.accountID,
currentUserEmail: currentUserDetails.email ?? '',
formatPhoneNumber,
groupBy,
exportReportActions,
lastSearchQuery?.searchKey,
archivedReportsIdSet,
);
reportActions: exportReportActions,
currentSearch: lastSearchQuery?.searchKey,
archivedReportsIDList: archivedReportsIdSet,
isActionLoadingSet,
});
results = getSortedSections(type, status ?? '', searchData, localeCompare, sortBy, sortOrder, groupBy).map((value) => value.reportID);
}
const allReports = results;
Expand Down
18 changes: 16 additions & 2 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import {isActionLoadingSetSelector} from '@src/selectors/ReportMetaData';
import type {OutstandingReportsByPolicyIDDerivedValue} from '@src/types/onyx';
import type Policy from '@src/types/onyx/Policy';
import type Report from '@src/types/onyx/Report';
Expand Down Expand Up @@ -258,6 +259,7 @@ function Search({
const [outstandingReportsByPolicyID] = useOnyx(ONYXKEYS.DERIVED.OUTSTANDING_REPORTS_BY_POLICY_ID, {canBeMissing: true});
const [violations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true});
const {accountID, email} = useCurrentUserPersonalDetails();
const [isActionLoadingSet = new Set<string>()] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}`, {canBeMissing: true, selector: isActionLoadingSetSelector});

// Filter violations based on user visibility
const filteredViolations = useMemo(() => {
Expand Down Expand Up @@ -406,9 +408,21 @@ function Search({
return [[], 0];
}

const data1 = getSections(type, searchResults.data, accountID, email ?? '', formatPhoneNumber, validGroupBy, exportReportActions, searchKey, archivedReportsIdSet, queryJSON);
const data1 = getSections({
type,
data: searchResults.data,
currentAccountID: accountID,
currentUserEmail: email ?? '',
formatPhoneNumber,
groupBy: validGroupBy,
reportActions: exportReportActions,
currentSearch: searchKey,
archivedReportsIDList: archivedReportsIdSet,
queryJSON,
isActionLoadingSet,
});
return [data1, data1.length];
}, [searchKey, exportReportActions, validGroupBy, isDataLoaded, searchResults, type, archivedReportsIdSet, formatPhoneNumber, accountID, queryJSON, email]);
}, [searchKey, exportReportActions, validGroupBy, isDataLoaded, searchResults, type, archivedReportsIdSet, formatPhoneNumber, accountID, queryJSON, email, isActionLoadingSet]);

useEffect(() => {
/** We only want to display the skeleton for the status filters the first time we load them for a specific data type */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
import {handleActionButtonPress} from '@userActions/Search';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {isActionLoadingSelector} from '@src/selectors/ReportMetaData';
import type {Policy} from '@src/types/onyx';
import type {SearchReport} from '@src/types/onyx/SearchResults';
import ActionCell from './ActionCell';
Expand Down Expand Up @@ -108,6 +109,7 @@ function HeaderFirstRow<TItem extends ListItem>({
const StyleUtils = useStyleUtils();
const {isLargeScreenWidth} = useResponsiveLayout();
const theme = useTheme();
const [isActionLoading] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportItem.reportID}`, {canBeMissing: true, selector: isActionLoadingSelector});

const {total, currency} = useMemo(() => {
let reportTotal = reportItem.total ?? 0;
Expand Down Expand Up @@ -180,7 +182,7 @@ function HeaderFirstRow<TItem extends ListItem>({
action={reportItem.action}
goToItem={handleOnButtonPress}
isSelected={reportItem.isSelected}
isLoading={reportItem.isActionLoading}
isLoading={isActionLoading}
policyID={reportItem.policyID}
reportID={reportItem.reportID}
hash={reportItem.hash}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {getSections} from '@libs/SearchUIUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {isActionLoadingSetSelector} from '@src/selectors/ReportMetaData';
import type {ReportAction, ReportActions} from '@src/types/onyx';
import CardListItemHeader from './CardListItemHeader';
import MemberListItemHeader from './MemberListItemHeader';
Expand Down Expand Up @@ -94,6 +95,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
const [transactionsVisibleLimit, setTransactionsVisibleLimit] = useState(CONST.TRANSACTION.RESULTS_PAGE_SIZE as number);
const [isExpanded, setIsExpanded] = useState(false);
const [isActionLoadingSet = new Set<string>()] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}`, {canBeMissing: true, selector: isActionLoadingSetSelector});

const transactions = useMemo(() => {
if (isExpenseReportType) {
Expand All @@ -102,18 +104,19 @@ function TransactionGroupListItem<TItem extends ListItem>({
if (!transactionsSnapshot?.data) {
return [];
}
const sectionData = getSections(
CONST.SEARCH.DATA_TYPES.EXPENSE,
transactionsSnapshot?.data,
accountID,
currentUserDetails.email ?? '',
const sectionData = getSections({
type: CONST.SEARCH.DATA_TYPES.EXPENSE,
data: transactionsSnapshot?.data,
currentAccountID: accountID,
currentUserEmail: currentUserDetails.email ?? '',
formatPhoneNumber,
) as TransactionListItemType[];
isActionLoadingSet,
}) as TransactionListItemType[];
return sectionData.map((transactionItem) => ({
...transactionItem,
isSelected: selectedTransactionIDsSet.has(transactionItem.transactionID),
}));
}, [isExpenseReportType, transactionsSnapshot?.data, accountID, formatPhoneNumber, groupItem.transactions, selectedTransactionIDsSet, currentUserDetails.email]);
}, [isExpenseReportType, transactionsSnapshot?.data, accountID, formatPhoneNumber, groupItem.transactions, selectedTransactionIDsSet, currentUserDetails.email, isActionLoadingSet]);

const selectedItemsLength = useMemo(() => {
return transactions.reduce((acc, transaction) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {isViolationDismissed, shouldShowViolation} from '@libs/TransactionUtils'
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {isActionLoadingSelector} from '@src/selectors/ReportMetaData';
import type {Policy, ReportAction, ReportActions} from '@src/types/onyx';
import type {SearchReport} from '@src/types/onyx/SearchResults';
import type {TransactionViolation} from '@src/types/onyx/TransactionViolation';
Expand Down Expand Up @@ -58,6 +59,8 @@ function TransactionListItem<TItem extends ListItem>({
return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionItem.reportID}`] ?? {}) as SearchReport;
}, [snapshot, transactionItem.reportID]);

const [isActionLoading] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${transactionItem.reportID}`, {canBeMissing: true, selector: isActionLoadingSelector});

const snapshotPolicy = useMemo(() => {
return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${transactionItem.policyID}`] ?? {}) as Policy;
}, [snapshot, transactionItem.policyID]);
Expand Down Expand Up @@ -176,7 +179,7 @@ function TransactionListItem<TItem extends ListItem>({
onCheckboxPress={handleCheckboxPress}
shouldUseNarrowLayout={!isLargeScreenWidth}
columns={columns}
isActionLoading={isLoading ?? transactionItem.isActionLoading ?? snapshotReport.isActionLoading}
isActionLoading={isLoading ?? transactionItem.isActionLoading ?? isActionLoading}
isSelected={!!transactionItem.isSelected}
dateColumnSize={dateColumnSize}
amountColumnSize={amountColumnSize}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, {useMemo} from 'react';
import React from 'react';
import {View} from 'react-native';
import type {StyleProp, ViewStyle} from 'react-native';
import {useSearchContext} from '@components/Search/SearchContext';
import type {TransactionListItemType, TransactionReportGroupListItemType} from '@components/SelectionListWithSections/types';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
Expand All @@ -11,7 +10,7 @@ import {isCorrectSearchUserName} from '@libs/SearchUIUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {SearchReport} from '@src/types/onyx/SearchResults';
import {isActionLoadingSelector} from '@src/selectors/ReportMetaData';
import ActionCell from './ActionCell';
import UserInfoCellsWithArrow from './UserInfoCellsWithArrow';

Expand All @@ -32,19 +31,13 @@ function UserInfoAndActionButtonRow({
const {isLargeScreenWidth} = useResponsiveLayout();
const {translate} = useLocalize();
const transactionItem = item as unknown as TransactionListItemType;
const {currentSearchHash} = useSearchContext();
const [snapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${currentSearchHash}`, {canBeMissing: true});
const [isActionLoading] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${transactionItem.reportID}`, {canBeMissing: true, selector: isActionLoadingSelector});
const hasFromSender = !!item?.from && !!item?.from?.accountID && !!item?.from?.displayName;
const hasToRecipient = !!item?.to && !!item?.to?.accountID && !!item?.to?.displayName;
const participantFromDisplayName = item?.from?.displayName ?? item?.from?.login ?? translate('common.hidden');
const participantToDisplayName = item?.to?.displayName ?? item?.to?.login ?? translate('common.hidden');
const shouldShowToRecipient = hasFromSender && hasToRecipient && !!item?.to?.accountID && !!isCorrectSearchUserName(participantToDisplayName);

const snapshotReport = useMemo(() => {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionItem.reportID}`] ?? {}) as SearchReport;
}, [snapshot, transactionItem.reportID]);

const isLoading = 'isActionLoading' in item ? item?.isActionLoading : isActionLoading;
return (
<View
style={[
Expand Down Expand Up @@ -77,7 +70,7 @@ function UserInfoAndActionButtonRow({
action={item.action}
goToItem={handleActionButtonPress}
isSelected={item.isSelected}
isLoading={item.isActionLoading ?? snapshotReport.isActionLoading}
isLoading={isLoading}
policyID={item.policyID}
reportID={item.reportID}
hash={item.hash}
Expand Down
44 changes: 30 additions & 14 deletions src/libs/SearchUIUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,20 @@ type SearchDateModifierLower = Lowercase<SearchDateModifier>;

type ArchivedReportsIDSet = ReadonlySet<string>;

type GetSectionsParams = {
type: SearchDataTypes;
data: OnyxTypes.SearchResults['data'];
currentAccountID: number | undefined;
currentUserEmail: string;
formatPhoneNumber: LocaleContextProps['formatPhoneNumber'];
groupBy?: SearchGroupBy;
reportActions?: Record<string, OnyxTypes.ReportAction[]>;
currentSearch?: SearchKey;
archivedReportsIDList?: ArchivedReportsIDSet;
queryJSON?: SearchQueryJSON;
isActionLoadingSet?: ReadonlySet<string>;
};

/**
* Returns a list of all possible searches in the LHN, along with their query & hash.
* *NOTE* When rendering the LHN, you should use the "createTypeMenuSections" method, which
Expand Down Expand Up @@ -1418,6 +1432,7 @@ function getReportSections(
currentAccountID: number | undefined,
currentUserEmail: string,
formatPhoneNumber: LocaleContextProps['formatPhoneNumber'],
isActionLoadingSet: ReadonlySet<string> | undefined,
reportActions: Record<string, OnyxTypes.ReportAction[]> = {},
): TransactionGroupListItemType[] {
const shouldShowMerchant = getShouldShowMerchant(data);
Expand Down Expand Up @@ -1455,7 +1470,7 @@ function getReportSections(
const actions = reportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportItem.reportID}`];

let shouldShow = true;
if (queryJSON && !reportItem.isActionLoading) {
if (queryJSON && isActionLoadingSet?.has(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportItem.reportID}`)) {
if (queryJSON.type === CONST.SEARCH.DATA_TYPES.EXPENSE) {
const status = queryJSON.status;

Expand Down Expand Up @@ -1669,18 +1684,19 @@ function getListItem(type: SearchDataTypes, status: SearchStatus, groupBy?: Sear
/**
* Organizes data into appropriate list sections for display based on the type of search results.
*/
function getSections(
type: SearchDataTypes,
data: OnyxTypes.SearchResults['data'],
currentAccountID: number | undefined,
currentUserEmail: string,
formatPhoneNumber: LocaleContextProps['formatPhoneNumber'],
groupBy?: SearchGroupBy,
reportActions: Record<string, OnyxTypes.ReportAction[]> = {},
currentSearch: SearchKey = CONST.SEARCH.SEARCH_KEYS.EXPENSES,
archivedReportsIDList?: ArchivedReportsIDSet,
queryJSON?: SearchQueryJSON,
) {
function getSections({
type,
data,
currentAccountID,
currentUserEmail,
formatPhoneNumber,
groupBy,
reportActions = {},
currentSearch = CONST.SEARCH.SEARCH_KEYS.EXPENSES,
archivedReportsIDList,
queryJSON,
isActionLoadingSet,
}: GetSectionsParams) {
if (type === CONST.SEARCH.DATA_TYPES.CHAT) {
return getReportActionsSections(data);
}
Expand All @@ -1689,7 +1705,7 @@ function getSections(
}

if (type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT) {
return getReportSections(data, currentSearch, currentAccountID, currentUserEmail, formatPhoneNumber, reportActions);
return getReportSections(data, currentSearch, currentAccountID, currentUserEmail, formatPhoneNumber, isActionLoadingSet, reportActions);
}

if (groupBy) {
Expand Down
Loading
Loading