Skip to content

Commit a6d5615

Browse files
authored
Merge pull request Expensify#67119 from Expensify/revert-66040-krishna2323/issue/65131
Revert "fix: Selected To/From accounts in Filters not surfaced to top in FilterBar dropdown."
2 parents bde1509 + ad8d5b9 commit a6d5615

4 files changed

Lines changed: 155 additions & 121 deletions

File tree

src/components/Search/FilterDropdowns/UserSelectPopup.tsx

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
import React, {memo, useCallback, useState} from 'react';
1+
import isEmpty from 'lodash/isEmpty';
2+
import React, {memo, useCallback, useMemo, useState} from 'react';
23
import {View} from 'react-native';
34
import Button from '@components/Button';
45
import {usePersonalDetails} from '@components/OnyxListItemProvider';
6+
import {useOptionsList} from '@components/OptionListContextProvider';
57
import SelectionList from '@components/SelectionList';
68
import UserSelectionListItem from '@components/SelectionList/Search/UserSelectionListItem';
79
import useLocalize from '@hooks/useLocalize';
810
import useOnyx from '@hooks/useOnyx';
911
import useResponsiveLayout from '@hooks/useResponsiveLayout';
10-
import useSearchParticipantsOptions from '@hooks/useSearchParticipantsOptions';
1112
import useThemeStyles from '@hooks/useThemeStyles';
1213
import useWindowDimensions from '@hooks/useWindowDimensions';
1314
import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus';
14-
import type {Option} from '@libs/OptionsListUtils';
15+
import type {Option, Section} from '@libs/OptionsListUtils';
16+
import {filterAndOrderOptions, getValidOptions} from '@libs/OptionsListUtils';
1517
import type {OptionData} from '@libs/ReportUtils';
18+
import CONST from '@src/CONST';
1619
import ONYXKEYS from '@src/ONYXKEYS';
1720

1821
function getSelectedOptionData(option: Option) {
@@ -33,9 +36,11 @@ type UserSelectPopupProps = {
3336
function UserSelectPopup({value, closeOverlay, onChange}: UserSelectPopupProps) {
3437
const styles = useThemeStyles();
3538
const {translate} = useLocalize();
39+
const {options} = useOptionsList();
3640
const personalDetails = usePersonalDetails();
3741
const {windowHeight} = useWindowDimensions();
3842
const {shouldUseNarrowLayout} = useResponsiveLayout();
43+
const [accountID] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: true, selector: (onyxSession) => onyxSession?.accountID});
3944
const shouldFocusInputOnScreenFocus = canFocusInputOnScreenFocus();
4045

4146
const [searchTerm, setSearchTerm] = useState('');
@@ -57,10 +62,64 @@ function UserSelectPopup({value, closeOverlay, onChange}: UserSelectPopupProps)
5762
});
5863

5964
const cleanSearchTerm = searchTerm.trim().toLowerCase();
60-
const {sections, headerMessage, areOptionsInitialized} = useSearchParticipantsOptions({
61-
selectedOptions: selectedOptions as OptionData[],
62-
cleanSearchTerm,
63-
});
65+
66+
// Get a list of all options/personal details and filter them by the current search term
67+
const listData = useMemo(() => {
68+
const optionsList = getValidOptions(
69+
{
70+
reports: options.reports,
71+
personalDetails: options.personalDetails,
72+
},
73+
{
74+
selectedOptions,
75+
excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
76+
includeSelectedOptions: true,
77+
includeCurrentUser: true,
78+
},
79+
);
80+
81+
const {personalDetails: filteredOptionsList, recentReports} = filterAndOrderOptions(optionsList, cleanSearchTerm, {
82+
excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
83+
maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW,
84+
canInviteUser: false,
85+
});
86+
87+
const personalDetailList = filteredOptionsList
88+
.map((participant) => ({
89+
...participant,
90+
isSelected: selectedOptions.some((selectedOption) => selectedOption.accountID === participant.accountID),
91+
}))
92+
.sort((a, b) => {
93+
// Put the current user at the top of the list
94+
if (a.accountID === accountID) {
95+
return -1;
96+
}
97+
if (b.accountID === accountID) {
98+
return 1;
99+
}
100+
return 0;
101+
});
102+
103+
return [...(personalDetailList ?? []), ...(recentReports ?? [])];
104+
}, [cleanSearchTerm, options.personalDetails, options.reports, selectedOptions, accountID]);
105+
106+
const {sections, headerMessage} = useMemo(() => {
107+
const newSections: Section[] = [
108+
{
109+
title: '',
110+
data: listData,
111+
shouldShow: !isEmpty(listData),
112+
},
113+
];
114+
115+
const noResultsFound = isEmpty(listData);
116+
const message = noResultsFound ? translate('common.noResultsFound') : undefined;
117+
118+
return {
119+
sections: newSections,
120+
headerMessage: message,
121+
};
122+
}, [listData, translate]);
64123

65124
const selectUser = useCallback(
66125
(option: Option) => {
@@ -113,7 +172,6 @@ function UserSelectPopup({value, closeOverlay, onChange}: UserSelectPopupProps)
113172
onSelectRow={selectUser}
114173
onChangeText={setSearchTerm}
115174
isLoadingNewOptions={isLoadingNewOptions}
116-
showLoadingPlaceholder={!areOptionsInitialized}
117175
/>
118176

119177
<View style={[styles.flexRow, styles.gap2, styles.mh5, !shouldUseNarrowLayout && styles.mb4]}>

src/components/Search/SearchFiltersParticipantsSelector.tsx

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,30 @@
11
import React, {useCallback, useEffect, useMemo, useState} from 'react';
22
import {usePersonalDetails} from '@components/OnyxListItemProvider';
3+
import {useOptionsList} from '@components/OptionListContextProvider';
34
import SelectionList from '@components/SelectionList';
45
import UserSelectionListItem from '@components/SelectionList/Search/UserSelectionListItem';
56
import useLocalize from '@hooks/useLocalize';
67
import useOnyx from '@hooks/useOnyx';
78
import useScreenWrapperTransitionStatus from '@hooks/useScreenWrapperTransitionStatus';
8-
import useSearchParticipantsOptions from '@hooks/useSearchParticipantsOptions';
99
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
10-
import type {Option} from '@libs/OptionsListUtils';
10+
import {filterAndOrderOptions, formatSectionsFromSearchTerm, getValidOptions} from '@libs/OptionsListUtils';
11+
import type {Option, Section} from '@libs/OptionsListUtils';
1112
import type {OptionData} from '@libs/ReportUtils';
13+
import {getDisplayNameForParticipant} from '@libs/ReportUtils';
1214
import Navigation from '@navigation/Navigation';
15+
import CONST from '@src/CONST';
1316
import ONYXKEYS from '@src/ONYXKEYS';
1417
import ROUTES from '@src/ROUTES';
1518
import SearchFilterPageFooterButtons from './SearchFilterPageFooterButtons';
1619

20+
const defaultListOptions = {
21+
userToInvite: null,
22+
recentReports: [],
23+
personalDetails: [],
24+
currentUserOption: null,
25+
headerMessage: '',
26+
};
27+
1728
function getSelectedOptionData(option: Option): OptionData {
1829
// eslint-disable-next-line rulesdir/no-default-id-values
1930
return {...option, selected: true, reportID: option.reportID ?? '-1'};
@@ -28,17 +39,87 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}:
2839
const {translate} = useLocalize();
2940
const personalDetails = usePersonalDetails();
3041
const {didScreenTransitionEnd} = useScreenWrapperTransitionStatus();
42+
const {options, areOptionsInitialized} = useOptionsList({
43+
shouldInitialize: didScreenTransitionEnd,
44+
});
3145

3246
const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {canBeMissing: false, initWithStoredValues: false});
3347
const [selectedOptions, setSelectedOptions] = useState<OptionData[]>([]);
3448
const [searchTerm, setSearchTerm] = useState('');
3549
const cleanSearchTerm = useMemo(() => searchTerm.trim().toLowerCase(), [searchTerm]);
3650

37-
const {sections, headerMessage, areOptionsInitialized} = useSearchParticipantsOptions({
38-
selectedOptions,
39-
cleanSearchTerm,
40-
shouldInitialize: didScreenTransitionEnd,
41-
});
51+
const defaultOptions = useMemo(() => {
52+
if (!areOptionsInitialized) {
53+
return defaultListOptions;
54+
}
55+
56+
return getValidOptions(
57+
{
58+
reports: options.reports,
59+
personalDetails: options.personalDetails,
60+
},
61+
{
62+
selectedOptions,
63+
excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
64+
},
65+
);
66+
}, [areOptionsInitialized, options.personalDetails, options.reports, selectedOptions]);
67+
68+
const chatOptions = useMemo(() => {
69+
return filterAndOrderOptions(defaultOptions, cleanSearchTerm, {
70+
selectedOptions,
71+
excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
72+
maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW,
73+
canInviteUser: false,
74+
});
75+
}, [defaultOptions, cleanSearchTerm, selectedOptions]);
76+
77+
const {sections, headerMessage} = useMemo(() => {
78+
const newSections: Section[] = [];
79+
if (!areOptionsInitialized) {
80+
return {sections: [], headerMessage: undefined};
81+
}
82+
83+
const formattedResults = formatSectionsFromSearchTerm(cleanSearchTerm, selectedOptions, chatOptions.recentReports, chatOptions.personalDetails, personalDetails, true);
84+
85+
const selectedCurrentUser = formattedResults.section.data.find((option) => option.accountID === chatOptions.currentUserOption?.accountID);
86+
87+
if (chatOptions.currentUserOption) {
88+
const formattedName = getDisplayNameForParticipant({
89+
accountID: chatOptions.currentUserOption.accountID,
90+
shouldAddCurrentUserPostfix: true,
91+
personalDetailsData: personalDetails,
92+
});
93+
if (selectedCurrentUser) {
94+
selectedCurrentUser.text = formattedName;
95+
} else {
96+
chatOptions.currentUserOption.text = formattedName;
97+
chatOptions.recentReports = [chatOptions.currentUserOption, ...chatOptions.recentReports];
98+
}
99+
}
100+
101+
newSections.push(formattedResults.section);
102+
103+
newSections.push({
104+
title: '',
105+
data: chatOptions.recentReports,
106+
shouldShow: chatOptions.recentReports.length > 0,
107+
});
108+
109+
newSections.push({
110+
title: '',
111+
data: chatOptions.personalDetails,
112+
shouldShow: chatOptions.personalDetails.length > 0,
113+
});
114+
115+
const noResultsFound = chatOptions.personalDetails.length === 0 && chatOptions.recentReports.length === 0 && !chatOptions.currentUserOption;
116+
const message = noResultsFound ? translate('common.noResultsFound') : undefined;
117+
118+
return {
119+
sections: newSections,
120+
headerMessage: message,
121+
};
122+
}, [areOptionsInitialized, cleanSearchTerm, selectedOptions, chatOptions, personalDetails, translate]);
42123

43124
const resetChanges = useCallback(() => {
44125
setSelectedOptions([]);

src/hooks/useSearchParticipantsOptions.ts

Lines changed: 0 additions & 105 deletions
This file was deleted.

src/libs/OptionsListUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2327,7 +2327,7 @@ function getFirstKeyForList(data?: Option[] | null) {
23272327
}
23282328

23292329
function getPersonalDetailSearchTerms(item: Partial<OptionData>) {
2330-
return [item.participantsList?.[0]?.displayName ?? item?.displayName ?? '', item.login ?? '', item.login?.replace(CONST.EMAIL_SEARCH_REGEX, '') ?? ''];
2330+
return [item.participantsList?.[0]?.displayName ?? '', item.login ?? '', item.login?.replace(CONST.EMAIL_SEARCH_REGEX, '') ?? ''];
23312331
}
23322332

23332333
function getCurrentUserSearchTerms(item: OptionData) {

0 commit comments

Comments
 (0)