Skip to content

Suggested Search & Filter Revamp #61170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 99 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 68 commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
601f8be
create search type menu
JS00001 Apr 25, 2025
736e43e
fix search menu popover
JS00001 Apr 25, 2025
481e506
cleanup styles
JS00001 Apr 25, 2025
967bf73
add more sections
JS00001 Apr 25, 2025
a842630
start adding conditions
JS00001 Apr 25, 2025
5a57e07
getApprover list
JS00001 Apr 28, 2025
4b28033
add exporter
JS00001 Apr 28, 2025
a47606c
routes for search
JS00001 Apr 28, 2025
cf705eb
fix crashing
JS00001 Apr 28, 2025
45a6551
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 Apr 28, 2025
19b3ec5
fix types of status and fix query building
JS00001 Apr 28, 2025
0695750
add better route filtering that allows for active items
JS00001 Apr 28, 2025
b823155
empty states
JS00001 Apr 28, 2025
392ddd8
add seelction for type
JS00001 Apr 28, 2025
288240f
fix searching by report filter
JS00001 Apr 28, 2025
d158500
fix how filters work
JS00001 Apr 28, 2025
ca92df1
begin empty state search/consolidation
JS00001 Apr 30, 2025
962c422
type safety for search view
JS00001 Apr 30, 2025
581bcd4
remove strange 'current query' items in popover
JS00001 Apr 30, 2025
bbbba19
add clear button and start filter bar
JS00001 Apr 30, 2025
adf17f3
add advanced filter, scrap search status bar, addd search filter bar
JS00001 Apr 30, 2025
acd3018
add new poup components, begin testing UI changes
JS00001 Apr 30, 2025
e608f92
dropdown component complete
JS00001 Apr 30, 2025
9ec397f
setup props for single & multi
JS00001 Apr 30, 2025
085c15e
single select functionality
JS00001 Apr 30, 2025
7b04639
add new SingleSelectListItem
JS00001 Apr 30, 2025
dc3f155
create filter lists of specific data
JS00001 Apr 30, 2025
50ba0c2
progress with dropdowns actually working
JS00001 Apr 30, 2025
474d827
dropdown working
JS00001 May 1, 2025
cd4d2d1
loading skeleton
JS00001 May 1, 2025
7a5545b
date picker start
JS00001 May 1, 2025
1a0c208
date picker cleanup
JS00001 May 1, 2025
2fb4fe2
remove type and status from RHP
JS00001 May 1, 2025
6796992
complete date selection for all except 'on'
JS00001 May 1, 2025
21d42ce
add user select list
JS00001 May 1, 2025
b07a372
update user select list item to match the UI
JS00001 May 1, 2025
a434fcc
add date on support
JS00001 May 5, 2025
56bf222
user selection works
JS00001 May 5, 2025
79653b2
cleanup code values
JS00001 May 6, 2025
1f7234f
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 6, 2025
758ed43
finish user select popup
JS00001 May 6, 2025
52bbb5b
add label to bottom sheets, fix crashing when navigating
JS00001 May 6, 2025
a013dae
remove createdBy, update to use 'from'
JS00001 May 6, 2025
13c9228
fix fireworks styling
JS00001 May 6, 2025
8ae06a3
fix calendar overlay
JS00001 May 6, 2025
f58ce49
create report on empty state
JS00001 May 6, 2025
ba09b58
fix styling issues on mobile
JS00001 May 6, 2025
1f2cef4
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 8, 2025
53b3d34
add back submodule, oops!
JS00001 May 8, 2025
0b0b247
update icon to be 'clear' icon, fix sizing on mobile
JS00001 May 8, 2025
2150638
height for user selection list
JS00001 May 8, 2025
376c049
fix list height
JS00001 May 8, 2025
19a8ec5
fix date selection issues
JS00001 May 9, 2025
de32ed6
fix search resetting because of re-renders
JS00001 May 9, 2025
3743463
fix styling of popovers
JS00001 May 9, 2025
af473fd
fix type errors
JS00001 May 9, 2025
db1ce4e
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 9, 2025
5105aad
eslint fixes
JS00001 May 9, 2025
3b0cb1d
fix tests and eslint
JS00001 May 9, 2025
a4bee06
fix eslint
JS00001 May 9, 2025
9ba635a
fix key console error
JS00001 May 9, 2025
c1f09f9
fix menu selected calculations
JS00001 May 12, 2025
08a9cf3
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 12, 2025
4ffa649
Update type menu to return sections
JS00001 May 12, 2025
bddd3d5
add keyboard avoiding view for users
JS00001 May 12, 2025
39f95b2
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 13, 2025
a7d0cd1
update clear button
JS00001 May 13, 2025
875cea0
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 13, 2025
6b20204
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 14, 2025
f660052
make sections reactive
JS00001 May 14, 2025
8074006
fix popup styling issues
JS00001 May 14, 2025
ed6156e
finish initial design feedback
JS00001 May 14, 2025
cab9617
fix crash, reorder expense status
JS00001 May 14, 2025
74b387e
fix pay suggestions to only show if at least one policy has reimburs…
JS00001 May 14, 2025
c75f2f2
begin export date picker
JS00001 May 14, 2025
8a102e5
continue updating logic of calendar
JS00001 May 14, 2025
99fae42
Fix how 'never' works
JS00001 May 15, 2025
f356aba
fix menu item sizing by adding compact mode
JS00001 May 15, 2025
3b33612
allow exported:never to be saved
JS00001 May 15, 2025
47df72c
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 15, 2025
0169fb7
fix eslint & types
JS00001 May 15, 2025
d6e76bc
fix empty state bug and 'pay' being visible
JS00001 May 15, 2025
f16ab86
use checkboxes, non-bold titles for sections, remove BG from radio bu…
JS00001 May 15, 2025
ac71d26
fix padding for user select popup
JS00001 May 15, 2025
1685a3e
add 'payer' and 'exporter'
JS00001 May 16, 2025
75f8cad
update button size
JS00001 May 16, 2025
5fb7f33
update suggested queries
JS00001 May 16, 2025
78d0a15
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 16, 2025
0d98132
update parsers to be re-generated
JS00001 May 16, 2025
5cd0dcd
make 'reset' close instantly & reset changes
JS00001 May 16, 2025
2b76d3e
fix button positioning
JS00001 May 16, 2025
88c1ce8
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 19, 2025
174fdd3
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 20, 2025
211c370
fix type issues
JS00001 May 20, 2025
1bc38f6
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 20, 2025
81275af
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 20, 2025
305dd0c
update report utils
JS00001 May 20, 2025
31bcf9b
Merge branch 'main' of github.com:Expensify/App into jsenyitko-search…
JS00001 May 20, 2025
86b1882
Revert submodule pointer for Mobile-Expensify
JS00001 May 20, 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
12 changes: 9 additions & 3 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,9 @@ const CONST = {
horizontal: 12 + variables.navigationTabBarSize,
vertical: 72,
},
POPOVER_DROPDOWN_WIDTH: 336,
POPOVER_DROPDOWN_MIN_HEIGHT: 0,
POPOVER_DROPDOWN_MAX_HEIGHT: 476,
POPOVER_DATE_WIDTH: 338,
POPOVER_DATE_MAX_HEIGHT: 366,
POPOVER_DATE_MIN_HEIGHT: 322,
Expand Down Expand Up @@ -6548,7 +6551,6 @@ const CONST = {
TAX_AMOUNT: 'taxAmount',
TITLE: 'title',
ASSIGNEE: 'assignee',
CREATED_BY: 'createdBy',
IN: 'in',
},
SYNTAX_OPERATORS: {
Expand Down Expand Up @@ -6592,7 +6594,6 @@ const CONST = {
POSTED: 'posted',
TITLE: 'title',
ASSIGNEE: 'assignee',
CREATED_BY: 'createdBy',
REIMBURSABLE: 'reimbursable',
BILLABLE: 'billable',
POLICY_ID: 'policyID',
Expand Down Expand Up @@ -6633,13 +6634,13 @@ const CONST = {
POSTED: 'posted',
TITLE: 'title',
ASSIGNEE: 'assignee',
CREATED_BY: 'created-by',
REIMBURSABLE: 'reimbursable',
BILLABLE: 'billable',
},
DATE_MODIFIERS: {
BEFORE: 'Before',
AFTER: 'After',
ON: 'On',
},
SNAPSHOT_ONYX_KEYS: [
ONYXKEYS.COLLECTION.REPORT,
Expand All @@ -6650,6 +6651,11 @@ const CONST = {
ONYXKEYS.PERSONAL_DETAILS_LIST,
ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
],
DATE_FILTERS: {
BEFORE: 'before',
AFTER: 'after',
ON: 'on',
},
},

EXPENSE: {
Expand Down
1 change: 0 additions & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ const ROUTES = {
SEARCH_ADVANCED_FILTERS_POSTED: 'search/filters/posted',
SEARCH_ADVANCED_FILTERS_TITLE: 'search/filters/title',
SEARCH_ADVANCED_FILTERS_ASSIGNEE: 'search/filters/assignee',
SEARCH_ADVANCED_FILTERS_CREATED_BY: 'search/filters/createdBy',
SEARCH_ADVANCED_FILTERS_REIMBURSABLE: 'search/filters/reimbursable',
SEARCH_ADVANCED_FILTERS_BILLABLE: 'search/filters/billable',
SEARCH_ADVANCED_FILTERS_WORKSPACE: 'search/filters/workspace',
Expand Down
1 change: 0 additions & 1 deletion src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ const SCREENS = {
ADVANCED_FILTERS_TO_RHP: 'Search_Advanced_Filters_To_RHP',
ADVANCED_FILTERS_TITLE_RHP: 'Search_Advanced_Filters_Title_RHP',
ADVANCED_FILTERS_ASSIGNEE_RHP: 'Search_Advanced_Filters_Assignee_RHP',
ADVANCED_FILTERS_CREATED_BY_RHP: 'Search_Advanced_Filters_Created_By_RHP',
ADVANCED_FILTERS_REIMBURSABLE_RHP: 'Search_Advanced_Filters_Reimbursable_RHP',
ADVANCED_FILTERS_BILLABLE_RHP: 'Search_Advanced_Filters_Billable_RHP',
ADVANCED_FILTERS_WORKSPACE_RHP: 'Search_Advanced_Filters_Workspace_RHP',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ function YearPickerModal({isVisible, years, currentYear = new Date().getFullYear
hideModalContentWhileAnimating
useNativeDriver
shouldHandleNavigationBack
shouldUseCustomBackdrop
onBackdropPress={onClose}
enableEdgeToEdgeBottomSafeAreaPadding
>
<ScreenWrapper
Expand Down
1 change: 1 addition & 0 deletions src/components/EmptyStateComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ function EmptyStateComponent({
<View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : styles.mhAuto]}>
{buttons?.map(({buttonText, buttonAction, success, icon, isDisabled, style}) => (
<Button
key={buttonText}
success={success}
onPress={buttonAction}
text={buttonText}
Expand Down
6 changes: 3 additions & 3 deletions src/components/EmptyStateComponent/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import type IconAsset from '@src/types/utils/IconAsset';

type ValidSkeletons = typeof SearchRowSkeleton | typeof TableRowSkeleton;
type MediaTypes = ValueOf<typeof CONST.EMPTY_STATE_MEDIA>;
type Button = {buttonText?: string; buttonAction?: () => void; success?: boolean; icon?: IconAsset; isDisabled?: boolean; style?: StyleProp<ViewStyle>};
type EmptyStateButton = {buttonText?: string; buttonAction?: () => void; success?: boolean; icon?: IconAsset; isDisabled?: boolean; style?: StyleProp<ViewStyle>};

type SharedProps<T> = {
SkeletonComponent?: ValidSkeletons;
title: string;
titleStyles?: StyleProp<TextStyle>;
subtitle?: string;
children?: React.ReactNode;
buttons?: Button[];
buttons?: EmptyStateButton[];
containerStyles?: StyleProp<ViewStyle>;
cardStyles?: StyleProp<ViewStyle>;
cardContentStyles?: StyleProp<ViewStyle>;
Expand Down Expand Up @@ -45,4 +45,4 @@ type VideoLoadedEventType = {
};
};

export type {EmptyStateComponentProps, VideoLoadedEventType};
export type {EmptyStateComponentProps, VideoLoadedEventType, EmptyStateButton};
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, {useState} from 'react';
import {View} from 'react-native';
import type {ValueOf} from 'type-fest';
import Button from '@components/Button';
import CalendarPicker from '@components/DatePicker/CalendarPicker';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import type CONST from '@src/CONST';

type CalendarViewProps = {
view: ValueOf<typeof CONST.SEARCH.DATE_FILTERS>;
value: string | null;
navigateBack: () => void;
setValue: (key: ValueOf<typeof CONST.SEARCH.DATE_FILTERS>, value: string | null) => void;
};

function CalendarView({view, value, navigateBack, setValue}: CalendarViewProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [localDateValue, setLocalDateValue] = useState(value);

const resetChanges = () => {
setValue(view, null);
navigateBack();
};

const saveChanges = () => {
setValue(view, localDateValue);
navigateBack();
};

return (
<View style={[styles.pv4]}>
<HeaderWithBackButton
style={[styles.h10, styles.pb3]}
subtitle={translate(`common.${view}`)}
onBackButtonPress={navigateBack}
/>

<CalendarPicker
value={localDateValue ?? undefined}
onSelected={setLocalDateValue}
/>

<View style={[styles.flexRow, styles.gap2, styles.ph5, styles.pt2]}>
<Button
medium
style={[styles.flex1]}
text={translate('common.reset')}
onPress={resetChanges}
/>
<Button
success
medium
style={[styles.flex1]}
text={translate('common.save')}
onPress={saveChanges}
/>
</View>
</View>
);
}

CalendarView.displayName = 'CalendarView';
export default CalendarView;
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import {View} from 'react-native';
import type {ValueOf} from 'type-fest';
import Button from '@components/Button';
import MenuItem from '@components/MenuItem';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import type {DateSelectPopupValue} from '.';

type RootViewProps = {
value: DateSelectPopupValue;
applyChanges: () => void;
resetChanges: () => void;
setView: (view: ValueOf<typeof CONST.SEARCH.DATE_FILTERS>) => void;
};

function RootView({value, applyChanges, resetChanges, setView}: RootViewProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
const {isSmallScreenWidth} = useResponsiveLayout();
const label = translate('common.date');

return (
<View style={[!isSmallScreenWidth && styles.pv4, styles.gap2]}>
{isSmallScreenWidth && <Text style={[styles.textLabel, styles.textSupporting, styles.ph5, styles.pv1]}>{label}</Text>}

<View>
{Object.values(CONST.SEARCH.DATE_FILTERS).map((dateType) => {
const dateValue = value[dateType];
const description = dateValue ?? undefined;

return (
<MenuItem
key={dateType}
shouldShowRightIcon
title={translate(`common.${dateType}`)}
description={description}
onPress={() => setView(dateType)}
/>
);
})}
</View>

<View style={[styles.flexRow, styles.gap2, styles.ph5]}>
<Button
medium
style={[styles.flex1]}
text={translate('common.reset')}
onPress={resetChanges}
/>
<Button
success
medium
style={[styles.flex1]}
text={translate('common.apply')}
onPress={applyChanges}
/>
</View>
</View>
);
}

RootView.displayName = 'RootView';
export default RootView;
72 changes: 72 additions & 0 deletions src/components/Search/FilterDropdowns/DateSelectPopup/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, {useCallback, useState} from 'react';
import type {ValueOf} from 'type-fest';
import type CONST from '@src/CONST';
import CalendarView from './CalendarView';
import RootView from './RootView';

type DateSelectPopupValue = Record<ValueOf<typeof CONST.SEARCH.DATE_FILTERS>, string | null>;

type DateSelectPopupProps = {
/** The current value of the date */
value: DateSelectPopupValue;

/** Function to call to close the overlay when changes are applied */
closeOverlay: () => void;

/** Function to call when changes are applied */
onChange: (value: DateSelectPopupValue) => void;
};

function DateSelectPopup({value, closeOverlay, onChange}: DateSelectPopupProps) {
const [localDateValues, setLocalDateValues] = useState(value);
const [view, setView] = useState<ValueOf<typeof CONST.SEARCH.DATE_FILTERS> | null>(null);

const setDateValue = (key: ValueOf<typeof CONST.SEARCH.DATE_FILTERS>, dateValue: string | null) => {
setLocalDateValues((currentValue) => {
return {
...currentValue,
[key]: dateValue,
};
});
};

const navigateToRootView = useCallback(() => {
setView(null);
}, []);

const resetChanges = useCallback(() => {
// Reset each field back to null
setLocalDateValues((prev) => {
return Object.fromEntries(Object.entries(prev).map(([key]) => [key, null])) as DateSelectPopupValue;
});
}, []);

const applyChanges = useCallback(() => {
closeOverlay();
onChange(localDateValues);
}, [closeOverlay, localDateValues, onChange]);

if (!view) {
return (
<RootView
value={localDateValues}
applyChanges={applyChanges}
resetChanges={resetChanges}
setView={setView}
/>
);
}

return (
<CalendarView
view={view}
value={localDateValues[view]}
navigateBack={navigateToRootView}
setValue={setDateValue}
/>
);
}

DateSelectPopup.displayName = 'DateSelectPopup';
export type {DateSelectPopupValue};
export default DateSelectPopup;
Loading
Loading