Skip to content
5 changes: 2 additions & 3 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
isReportListItemType,
isSearchResultsEmpty as isSearchResultsEmptyUtil,
isTransactionListItemType,
shouldShowEmptyState,
shouldShowYear as shouldShowYearUtil,
} from '@libs/SearchUIUtils';
import {isOnHold} from '@libs/TransactionUtils';
Expand Down Expand Up @@ -379,9 +380,7 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
return mapToItemWithSelectionInfo(item, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight);
});

const shouldShowEmptyState = !isDataLoaded || data.length === 0;

if (shouldShowEmptyState) {
if (shouldShowEmptyState(isDataLoaded, data.length, searchResults.search.type)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also shouldn't show the empty state when there's any action that is currently loading.

More details:
#80424 (comment)

return (
<View style={[shouldUseNarrowLayout ? styles.searchListContentContainerStyles : styles.mt3, styles.flex1]}>
<EmptySearchView
Expand Down
7 changes: 4 additions & 3 deletions src/components/SelectionList/SearchTableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import * as SearchUIUtils from '@libs/SearchUIUtils';
import {getShouldShowMerchant} from '@libs/SearchUIUtils';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
import type * as OnyxTypes from '@src/types/onyx';
Expand Down Expand Up @@ -39,12 +39,12 @@ const expenseHeaders: SearchColumnConfig[] = [
{
columnName: CONST.SEARCH.TABLE_COLUMNS.MERCHANT,
translationKey: 'common.merchant',
shouldShow: (data: OnyxTypes.SearchResults['data']) => SearchUIUtils.getShouldShowMerchant(data),
shouldShow: (data: OnyxTypes.SearchResults['data']) => getShouldShowMerchant(data),
},
{
columnName: CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION,
translationKey: 'common.description',
shouldShow: (data: OnyxTypes.SearchResults['data']) => !SearchUIUtils.getShouldShowMerchant(data),
shouldShow: (data: OnyxTypes.SearchResults['data']) => !getShouldShowMerchant(data),
},
{
columnName: CONST.SEARCH.TABLE_COLUMNS.FROM,
Expand Down Expand Up @@ -151,3 +151,4 @@ function SearchTableHeader({data, metadata, sortBy, sortOrder, onSortPress, shou
SearchTableHeader.displayName = 'SearchTableHeader';

export default SearchTableHeader;
export {SearchColumns};
9 changes: 9 additions & 0 deletions src/libs/SearchUIUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {SearchColumnType, SearchStatus, SortOrder} from '@components/Search
import ChatListItem from '@components/SelectionList/ChatListItem';
import ReportListItem from '@components/SelectionList/Search/ReportListItem';
import TransactionListItem from '@components/SelectionList/Search/TransactionListItem';
import {SearchColumns} from '@components/SelectionList/SearchTableHeader';
import type {ListItem, ReportActionListItemType, ReportListItemType, TransactionListItemType} from '@components/SelectionList/types';
import * as Expensicons from '@src/components/Icon/Expensicons';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -784,6 +785,13 @@ function createBaseSavedSearchMenuItem(item: SaveSearchItem, key: string, index:
};
}

/**
* Whether to show the empty state or not
*/
function shouldShowEmptyState(isDataLoaded: boolean, dataLength: number, type: SearchDataTypes) {
return !isDataLoaded || dataLength === 0 || !Object.hasOwn(SearchColumns, type);
}

export {
getListItem,
getSections,
Expand All @@ -801,5 +809,6 @@ export {
getAction,
createTypeMenuItems,
createBaseSavedSearchMenuItem,
shouldShowEmptyState,
};
export type {SavedSearchMenuItem, SearchTypeMenuItem};
9 changes: 9 additions & 0 deletions tests/unit/Search/SearchUIUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as SearchUIUtils from '@src/libs/SearchUIUtils';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates';

const adminAccountID = 18439984;
Expand Down Expand Up @@ -1388,4 +1389,12 @@ describe('SearchUIUtils', () => {
expect(action).toEqual(CONST.SEARCH.ACTION_TYPES.VIEW);
});
});

test('Should return true if the search result has valid type', () => {
expect(SearchUIUtils.shouldShowEmptyState(false, reportsListItems.length, searchResults.search.type)).toBe(true);
expect(SearchUIUtils.shouldShowEmptyState(true, 0, searchResults.search.type)).toBe(true);
const inValidSearchType: SearchDataTypes = 'expensse' as SearchDataTypes;
expect(SearchUIUtils.shouldShowEmptyState(true, reportsListItems.length, inValidSearchType)).toBe(true);
expect(SearchUIUtils.shouldShowEmptyState(true, reportsListItems.length, searchResults.search.type)).toBe(false);
});
});
Loading