Advanced date filter view#45756
Conversation
…-fork into Guccio163/45026-search-advanced-filters
…-fork into Guccio163/45026-search-advanced-filters
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
…h-advanced-filters
Kicu
left a comment
There was a problem hiding this comment.
Good job, the UI code looks good and mostly simple 👍
I left you several comments, most of them quite simple, some renaming and some pointing out of better patterns.
Please take a look
src/libs/actions/Search.ts
Outdated
| export {search, createTransactionThread, deleteMoneyRequestOnSearch, holdMoneyRequestOnSearch, unholdMoneyRequestOnSearch, exportSearchItemsToCSV}; | ||
|
|
||
| // Temporary function, ultimately general function to update filters object with any filter, bow only date for test purposes | ||
| function mergeFilters(updatedForm: FormOnyxValues<typeof ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM>) { |
There was a problem hiding this comment.
this should be moved to SearchUtils.ts which is the file to keep helper functions and functions that help with managing data.
actions are strictly for api calls
There was a problem hiding this comment.
@blazejkustra what do You think about that?
There was a problem hiding this comment.
I think @Kicu is right here, let's move to utils file 👍
There was a problem hiding this comment.
Okay, thanks for the help 🙌
There was a problem hiding this comment.
I'm moving it to SearchUtils.ts, but it requires me to add // eslint-disable-next-line rulesdir/prefer-actions-set-data which I didn't have to add in actions/Search.ts. From looking into other Onyx.merge usages it is the only way.
There was a problem hiding this comment.
Additionally when writing it in actions/Search.ts I was following convention seen f.ex. in IOURequestStepDate.tsx in which they get function merging in Onyx from actions/IOS.ts : IOU.setDraftSplitTransaction(transaction?.transactionID ?? '-1', {created: newCreated});
There was a problem hiding this comment.
After consulting with @blazejkustra I'm moving mergeFilters back to actions/Search
There was a problem hiding this comment.
We should move this to src/libs/actions/Search.ts. All Onyx actions should be declared in libs/actions files.
|
|
||
| const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM); | ||
|
|
||
| const isDateAfterInitialized = !!(searchAdvancedFiltersForm && searchAdvancedFiltersForm[INPUT_IDS.DATE.AFTER]); |
There was a problem hiding this comment.
you have to do a lot of work here to make sure searchAdvancedFiltersForm is non null.
This code will be simpler if you do a default value when destructuring array in line 26:
const [foo = {}] = useOnyx(...
then these 2 checks will be much simpler
There was a problem hiding this comment.
I extracted default value into separate const and added it just like you wrote, everything works just fine
There was a problem hiding this comment.
I left a comment here, but given that these filters are all optional, I don't think it makes sense to add a default value. We should just leave them empty and add only what the user selects
|
Right now I have 4 questions regarding filters:
|
I thought that our plan is that:
the rest of questions go to @luacmartins |
|
What I meant is a matter of how we want to handle situation in which user starts to set filters and then changes his mind/ closes page and return after f.ex. 2 days? Right now filters would still be set in Onyx. |
…-fork into Guccio163/45026-search-advanced-filters
|
@rayane-djouah Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
Reviewer Checklist
Screenshots/VideosAndroid: NativeScreen.Recording.2024-07-24.at.1.10.45.PM.movAndroid: mWeb ChromeScreen.Recording.2024-07-24.at.12.59.48.PM.moviOS: NativeiOS: mWeb SafariSimulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2024-07-24.at.12.55.50.mp4MacOS: Chrome / SafariScreen.Recording.2024-07-24.at.12.54.37.PM.movMacOS: DesktopScreen.Recording.2024-07-24.at.1.53.58.PM.mov |
luacmartins
left a comment
There was a problem hiding this comment.
Welcome to the team @Guccio163! Overall the PR looks good, I left a few comments in code. Additionally, there are a couple more things I'd like to request:
- Can we add the
View resultsbutton to theAdvancedSearchFilterspage? That way we can test that selecting a value and clicking it will correctly update the URL with the new query string and thus the search results. - Selecting dates and saving doesn't update the
MenuItemWithTopDescriptionwith the selected values
Screen.Recording.2024-07-22.at.2.45.55.PM.mov
However, the doc shows it just as the text input (no calendar). @Expensify/design could you confirm which version we should have for the Search date filter?
src/libs/actions/Search.ts
Outdated
| export {search, createTransactionThread, deleteMoneyRequestOnSearch, holdMoneyRequestOnSearch, unholdMoneyRequestOnSearch, exportSearchItemsToCSV}; | ||
|
|
||
| // Temporary function, ultimately general function to update filters object with any filter, bow only date for test purposes | ||
| function mergeFilters(updatedForm: FormOnyxValues<typeof ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM>) { |
There was a problem hiding this comment.
We should move this to src/libs/actions/Search.ts. All Onyx actions should be declared in libs/actions files.
| const defaultDateAfter = searchAdvancedFiltersForm[INPUT_IDS.DATE_AFTER]; | ||
| const defaultDateBefore = searchAdvancedFiltersForm[INPUT_IDS.DATE_BEFORE]; |
There was a problem hiding this comment.
I don't think we should add defaults here. All of these values are optional so the default should be no date selected
There was a problem hiding this comment.
If we want default date to not be set, default values should be changed from current date to undefined, but I need to create them so that Typescript is assured that searchAdvancedFiltersForm is not undefined.
There was a problem hiding this comment.
We should define the ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM values Onyx type in OnyxFormValuesMapping to ensure that searchAdvancedFiltersForm is correctly typed, and remove DEFAULT_FILTERS_FORM_VALUE
There was a problem hiding this comment.
If I apply these changes, TS still isn't sure the whole object under Onyx key isn't undefined:

Alternatively, I can assign empty object with a cast, that works as well:
const [searchAdvancedFiltersForm = {} as SearchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM)
defaultDateAfter/Before are both extracted just for clarity
There was a problem hiding this comment.
Sorry, I'm on mobile right now so I can't check. But, All Onyx entries can be undefined, and you can use Typescript optional chaining to access their properties with a fallback if you don't want the value to be undefined. You can also search for useOnyx usages in the codebase to see examples. I can give you code suggestions when I get back.
There was a problem hiding this comment.
Good point, optional chaining went through my mind, but I thought it would be less clean, I'll change it right now
|
Ahh, ok interesting. So (speaking for myself) I didn't realize that the calendar was always present with the date inputs. I thought it only showed up when the input was focused. Since that's clearly not the case, it seems to me like our options are to:
Does that sound correct to you? Super duper interested in the rest of the design team's thoughts. I was honestly kinda surprised to realize how those date inputs actually work! |
Haha I made several comments about this, but we need the date to be empty since they are optional.
I think we should clear the Onyx keys once we close the advanced filter page. IMO every time the user opens the page, we should load the filters based on the user's current search and disregard any previous selected values.
I think [UI Designer] how do we want to display the calendars, one under another, pop-up or maybe sliding in from under input onPress? I pinged the design team above. The design doc has just the text input, so I assume pop-up, but I'll let them confirm.
Answered above. I think we should clear the data when the user navigates away from the page. |
I'd add a third option which is to modify the date input to allow for a pop up when it's focused. Otherwise, yea these are the options we have. |
Personally this would probably get my vote, but I really don't know what kind of effort that would require or what any potential gotchas we might encounter would be, so I was hesitant to suggest it haha. @shawnborton @dubielzyk-expensify what do you guys think? |
|
Sorry, but that is not completely true. What I'm trying to say for the last 3 comments is that it's the input UI "type" itself adding this extra step. This whole UI control consists of 2 screens. Anyways: I don't want to hijack this PR, so I will code around it, but wanted to point this out for other designers and devs to be aware. |
|
Hmm I am really not following what you are saying. We have plenty of examples of screens throughout the app where list selection inputs only use two screens, I don't know why this particular flow was using 3 screens. I can't think of any other place in the app that has it implemented as 3 screens either. |
|
@Kicu - I think we can use |
|
@rayane-djouah it's a good suggestion but I'm afraid its not optimal. @shawnborton yes I understand that you are not following because I started to talk directly about the React Components available in the code, maybe I shouldn't have. What I said is completely true in regards to code, not to the UI flows. But I know what is the expectation and I'm able to do it, there will be a PR soon |
| const defaultDateAfter = searchAdvancedFiltersForm[INPUT_IDS.DATE_AFTER]; | ||
| const defaultDateBefore = searchAdvancedFiltersForm[INPUT_IDS.DATE_BEFORE]; |
There was a problem hiding this comment.
We should define the ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM values Onyx type in OnyxFormValuesMapping to ensure that searchAdvancedFiltersForm is correctly typed, and remove DEFAULT_FILTERS_FORM_VALUE
|
Ok so it sounds like we're down to try the calendar as a popover on focus.
@shawnborton I definitely see your point here, but my counter-argument is that we autofocus these kinds of inputs when you navigate to a page. So basically you would still see the calendar by default because we're immediately focusing the input when you land on the screen. In regards to the CleanShot.2024-07-23.at.08.30.04.mp4 |
Ah I guess that's a fair point. I guess what I'm mostly saying is that I don't think we need to change the existing behavior for this in the places where it's already working well.
Indeed it is! |
Works for me if everyone is cool with that approach! |
Makes sense. I think the behavior is:
Correct, we need to display both since they are independent filters.
We can do this in a follow up, not to distract from the original issue.
@Kicu I think this is what we do in other forms. The only reason for the date filter (and some others) to have their own route/page is because they are a bit special, e.g. the date filter has both before and after dates in a single page so we need to create a separate view for that. I'm not sure that that's a requirement for simple pickers like the type/status |
|
@Guccio163 let me know once this PR is ready for review again |
|
I think that it'll be completed right after we finish with the |
|
@rayane-djouah just letting you know that I applied optional chaining and deleted default values, because GitHub hid it in |
|
@luacmartins I see that @rayane-djouah has completed the Reviewer Checklist, I suppose this is sign that it's ready for the review again 🤞 |
| InputComponent={DatePicker} | ||
| inputID={INPUT_IDS.DATE_BEFORE} | ||
| label={translate('search.filters.date.before')} | ||
| defaultValue={searchAdvancedFiltersForm?.[INPUT_IDS.DATE_BEFORE]} |
There was a problem hiding this comment.
same here for searchAdvancedFiltersForm?.[INPUT_IDS.DATE_BEFORE]
rayane-d
left a comment
There was a problem hiding this comment.
Thank you!
Changes look good to me and test well. The reviewer checklist is also complete.
🎀👀🎀 C+ reviewed
| const dateAfter = searchAdvancedFiltersForm?.[INPUT_IDS.DATE_AFTER]; | ||
| const dateBefore = searchAdvancedFiltersForm?.[INPUT_IDS.DATE_BEFORE]; |
There was a problem hiding this comment.
@Guccio163 - Another NAB comment 😄: We can define INPUT_IDS.DATE_AFTER and INPUT_IDS.DATE_BEFORE as two constants outside the component (line 18) with the names DATE_AFTER_KEY and DATE_BEFORE_KEY just to make these two lines super clear
| const dateAfter = searchAdvancedFiltersForm?.[INPUT_IDS.DATE_AFTER]; | ||
| const dateBefore = searchAdvancedFiltersForm?.[INPUT_IDS.DATE_BEFORE]; |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/luacmartins in version: 9.0.12-0 🚀
|
|
🚀 Deployed to production by https://github.com/francoisl in version: 9.0.12-0 🚀
|
|
🚀 Deployed to staging by https://github.com/luacmartins in version: 9.0.13-0 🚀
|


Details
This PR adds an Advanced filter "Date" and is an example of underlying logic that will be used for the rest of the filters.
Fixed Issues
$ #46033
PROPOSAL:
Tests
Offline tests
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)myBool && <MyComponent />.src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
search_date_android.mov
Android: mWeb Chrome
Screen.Recording.2024-07-22.at.12.13.14.mov
iOS: Native
Screen.Recording.2024-07-22.at.09.02.20.mov
iOS: mWeb Safari
search_date_iosWeb.mov
MacOS: Chrome / Safari
Screen.Recording.2024-07-22.at.08.44.31.mov
MacOS: Desktop
Screen.Recording.2024-07-22.at.12.50.41.mov