Skip to content

Commit e40955e

Browse files
fix(frontend): #2302 test search UI improvement (#2314)
1 parent b462845 commit e40955e

File tree

3 files changed

+144
-134
lines changed

3 files changed

+144
-134
lines changed

.github/codeowners

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Matched against repo root (asterisk)
2-
* @xiaopeng0202 @mgaseta @MCatherine1994 @SLDonnelly
2+
* @xiaopeng0202 @MCatherine1994 @SLDonnelly
33

44
# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners

frontend/src/views/CONSEP/TestingActivities/TestSearch/index.tsx

Lines changed: 142 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ const csvConfig = mkConfig({
6161
useKeysAsHeaders: true,
6262
filename: `Testing_Activity_Search_${new Date().toISOString().split('T')[0]}`
6363
});
64-
6564
const LOT_INPUT_KEYS = ['lot-input-1', 'lot-input-2', 'lot-input-3', 'lot-input-4', 'lot-input-5'] as const;
65+
const toDate = (value?: string) => (value ? new Date(`${value}T00:00:00`) : undefined);
6666

6767
const TestSearch = () => {
6868
const [hasSearched, setHasSearched] = useState(false);
@@ -357,9 +357,9 @@ const TestSearch = () => {
357357
resetAlert();
358358
};
359359

360-
const handleWithdrawalDateChange = (dates: (string | Date)[], type: 'start' | 'end') => {
360+
const handleWithdrawalDateChange = (dates: Date[], type: 'start' | 'end') => {
361361
const raw = dates?.[0];
362-
const value = typeof raw === 'string' ? raw : raw?.toISOString().slice(0, 10);
362+
const value = raw instanceof Date ? raw.toISOString().slice(0, 10) : undefined;
363363

364364
setSearchParams((prev) => {
365365
const currentStart = prev.seedWithdrawalStartDate;
@@ -472,140 +472,150 @@ const TestSearch = () => {
472472
<Row className="consep-test-search-title">
473473
<PageTitle title="Testing activities" />
474474
</Row>
475-
<Row className="consep-test-search-lot-numbers-filter">
476-
<FormLabel className="lot-inputs-label">Lot #</FormLabel>
477-
<div className="lot-inputs">
478-
{rawLotInput.map((value, index) => (
479-
<TextInput
480-
key={`${LOT_INPUT_KEYS[index]}`}
481-
id={`lot-input-${index}`}
482-
value={value}
483-
labelText={`Lot # ${index + 1}`}
484-
hideLabel
485-
onChange={(e: ChangeEvent<HTMLInputElement>) => {
486-
handleLotInputChange(index, e.target.value);
475+
<form
476+
noValidate
477+
onSubmit={(e) => {
478+
e.preventDefault();
479+
if (!hasValidationErrors()) {
480+
handleSearchClick();
481+
}
482+
}}
483+
>
484+
<Row className="consep-test-search-lot-numbers-filter">
485+
<FormLabel className="lot-inputs-label">Lot #</FormLabel>
486+
<div className="lot-inputs">
487+
{rawLotInput.map((value, index) => (
488+
<TextInput
489+
key={`${LOT_INPUT_KEYS[index]}`}
490+
id={`lot-input-${index}`}
491+
value={value}
492+
labelText={`Lot # ${index + 1}`}
493+
hideLabel
494+
onChange={(e: ChangeEvent<HTMLInputElement>) => {
495+
handleLotInputChange(index, e.target.value);
496+
}}
497+
invalid={validateSearch.lotNumbers[index]?.error}
498+
invalidText={validateSearch.lotNumbers[index]?.errorMessage}
499+
/>
500+
))}
501+
</div>
502+
</Row>
503+
<Row className="consep-test-search-filters">
504+
<Column className="filters-row">
505+
<FilterableMultiSelect
506+
id="test-type-input"
507+
className="test-type-input"
508+
titleText="Test type"
509+
items={
510+
testTypeQuery.data
511+
? testTypeQuery.data.map((type: string) => ({
512+
id: type,
513+
text: type
514+
}))
515+
: []
516+
}
517+
itemToString={(item: { id: string; text: string } | null) => (item ? item.text : '')}
518+
onChange={(event: { selectedItems: Array<{ id: string }> }) => {
519+
handleMultiSelectChanges('testTypes', event.selectedItems.map((it: { id: string }) => it.id));
487520
}}
488-
invalid={validateSearch.lotNumbers[index]?.error}
489-
invalidText={validateSearch.lotNumbers[index]?.errorMessage}
521+
selectionFeedback="top-after-reopen"
490522
/>
491-
))}
492-
</div>
493-
</Row>
494-
<Row className="consep-test-search-filters">
495-
<Column className="filters-row">
496-
<FilterableMultiSelect
497-
id="test-type-input"
498-
className="test-type-input"
499-
titleText="Test type"
500-
items={
501-
testTypeQuery.data
502-
? testTypeQuery.data.map((type: string) => ({
503-
id: type,
504-
text: type
505-
}))
506-
: []
507-
}
508-
itemToString={(item: { id: string; text: string } | null) => (item ? item.text : '')}
509-
onChange={(event: { selectedItems: Array<{ id: string }> }) => {
510-
handleMultiSelectChanges('testTypes', event.selectedItems.map((it: { id: string }) => it.id));
511-
}}
512-
selectionFeedback="top-after-reopen"
513-
/>
514-
<FilterableMultiSelect
515-
id="activity-type-input"
516-
className="activity-type-input"
517-
titleText="Choose activity"
518-
items={
519-
activityIdQuery.data
520-
? activityIdQuery.data.map((id) => ({ id, text: id }))
521-
: []
522-
}
523-
itemToString={(item: { id: string; text: string } | null) => (item ? item.text : '')}
524-
onChange={(event: { selectedItems: Array<{ id: string }> }) => {
525-
handleMultiSelectChanges('activityIds', event.selectedItems.map((it: { id: string }) => it.id));
526-
}}
527-
selectionFeedback="top-after-reopen"
528-
/>
529-
<TextInput
530-
id="germ-tray-input"
531-
className="germ-tray-input"
532-
labelText="Germ tray ID"
533-
type="number"
534-
onChange={(e: ChangeEvent<HTMLInputElement>) => {
535-
handleGermTrayIdChange(e);
536-
}}
537-
value={searchParams.germinatorTrayId}
538-
invalid={validateSearch.germinatorTray.error}
539-
invalidText={validateSearch.germinatorTray.errorMessage}
540-
/>
541-
<DatePicker
542-
datePickerType="single"
543-
className="withdrawal-date-input"
544-
dateFormat={DATE_FORMAT}
545-
onChange={(e: Array<Date>) => {
546-
handleWithdrawalDateChange(e, 'start');
547-
}}
548-
value={
549-
searchParams.seedWithdrawalStartDate !== minStartDate
550-
? searchParams.seedWithdrawalStartDate
551-
: undefined
552-
}
553-
style={{ minWidth: '9rem' }}
554-
>
555-
<DatePickerInput
556-
id="withdrawal-start-date-input"
557-
labelText="Withdrawal start"
558-
autoComplete="off"
523+
<FilterableMultiSelect
524+
id="activity-type-input"
525+
className="activity-type-input"
526+
titleText="Choose activity"
527+
items={
528+
activityIdQuery.data
529+
? activityIdQuery.data.map((id) => ({ id, text: id }))
530+
: []
531+
}
532+
itemToString={(item: { id: string; text: string } | null) => (item ? item.text : '')}
533+
onChange={(event: { selectedItems: Array<{ id: string }> }) => {
534+
handleMultiSelectChanges('activityIds', event.selectedItems.map((it: { id: string }) => it.id));
535+
}}
536+
selectionFeedback="top-after-reopen"
559537
/>
560-
</DatePicker>
561-
<DatePicker
562-
datePickerType="single"
563-
className="withdrawal-date-input"
564-
dateFormat={DATE_FORMAT}
565-
onChange={(e: Array<Date>) => {
566-
handleWithdrawalDateChange(e, 'end');
567-
}}
568-
minDate={searchParams.seedWithdrawalStartDate ?? undefined}
569-
value={
570-
searchParams.seedWithdrawalEndDate !== maxEndDate
571-
? searchParams.seedWithdrawalEndDate
572-
: undefined
573-
}
574-
style={{ minWidth: '9rem' }}
575-
>
576-
<DatePickerInput
577-
id="withdrawal-end-date-input"
578-
labelText="Withdrawal end"
579-
autoComplete="off"
538+
<TextInput
539+
id="germ-tray-input"
540+
className="germ-tray-input"
541+
labelText="Germ tray ID"
542+
type="number"
543+
onChange={(e: ChangeEvent<HTMLInputElement>) => {
544+
handleGermTrayIdChange(e);
545+
}}
546+
value={searchParams.germinatorTrayId}
547+
invalid={validateSearch.germinatorTray.error}
548+
invalidText={validateSearch.germinatorTray.errorMessage}
580549
/>
581-
</DatePicker>
582-
<div className="filters-row-buttons">
583-
<Button ref={advSearchRef} size="md" kind="tertiary" onClick={toggleAdvSearch}>
584-
Filters
585-
</Button>
586-
<Button
587-
renderIcon={Search}
588-
iconDescription="Search activity"
589-
size="md"
590-
onClick={handleSearchClick}
591-
disabled={hasValidationErrors()}
550+
<DatePicker
551+
datePickerType="single"
552+
className="withdrawal-date-input"
553+
dateFormat={DATE_FORMAT}
554+
onChange={(dates: Date[]) => {
555+
handleWithdrawalDateChange(dates, 'start');
556+
}}
557+
value={
558+
searchParams.seedWithdrawalStartDate !== minStartDate
559+
? toDate(searchParams.seedWithdrawalStartDate)
560+
: undefined
561+
}
562+
style={{ minWidth: '9rem' }}
592563
>
593-
Search activity
594-
</Button>
595-
</div>
596-
</Column>
597-
</Row>
598-
{openAdvSearch && modalAnchor && (
599-
<AdvancedFilters
600-
searchParams={searchParams}
601-
setSearchParams={setSearchParams}
602-
validateSearch={validateSearch}
603-
setValidateSearch={setValidateSearch}
604-
alignTo={modalAnchor}
605-
onClose={handleCloseAdvSearch}
606-
anchorRef={advSearchRef}
607-
/>
608-
)}
564+
<DatePickerInput
565+
id="withdrawal-start-date-input"
566+
labelText="Withdrawal start"
567+
autoComplete="off"
568+
/>
569+
</DatePicker>
570+
<DatePicker
571+
datePickerType="single"
572+
className="withdrawal-date-input"
573+
dateFormat={DATE_FORMAT}
574+
onChange={(dates: Date[]) => {
575+
handleWithdrawalDateChange(dates, 'end');
576+
}}
577+
minDate={searchParams.seedWithdrawalStartDate || undefined}
578+
value={
579+
searchParams.seedWithdrawalEndDate !== maxEndDate
580+
? toDate(searchParams.seedWithdrawalEndDate)
581+
: undefined
582+
}
583+
style={{ minWidth: '9rem' }}
584+
>
585+
<DatePickerInput
586+
id="withdrawal-end-date-input"
587+
labelText="Withdrawal end"
588+
autoComplete="off"
589+
/>
590+
</DatePicker>
591+
<div className="filters-row-buttons">
592+
<Button ref={advSearchRef} size="md" kind="tertiary" onClick={toggleAdvSearch}>
593+
Filters
594+
</Button>
595+
<Button
596+
type="submit"
597+
renderIcon={Search}
598+
iconDescription="Search activity"
599+
size="md"
600+
disabled={hasValidationErrors()}
601+
>
602+
Search activity
603+
</Button>
604+
</div>
605+
</Column>
606+
</Row>
607+
{openAdvSearch && modalAnchor && (
608+
<AdvancedFilters
609+
searchParams={searchParams}
610+
setSearchParams={setSearchParams}
611+
validateSearch={validateSearch}
612+
setValidateSearch={setValidateSearch}
613+
alignTo={modalAnchor}
614+
onClose={handleCloseAdvSearch}
615+
anchorRef={advSearchRef}
616+
/>
617+
)}
618+
</form>
609619
</FlexGrid>
610620
<FlexGrid>
611621
<Row className="consep-test-search-alert">

frontend/src/views/CONSEP/TestingActivities/TestSearch/styles.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
}
143143

144144
.MuiTableContainer-root {
145-
max-height: calc(100vh - 28.2rem);
145+
max-height: calc(100vh - 10rem);
146146

147147
// style for table header resize handle
148148
.Mui-TableHeadCell-ResizeHandle-Wrapper {

0 commit comments

Comments
 (0)