Skip to content

Commit 2bc316f

Browse files
authored
Merge pull request Expensify#67799 from Expensify/cmartins-makeFeedMultiSelect
Make Feed pill a multi select
2 parents d639c6f + 0761033 commit 2bc316f

5 files changed

Lines changed: 69 additions & 60 deletions

File tree

src/components/Search/FilterDropdowns/MultiSelectPopup.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ import Text from '@components/Text';
88
import useLocalize from '@hooks/useLocalize';
99
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1010
import useThemeStyles from '@hooks/useThemeStyles';
11-
import type {TranslationPaths} from '@src/languages/types';
1211

1312
type MultiSelectItem<T> = {
14-
translation: TranslationPaths;
13+
text: string;
1514
value: T;
1615
};
1716

@@ -41,11 +40,11 @@ function MultiSelectPopup<T extends string>({label, value, items, closeOverlay,
4140

4241
const listData: ListItem[] = useMemo(() => {
4342
return items.map((item) => ({
44-
text: translate(item.translation),
43+
text: item.text,
4544
keyForList: item.value,
4645
isSelected: !!selectedItems.find((i) => i.value === item.value),
4746
}));
48-
}, [items, selectedItems, translate]);
47+
}, [items, selectedItems]);
4948

5049
const updateSelectedItems = useCallback(
5150
(item: ListItem) => {

src/components/Search/SearchPageHeader/SearchFiltersBar.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,9 @@ function SearchFiltersBar({queryJSON, headerButtonsOptions, isMobileSelectionMod
103103
}, [unsafeGroupBy]);
104104

105105
const [feedOptions, feed] = useMemo(() => {
106-
const feedFilterValue = flatFilters
107-
.find((filter) => filter.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED)
108-
?.filters.find((filter) => filter.operator === CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO)?.value;
106+
const feedFilterValues = flatFilters.find((filter) => filter.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED)?.filters?.map((filter) => filter.value);
109107
const options = getFeedOptions(allFeeds, allCards);
110-
const value = options.find((option) => option.value === feedFilterValue) ?? null;
108+
const value = feedFilterValues ? options.filter((option) => feedFilterValues.includes(option.value)) : [];
111109
return [options, value];
112110
}, [flatFilters, allFeeds, allCards]);
113111

@@ -226,12 +224,12 @@ function SearchFiltersBar({queryJSON, headerButtonsOptions, isMobileSelectionMod
226224
const feedComponent = useCallback(
227225
({closeOverlay}: PopoverComponentProps) => {
228226
return (
229-
<SingleSelectPopup
227+
<MultiSelectPopup
230228
label={translate('search.filters.feed')}
231229
items={feedOptions}
232230
value={feed}
233231
closeOverlay={closeOverlay}
234-
onChange={(item) => updateFilterForm({feed: item ? [item.value] : undefined})}
232+
onChange={(items) => updateFilterForm({feed: items.map((item) => item.value)})}
235233
/>
236234
);
237235
},
@@ -356,7 +354,7 @@ function SearchFiltersBar({queryJSON, headerButtonsOptions, isMobileSelectionMod
356354
{
357355
label: translate('search.filters.feed'),
358356
PopoverComponent: feedComponent,
359-
value: feed?.text ?? null,
357+
value: feed.map((option) => option.text),
360358
filterKey: FILTER_KEYS.FEED,
361359
},
362360
]
@@ -374,7 +372,7 @@ function SearchFiltersBar({queryJSON, headerButtonsOptions, isMobileSelectionMod
374372
{
375373
label: translate('common.status'),
376374
PopoverComponent: statusComponent,
377-
value: status.map((option) => translate(option.translation)),
375+
value: status.map((option) => option.text),
378376
filterKey: FILTER_KEYS.STATUS,
379377
},
380378
{

src/libs/SearchUIUtils.ts

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -122,45 +122,57 @@ const taskColumnNamesToSortingProperty = {
122122
[CONST.SEARCH.TABLE_COLUMNS.IN]: 'parentReportID' as const,
123123
};
124124

125-
const expenseStatusOptions: Array<MultiSelectItem<SingularSearchStatus>> = [
126-
{translation: 'common.unreported', value: CONST.SEARCH.STATUS.EXPENSE.UNREPORTED},
127-
{translation: 'common.drafts', value: CONST.SEARCH.STATUS.EXPENSE.DRAFTS},
128-
{translation: 'common.outstanding', value: CONST.SEARCH.STATUS.EXPENSE.OUTSTANDING},
129-
{translation: 'iou.approved', value: CONST.SEARCH.STATUS.EXPENSE.APPROVED},
130-
{translation: 'iou.settledExpensify', value: CONST.SEARCH.STATUS.EXPENSE.PAID},
131-
{translation: 'iou.done', value: CONST.SEARCH.STATUS.EXPENSE.DONE},
132-
];
133-
134-
const expenseReportedStatusOptions: Array<MultiSelectItem<SingularSearchStatus>> = [
135-
{translation: 'common.drafts', value: CONST.SEARCH.STATUS.EXPENSE.DRAFTS},
136-
{translation: 'common.outstanding', value: CONST.SEARCH.STATUS.EXPENSE.OUTSTANDING},
137-
{translation: 'iou.approved', value: CONST.SEARCH.STATUS.EXPENSE.APPROVED},
138-
{translation: 'iou.settledExpensify', value: CONST.SEARCH.STATUS.EXPENSE.PAID},
139-
{translation: 'iou.done', value: CONST.SEARCH.STATUS.EXPENSE.DONE},
140-
];
141-
142-
const chatStatusOptions: Array<MultiSelectItem<SingularSearchStatus>> = [
143-
{translation: 'common.unread', value: CONST.SEARCH.STATUS.CHAT.UNREAD},
144-
{translation: 'common.sent', value: CONST.SEARCH.STATUS.CHAT.SENT},
145-
{translation: 'common.attachments', value: CONST.SEARCH.STATUS.CHAT.ATTACHMENTS},
146-
{translation: 'common.links', value: CONST.SEARCH.STATUS.CHAT.LINKS},
147-
{translation: 'search.filters.pinned', value: CONST.SEARCH.STATUS.CHAT.PINNED},
148-
];
149-
150-
const invoiceStatusOptions: Array<MultiSelectItem<SingularSearchStatus>> = [
151-
{translation: 'common.outstanding', value: CONST.SEARCH.STATUS.INVOICE.OUTSTANDING},
152-
{translation: 'iou.settledExpensify', value: CONST.SEARCH.STATUS.INVOICE.PAID},
153-
];
154-
155-
const tripStatusOptions: Array<MultiSelectItem<SingularSearchStatus>> = [
156-
{translation: 'search.filters.current', value: CONST.SEARCH.STATUS.TRIP.CURRENT},
157-
{translation: 'search.filters.past', value: CONST.SEARCH.STATUS.TRIP.PAST},
158-
];
159-
160-
const taskStatusOptions: Array<MultiSelectItem<SingularSearchStatus>> = [
161-
{translation: 'common.outstanding', value: CONST.SEARCH.STATUS.TASK.OUTSTANDING},
162-
{translation: 'search.filters.completed', value: CONST.SEARCH.STATUS.TASK.COMPLETED},
163-
];
125+
function getExpenseStatusOptions(): Array<MultiSelectItem<SingularSearchStatus>> {
126+
return [
127+
{text: translateLocal('common.unreported'), value: CONST.SEARCH.STATUS.EXPENSE.UNREPORTED},
128+
{text: translateLocal('common.drafts'), value: CONST.SEARCH.STATUS.EXPENSE.DRAFTS},
129+
{text: translateLocal('common.outstanding'), value: CONST.SEARCH.STATUS.EXPENSE.OUTSTANDING},
130+
{text: translateLocal('iou.approved'), value: CONST.SEARCH.STATUS.EXPENSE.APPROVED},
131+
{text: translateLocal('iou.settledExpensify'), value: CONST.SEARCH.STATUS.EXPENSE.PAID},
132+
{text: translateLocal('iou.done'), value: CONST.SEARCH.STATUS.EXPENSE.DONE},
133+
];
134+
}
135+
136+
function getExpenseReportedStatusOptions(): Array<MultiSelectItem<SingularSearchStatus>> {
137+
return [
138+
{text: translateLocal('common.drafts'), value: CONST.SEARCH.STATUS.EXPENSE.DRAFTS},
139+
{text: translateLocal('common.outstanding'), value: CONST.SEARCH.STATUS.EXPENSE.OUTSTANDING},
140+
{text: translateLocal('iou.approved'), value: CONST.SEARCH.STATUS.EXPENSE.APPROVED},
141+
{text: translateLocal('iou.settledExpensify'), value: CONST.SEARCH.STATUS.EXPENSE.PAID},
142+
{text: translateLocal('iou.done'), value: CONST.SEARCH.STATUS.EXPENSE.DONE},
143+
];
144+
}
145+
146+
function getChatStatusOptions(): Array<MultiSelectItem<SingularSearchStatus>> {
147+
return [
148+
{text: translateLocal('common.unread'), value: CONST.SEARCH.STATUS.CHAT.UNREAD},
149+
{text: translateLocal('common.sent'), value: CONST.SEARCH.STATUS.CHAT.SENT},
150+
{text: translateLocal('common.attachments'), value: CONST.SEARCH.STATUS.CHAT.ATTACHMENTS},
151+
{text: translateLocal('common.links'), value: CONST.SEARCH.STATUS.CHAT.LINKS},
152+
{text: translateLocal('search.filters.pinned'), value: CONST.SEARCH.STATUS.CHAT.PINNED},
153+
];
154+
}
155+
156+
function getInvoiceStatusOptions(): Array<MultiSelectItem<SingularSearchStatus>> {
157+
return [
158+
{text: translateLocal('common.outstanding'), value: CONST.SEARCH.STATUS.INVOICE.OUTSTANDING},
159+
{text: translateLocal('iou.settledExpensify'), value: CONST.SEARCH.STATUS.INVOICE.PAID},
160+
];
161+
}
162+
163+
function getTripStatusOptions(): Array<MultiSelectItem<SingularSearchStatus>> {
164+
return [
165+
{text: translateLocal('search.filters.current'), value: CONST.SEARCH.STATUS.TRIP.CURRENT},
166+
{text: translateLocal('search.filters.past'), value: CONST.SEARCH.STATUS.TRIP.PAST},
167+
];
168+
}
169+
170+
function getTaskStatusOptions(): Array<MultiSelectItem<SingularSearchStatus>> {
171+
return [
172+
{text: translateLocal('common.outstanding'), value: CONST.SEARCH.STATUS.TASK.OUTSTANDING},
173+
{text: translateLocal('search.filters.completed'), value: CONST.SEARCH.STATUS.TASK.COMPLETED},
174+
];
175+
}
164176

165177
let currentAccountID: number | undefined;
166178
Onyx.connect({
@@ -1817,16 +1829,16 @@ function isSearchDataLoaded(searchResults: SearchResults | undefined, queryJSON:
18171829
function getStatusOptions(type: SearchDataTypes, groupBy: SearchGroupBy | undefined) {
18181830
switch (type) {
18191831
case CONST.SEARCH.DATA_TYPES.CHAT:
1820-
return chatStatusOptions;
1832+
return getChatStatusOptions();
18211833
case CONST.SEARCH.DATA_TYPES.INVOICE:
1822-
return invoiceStatusOptions;
1834+
return getInvoiceStatusOptions();
18231835
case CONST.SEARCH.DATA_TYPES.TRIP:
1824-
return tripStatusOptions;
1836+
return getTripStatusOptions();
18251837
case CONST.SEARCH.DATA_TYPES.TASK:
1826-
return taskStatusOptions;
1838+
return getTaskStatusOptions();
18271839
case CONST.SEARCH.DATA_TYPES.EXPENSE:
18281840
default:
1829-
return groupBy === CONST.SEARCH.GROUP_BY.REPORTS || groupBy === CONST.SEARCH.GROUP_BY.MEMBERS ? expenseReportedStatusOptions : expenseStatusOptions;
1841+
return groupBy === CONST.SEARCH.GROUP_BY.REPORTS || groupBy === CONST.SEARCH.GROUP_BY.MEMBERS ? getExpenseReportedStatusOptions() : getExpenseStatusOptions();
18301842
}
18311843
}
18321844

src/pages/Search/AdvancedSearchFilters.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ function getFilterDisplayTitle(
473473
}
474474

475475
function getStatusFilterDisplayTitle(filters: Partial<SearchAdvancedFiltersForm>, type: SearchDataTypes, groupBy: SearchGroupBy | undefined, translate: LocaleContextProps['translate']) {
476-
const statusOptions = getStatusOptions(type, groupBy).concat({translation: 'common.all', value: CONST.SEARCH.STATUS.EXPENSE.ALL});
476+
const statusOptions = getStatusOptions(type, groupBy).concat({text: translate('common.all'), value: CONST.SEARCH.STATUS.EXPENSE.ALL});
477477
let filterValue = filters?.status;
478478

479479
if (!filterValue?.length) {
@@ -488,7 +488,7 @@ function getStatusFilterDisplayTitle(filters: Partial<SearchAdvancedFiltersForm>
488488
.reduce((acc, value) => {
489489
const status = statusOptions.find((statusOption) => statusOption.value === value);
490490
if (status) {
491-
return acc.concat(translate(status.translation));
491+
return acc.concat(status.text);
492492
}
493493
return acc;
494494
}, [] as string[])

src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersStatusPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ function SearchFiltersStatusPage() {
4040

4141
const listData: ListItem[] = useMemo(() => {
4242
return items.map((statusOption) => ({
43-
text: translate(statusOption.translation),
43+
text: statusOption.text,
4444
keyForList: statusOption.value,
4545
isSelected: selectedItems.includes(statusOption.value),
4646
}));
47-
}, [items, selectedItems, translate]);
47+
}, [items, selectedItems]);
4848

4949
const updateSelectedItems = useCallback(
5050
(listItem: ListItem) => {

0 commit comments

Comments
 (0)