Skip to content
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

[CNFT1-2939] List view sort options #1769

Merged
merged 2 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 12 additions & 0 deletions apps/modernization-ui/src/apps/search/basic/BasicPatient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Link } from 'react-router-dom';
import { displayName } from 'name';
import { asSelectableGender } from 'options/gender';
import { Mapping, Maybe } from 'utils';
import { SortingSelectable } from 'design-system/sorting/preferences';
import { Direction } from 'sorting';

type BasicPatient = {
birthTime?: string | null;
Expand All @@ -28,3 +30,13 @@ const displayProfileLink = (patient: Maybe<BasicPatient>) => (
const displayGender = (patient: Maybe<BasicPatient>) => asSelectableGender(patient?.currSexCd)?.name;

export { withPatient, displayProfileLink, displayGender };

const sorting: SortingSelectable[] = [
{ property: 'relavance', direction: Direction.Descending, name: 'Closest match' },
{ property: 'legalName', direction: Direction.Ascending, name: 'Patient name (A-Z)' },
{ property: 'legalName', direction: Direction.Descending, name: 'Patient name (Z-A)' },
{ property: 'birthday', direction: Direction.Ascending, name: 'Date of birth (Ascending)' },
{ property: 'birthday', direction: Direction.Descending, name: 'Date of birth (Descending)' }
];

export { sorting };
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { findByValue } from 'options';
import { SearchLayout, SearchResultList } from 'apps/search/layout';
import { useSearchResultDisplay } from 'apps/search/useSearchResultDisplay';
import { Investigation } from 'generated/graphql/schema';
import { SortingPreferenceProvider } from 'design-system/sorting/preferences';
import { sorting } from 'apps/search/basic';
import { InvestigationSearchResultListItem } from './result/list';
import { InvestigationSearchForm } from './InvestigationSearchForm';
import { InvestigationFilterEntry } from './InvestigationFormTypes';
Expand Down Expand Up @@ -34,32 +36,34 @@ const InvestigationSearch = () => {

return (
<ColumnPreferenceProvider id="search.investigations.preferences.columns" defaults={preferences}>
<FormProvider {...form}>
<SearchLayout
onRemoveTerm={handleRemoveTerm}
criteria={() => <InvestigationSearchForm />}
resultsAsList={() => (
<SearchResultList<Investigation>
results={results}
render={(result) => (
<InvestigationSearchResultListItem
result={result}
notificationStatusResolver={notificationStatusResolver}
/>
)}
/>
)}
resultsAsTable={() => (
<InvestigationSearchResultsTable
results={results}
notificationStatusResolver={notificationStatusResolver}
/>
)}
searchEnabled={enabled}
onSearch={search}
onClear={clear}
/>
</FormProvider>
<SortingPreferenceProvider id="search.investigations.preferences.sorting" available={sorting}>
<FormProvider {...form}>
<SearchLayout
onRemoveTerm={handleRemoveTerm}
criteria={() => <InvestigationSearchForm />}
resultsAsList={() => (
<SearchResultList<Investigation>
results={results}
render={(result) => (
<InvestigationSearchResultListItem
result={result}
notificationStatusResolver={notificationStatusResolver}
/>
)}
/>
)}
resultsAsTable={() => (
<InvestigationSearchResultsTable
results={results}
notificationStatusResolver={notificationStatusResolver}
/>
)}
searchEnabled={enabled}
onSearch={search}
onClear={clear}
/>
</FormProvider>
</SortingPreferenceProvider>
</ColumnPreferenceProvider>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { SearchLayout, SearchResultList } from 'apps/search/layout';
import { removeTerm } from 'apps/search/terms';
import { useSearchResultDisplay } from 'apps/search/useSearchResultDisplay';
import { LabReport } from 'generated/graphql/schema';
import { SortingPreferenceProvider } from 'design-system/sorting/preferences';
import { sorting } from 'apps/search/basic';
import { useLaboratoryReportSearch } from './useLaboratoryReportSearch';
import { LabReportFilterEntry, initial as defaultValues } from './labReportFormTypes';
import { LaboratoryReportSearchResultListItem } from './result/list';
Expand Down Expand Up @@ -34,26 +36,31 @@ const LaboratoryReportSearch = () => {

return (
<ColumnPreferenceProvider id="search.laboratory-reports.preferences.columns" defaults={preferences}>
<FormProvider {...form}>
<SearchLayout
onRemoveTerm={handleRemoveTerm}
criteria={() => <LaboratoryReportSearchCriteria />}
resultsAsList={() => (
<SearchResultList<LabReport>
results={results}
render={(result) => (
<LaboratoryReportSearchResultListItem result={result} jurisdictionResolver={findById} />
)}
/>
)}
resultsAsTable={() => (
<LaboratoryReportSearchResultsTable results={results} jurisdictionResolver={findById} />
)}
searchEnabled={enabled}
onSearch={search}
onClear={clear}
/>
</FormProvider>
<SortingPreferenceProvider id="search.laboratory-reports.preferences.sorting" available={sorting}>
<FormProvider {...form}>
<SearchLayout
onRemoveTerm={handleRemoveTerm}
criteria={() => <LaboratoryReportSearchCriteria />}
resultsAsList={() => (
<SearchResultList<LabReport>
results={results}
render={(result) => (
<LaboratoryReportSearchResultListItem
result={result}
jurisdictionResolver={findById}
/>
)}
/>
)}
resultsAsTable={() => (
<LaboratoryReportSearchResultsTable results={results} jurisdictionResolver={findById} />
)}
searchEnabled={enabled}
onSearch={search}
onClear={clear}
/>
</FormProvider>
</SortingPreferenceProvider>
</ColumnPreferenceProvider>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,32 @@
import { ButtonActionMenu } from 'components/ButtonActionMenu/ButtonActionMenu';
import styles from './search-results-list-options.module.scss';
import { Direction, useSorting } from 'sorting';
import { SortField } from 'generated/graphql/schema';
import { useEffect } from 'react';
import { Button } from 'components/button';
import { Icon } from 'design-system/icon';
import classNames from 'classnames';
import { SortingPreferencesPanel } from 'design-system/sorting/preferences';
import { OverlayPanel } from 'overlay';

import styles from './search-results-list-options.module.scss';

type Props = {
disabled?: boolean;
};

const SearchResultsListOptions = ({ disabled = false }: Props) => {
const { sortBy, property, direction } = useSorting();

const savePreferences = (selection: SortField, direction: Direction) => {
localStorage.setItem('searchResultsSortBy', selection);
localStorage.setItem('searchResultsSortDirection', direction);
};

useEffect(() => {
const sortName = localStorage.getItem('searchResultsSortBy');
const sortDirection = localStorage.getItem('searchResultsSortDirection');

if (sortName && sortDirection) {
sortBy(sortName, sortDirection as Direction);
}
}, []);

const isActive = (field: SortField, dir: Direction) => property === field && direction === dir;

const renderSortButton = (field: SortField, dir: Direction, label: string) => (
<Button
className={classNames(styles.optionItem, { [styles.active]: isActive(field, dir) })}
icon={isActive(field, dir) ? <Icon name="check" className={styles.check} /> : undefined}
labelPosition="right"
type="button"
onClick={() => {
sortBy(field, dir);
savePreferences(field, dir);
}}>
{label}
</Button>
);

return (
<ButtonActionMenu
className={styles.option}
ariaLabel="Sort by list"
outline
icon={<Icon className={styles.sortArrow} name="sort_arrow" />}
disabled={disabled}>
{renderSortButton(SortField.Relevance, Direction.Descending, 'Closest match')}
{renderSortButton(SortField.LastNm, Direction.Ascending, 'Patient name (A-Z)')}
{renderSortButton(SortField.LastNm, Direction.Descending, 'Patient name (Z-A)')}
{renderSortButton(SortField.BirthTime, Direction.Ascending, 'Date of birth (Ascending)')}
{renderSortButton(SortField.BirthTime, Direction.Descending, 'Date of birth (Descending)')}
</ButtonActionMenu>
<OverlayPanel
className={styles.options}
position="right"
toggle={({ toggle }) => (
<Button
className={styles.opener}
aria-label="Sort settings"
data-tooltip-position="top"
outline
disabled={disabled}
icon={<Icon name="sort_arrow" className={styles.icon} />}
onClick={toggle}
/>
)}
render={(close) => <SortingPreferencesPanel onClose={close} />}
/>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,14 @@
@use 'styles/colors.scss';

.option {
.sortArrow {
width: 1.75rem;
height: 1.75rem;
margin: 0;
fill: colors.$primary;
}
.options {
--modal-min-width: max-content;
}

.optionItem {
padding: 0.625rem 2.75rem !important;
gap: 0.5rem !important;
.opener {
color: colors.$primary;

&.active {
padding: 0.625rem 1rem !important;

.check {
width: 1.25rem;
height: 1.25rem;
margin: 0 !important;
fill: colors.$primary;
}
.icon {
width: 1.75rem;
height: 1.75rem;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ $content-height: calc($search-height - $navigation-height - 3rem);

background-color: colors.$base-white;

overflow-y: clip;

@include borders.bordered();
@include borders.rounded();

Expand Down
40 changes: 22 additions & 18 deletions apps/modernization-ui/src/apps/search/patient/PatientSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ColumnPreferenceProvider } from 'design-system/table/preferences';
import { SearchLayout, SearchResultList } from 'apps/search/layout';
import { Term, useSearchResultDisplay } from 'apps/search';
import { PatientSearchResult } from 'generated/graphql/schema';
import { SortingPreferenceProvider } from 'design-system/sorting/preferences';
import { sorting } from 'apps/search/basic';
import { usePatientSearch } from './usePatientSearch';
import { PatientSearchResultListItem } from './result/list';
import { NoPatientResults } from './result/none';
Expand Down Expand Up @@ -37,24 +39,26 @@ const PatientSearch = () => {

return (
<ColumnPreferenceProvider id="search.patients.preferences.columns" defaults={preferences}>
<FormProvider {...form}>
<SearchLayout
onRemoveTerm={handleRemoveTerm}
actions={() => <PatientSearchActions />}
criteria={() => <PatientCriteria />}
resultsAsList={() => (
<SearchResultList<PatientSearchResult>
results={results}
render={(result) => <PatientSearchResultListItem result={result} />}
/>
)}
resultsAsTable={() => <PatientSearchResultTable results={results} />}
searchEnabled={enabled}
onSearch={search}
noResults={() => <NoPatientResults />}
onClear={clear}
/>
</FormProvider>
<SortingPreferenceProvider id="search.patients.preferences.sorting" available={sorting}>
<FormProvider {...form}>
<SearchLayout
onRemoveTerm={handleRemoveTerm}
actions={() => <PatientSearchActions />}
criteria={() => <PatientCriteria />}
resultsAsList={() => (
<SearchResultList<PatientSearchResult>
results={results}
render={(result) => <PatientSearchResultListItem result={result} />}
/>
)}
resultsAsTable={() => <PatientSearchResultTable results={results} />}
searchEnabled={enabled}
onSearch={search}
noResults={() => <NoPatientResults />}
onClear={clear}
/>
</FormProvider>
</SortingPreferenceProvider>
</ColumnPreferenceProvider>
);
};
Expand Down
6 changes: 4 additions & 2 deletions apps/modernization-ui/src/design-system/icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import { SVGProps as ReactSVGProps } from 'react';
import uswds from '@uswds/uswds/img/sprite.svg';
import classNames from 'classnames';

import styles from './icon.module.scss';

type Icons = USWDSIcons | ExtendedIcons;

type Props = { name: Icons } & ReactSVGProps<SVGSVGElement>;

const Icon = ({ name, role = 'img', ...props }: Props) => {
const Icon = ({ name, role = 'img', className, ...props }: Props) => {
const location = resolveLocation(name);

return (
<svg
className={classNames(props.className)}
className={classNames(styles.icon, className)}
role={role}
aria-hidden={props['aria-hidden'] || !props['aria-label'] || !props['aria-labelledby']}
{...props}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.icon {
width: 1rem;
height: 1rem;
fill: currentColor;
}
Loading
Loading