-
Notifications
You must be signed in to change notification settings - Fork 15
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
Filter by Date Pt. 2 - Custom date selection #3117
base: main
Are you sure you want to change the base?
Conversation
if (new Date(startDate) > new Date(endDate)) { | ||
alert( | ||
"Invalid date range. Start date must be earlier or equal to the end date.", | ||
); | ||
resetFilterDate(); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This is temporary -- a placeholder alert to safeguard against error where Start date > end date
. Still working on how to make the custom error tooltip for this / might get brought out into a separate small ticket
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3117 +/- ##
==========================================
- Coverage 87.05% 85.67% -1.39%
==========================================
Files 219 25 -194
Lines 13652 1424 -12228
Branches 709 0 -709
==========================================
- Hits 11885 1220 -10665
+ Misses 1758 204 -1554
+ Partials 9 0 -9
Flags with carried forward coverage won't be shown. Click here to find out more. |
@@ -77,7 +88,7 @@ const Filters = () => { | |||
} | |||
}, [filterBoxOpen]); | |||
|
|||
const paramKeys = ["condition", "dateRange"]; | |||
const paramKeys = [ParamName.Condition, ParamName.DateRange, ParamName.Dates]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this instead be computed from the enum? (is a formal enum worth it or just use a plain object?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just made an update!
(Maybe an enum is overkill, but thought it would make things clearer in case we expand the scope of filters?)
@@ -124,7 +135,8 @@ const Filters = () => { | |||
* - Updates the browser's query string when the filter is applied. | |||
*/ | |||
const FilterReportableConditions = () => { | |||
const { searchParams, updateQueryParam } = useQueryParam(); | |||
const { searchParams, updateQueryParam, pushQueryUpdate } = useQueryParam(); | |||
const params = new URLSearchParams(searchParams.toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need to do this copy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needed to pass params to updateQueryParam in the submitHandler
(can't pass searchParams which is read-only)
Could move Line 139 into the submitHandler
so it's more clear why that's needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd move this into updateQueryParams
so it always returns a new params and doesn't mutate. Especially since mutating state can be such a footgun, best to avoid it entirely by default
|
||
const submitHandler = () => { | ||
const params = new URLSearchParams(searchParams.toString()); | ||
if (filterDateOption === "custom") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what were the pros/cons/thinking on the two param approach vs a single param like custom(start,end)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, missed this comment on Friday! My thoughts are below, and I'm definitely open to changing the approach.
I went with two URL parameters to keep things simpler. One shows that it’s a custom date, and the other holds the actual dates. Keeping these definitions separate means we don’t have to deal with extra parsing every time we just need one of them (felt cleaner and easier to work with this approach). Also, having two separate parameters helps keep the radio button option name and the URL param values in sync, which makes it simpler to match what the user picks to what’s in the query string.
Also, keeping custom dates in their own parameter seemed like it would make it easier to extend things in the future—like if we wanted to add time ranges. Saves us from having to dig through and parse a single dateRange parameter if we need to add more customizations down the line.
The main con with maintaining the two parameters is maintaining consistency between dateRange
and dates
, i.e. making sure that dates
only exists and is processed when dateRange=custom
, and that dates
does not exist when dateRange
is set to one of the other predefined date ranges. Using the single dateRange
parameter also to house the custom dates would eliminate this risk.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That matches what I see as well. We just need to make sure we've got robust handling of the keeping in sync and edge cases there
type="date" | ||
className="usa-input width-card margin-top-0 border-base-dark custom-date" | ||
defaultValue={endDate || ""} | ||
required |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we require an end date? or should it be implicitly today if not selected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I think this is a question for @ashton-skylight.
Do you prefer that 1) end date is always required, i.e. folks would have to manually set today as the end date, or 2) end date is not required, i.e. if users don't fill in the end date, the end date would implicitly be set as today?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@angelathe Since case investigation will usually take place with more recent cases, end date shouldn't necessarily be required. Let's go with 2, if the user does not manually set an end date, the end date is implicitly set as today, assuming that would reflect in the custom date range inputs after the user presses "apply filter".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok! Just making a note this slightly changes the acceptance criteria / scenario of the original ticket
…Cgov/phdi into angela/2753-filter-by-date-p2
@@ -286,52 +309,108 @@ const FilterByDate = () => { | |||
}; | |||
|
|||
const resetFilterDate = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a bug here where if you have a custom date range, then hit the reset button, then go back to the custom date range radio, the old custom dates are still there. Should those properly reset? Maybe just adding the setStartDate
and end date to null in the default case?
@@ -286,52 +309,108 @@ const FilterByDate = () => { | |||
}; | |||
|
|||
const resetFilterDate = () => { | |||
const queryDateRange = searchParams.get("dateRange"); | |||
const queryDateRange = searchParams.get(ParamName.DateRange); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if a user manually deletes the dates param, it ends up looking like this
should we reset to the default instead at this point? cc @ashton-skylight
updatedParams, | ||
ParamName.Dates, | ||
datesParam, | ||
false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add false
as the default on the function signature so we can skip this here?
let updatedParams: URLSearchParams; | ||
updatedParams = updateQueryParam( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let updatedParams: URLSearchParams; | |
updatedParams = updateQueryParam( | |
let updatedParams = updateQueryParam( |
return ( | ||
<div className="padding-x-105"> | ||
<div> | ||
<Label htmlFor="start-date" className="margin-top-1"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it worth abstracting out these date inputs? there's a lot of overlap between the two
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or maybe make the CustomDateInput
just do one input, then have the CustomDateRange
handle both or at that point just inline it into the date filter jsx
> | ||
<div className="display-flex flex-column"> | ||
{Object.values(DateRangeOptions).map((option) => ( | ||
<div | ||
className="checkbox-color usa-radio padding-bottom-1 padding-x-105" | ||
<RadioDateOption |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe move this abstraction up one level to RadioDateOptions
? there's still a bit of "guts" in here that could have a nicer API if it handles the options bit. Then it could just pass what are all the options
handler for option change
and current option
, which is pretty universal to any set of radio buttons
@@ -68,7 +80,7 @@ const HomePage = async ({ | |||
sortDirection={sortDirection} | |||
searchTerm={searchTerm} | |||
filterConditions={filterConditionsArr} | |||
filterDate={filterDateRange} | |||
filterDate={filterDates} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nit - pluralization doesn't match
if (filterDateRange === "custom") { | ||
const datesParam = searchParams?.dates as string | undefined; | ||
if (datesParam) { | ||
filterDates = buildCustomDateRange(datesParam); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the dates param has junk content, we get a system internal error, can we harden this?
const filterDateRange = | ||
(searchParams?.dateRange as string) || DEFAULT_DATE_RANGE; | ||
let filterDates; | ||
|
||
if (filterDateRange === "custom") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this logic feels a bit out of place here as it's likely something we'll want to sync with the component itself. Can we think about making this a bit more centralized then using that logic both here and in the UI component?
PULL REQUEST
Summary
today
00:00:00.000
, and end date time set to23:59:59.999
Related Issue
Fixes #2753
Additional Information
NOTE: Still looking to clean some things up (left a few comments), but would love to start the feedback process now.
Things that will probably get broken out into other tickets:
Apply Filter
button disabled/enabled states - button shouldstartDate > endDate
. Right now, there's a placeholderAlert
for this errorAcceptance Criteria
Checklist