From 30a29162027e4fdea5b2f1e6ec5987de9a73b581 Mon Sep 17 00:00:00 2001 From: Paul Bui-Quang Date: Tue, 1 Oct 2024 10:02:58 +0200 Subject: [PATCH] refactor: filter components - Ref gestion-de-projet#2490 --- .../AdvancedInputs/index.tsx | 2 +- .../DemographicForm/index.tsx | 2 +- .../EpisodeConstraints.tsx | 6 +- .../StayConstraints.tsx | 6 +- .../Dashboard/BiologyList/index.tsx | 38 +++++++--- src/components/Dashboard/Documents/index.tsx | 53 +++++++++---- .../Dashboard/ExportModal/exportUtils.ts | 2 +- src/components/Dashboard/FormsList/index.tsx | 34 +++++++-- .../Dashboard/ImagingList/index.tsx | 42 +++++----- .../Dashboard/MedicationList/index.tsx | 64 ++++++++++------ src/components/Dashboard/PMSIList/index.tsx | 76 ++++++++++++++----- .../Dashboard/PatientList/index.tsx | 32 ++++++-- .../AdministrationTypesFilter/index.tsx | 56 -------------- .../Filters/BirthdatesRangesFilters/index.tsx | 4 +- .../Filters/CheckboxsFilter/index.tsx | 44 +++++++++++ src/components/Filters/CodeFilter/index.tsx | 2 +- .../Filters/CohortStatusFilter/index.tsx | 41 ---------- .../Filters/CohortsTypeFilter/index.tsx | 45 ----------- .../Filters/DiagnosticTypesFilter/index.tsx | 50 ------------ .../Filters/DocStatusFilter/index.tsx | 39 ---------- .../Filters/DocTypesFilter/index.tsx | 2 +- .../Filters/EncounterStatusFilter/index.tsx | 48 ------------ .../Filters/GendersFilter/index.tsx | 62 --------------- src/components/Filters/IppFilter/index.tsx | 35 --------- .../Filters/MaternityFormFilter/index.tsx | 49 ------------ .../Filters/ModalityFilter/ModalityFilter.tsx | 42 ---------- .../Filters/MultiSelectInput/index.tsx | 44 +++++++++++ src/components/Filters/NdaFilter/index.tsx | 35 --------- .../Filters/OrderByFilter/index.tsx | 35 --------- .../Filters/OrderDirectionFilter/index.tsx | 33 -------- .../Filters/PatientsNbFilter/index.tsx | 2 +- .../Filters/PrescriptionTypesFilter/index.tsx | 50 ------------ .../Filters/RadioGroupFilter/index.tsx | 32 ++++++++ src/components/Filters/SelectFilter/index.tsx | 33 ++++++++ src/components/Filters/SourceFilter/index.tsx | 38 ---------- src/components/Filters/TextInput/index.tsx | 2 +- .../Filters/VitalStatusesFilter.tsx/index.tsx | 48 ------------ .../Filters/VitalStatusesFilter/index.tsx | 50 ------------ .../Patient/PatientBiology/index.tsx | 26 +++---- .../PatientBiology/{styles.js => styles.ts} | 0 src/components/Patient/PatientDocs/index.tsx | 49 +++++++----- .../PatientForms/MaternityForms/index.tsx | 31 ++++++-- .../Patient/PatientImaging/index.tsx | 29 ++++--- .../Patient/PatientMedication/index.tsx | 54 +++++++------ .../{styles.js => styles.ts} | 0 src/components/Patient/PatientPMSI/index.tsx | 59 +++++++++----- .../Patient/PatientSidebar/PatientSidebar.tsx | 35 +++++---- src/components/SearchValueSet/index.tsx | 1 + .../ui/Inputs/CheckboxGroup/index.tsx | 52 +++++++++++++ .../ui/Inputs/DurationRange/index.tsx | 21 +++-- .../ui/Inputs/ExecutiveUnits/index.tsx | 2 +- src/components/ui/Inputs/Text/index.tsx | 69 +++++++++++++++++ .../ui/Inputs/{index.tsx => styles.ts} | 0 src/components/ui/RadioGroup/index.tsx | 20 ++--- src/hooks/filters/useSavedFilters.ts | 2 +- src/mappers/filters.ts | 9 ++- src/services/aphp/callApi.ts | 1 + src/services/aphp/serviceCohorts.ts | 2 +- src/services/aphp/serviceProjects.ts | 2 +- src/state/patient.ts | 2 +- src/types/searchCriterias.ts | 36 ++++++++- src/utils/filters.ts | 6 +- src/views/MyCohorts/index.tsx | 49 +++++++----- 63 files changed, 798 insertions(+), 1037 deletions(-) delete mode 100644 src/components/Filters/AdministrationTypesFilter/index.tsx create mode 100644 src/components/Filters/CheckboxsFilter/index.tsx delete mode 100644 src/components/Filters/CohortStatusFilter/index.tsx delete mode 100644 src/components/Filters/CohortsTypeFilter/index.tsx delete mode 100644 src/components/Filters/DiagnosticTypesFilter/index.tsx delete mode 100644 src/components/Filters/DocStatusFilter/index.tsx delete mode 100644 src/components/Filters/EncounterStatusFilter/index.tsx delete mode 100644 src/components/Filters/GendersFilter/index.tsx delete mode 100644 src/components/Filters/IppFilter/index.tsx delete mode 100644 src/components/Filters/MaternityFormFilter/index.tsx delete mode 100644 src/components/Filters/ModalityFilter/ModalityFilter.tsx create mode 100644 src/components/Filters/MultiSelectInput/index.tsx delete mode 100644 src/components/Filters/NdaFilter/index.tsx delete mode 100644 src/components/Filters/OrderByFilter/index.tsx delete mode 100644 src/components/Filters/OrderDirectionFilter/index.tsx delete mode 100644 src/components/Filters/PrescriptionTypesFilter/index.tsx create mode 100644 src/components/Filters/RadioGroupFilter/index.tsx create mode 100644 src/components/Filters/SelectFilter/index.tsx delete mode 100644 src/components/Filters/SourceFilter/index.tsx delete mode 100644 src/components/Filters/VitalStatusesFilter.tsx/index.tsx delete mode 100644 src/components/Filters/VitalStatusesFilter/index.tsx rename src/components/Patient/PatientBiology/{styles.js => styles.ts} (100%) rename src/components/Patient/PatientMedication/{styles.js => styles.ts} (100%) create mode 100644 src/components/ui/Inputs/CheckboxGroup/index.tsx create mode 100644 src/components/ui/Inputs/Text/index.tsx rename src/components/ui/Inputs/{index.tsx => styles.ts} (100%) diff --git a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/AdvancedInputs/index.tsx b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/AdvancedInputs/index.tsx index 0508d05b6..6acccf697 100644 --- a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/AdvancedInputs/index.tsx +++ b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/AdvancedInputs/index.tsx @@ -15,7 +15,7 @@ import { DurationRangeType } from 'types/searchCriterias' import { CriteriaLabel } from 'components/ui/CriteriaLabel' import { getOccurenceDateLabel } from 'utils/requestCriterias' import ExecutiveUnitsInput from 'components/ui/Inputs/ExecutiveUnits' -import { InputWrapper } from 'components/ui/Inputs' +import { InputWrapper } from 'components/ui/Inputs/styles' type AdvancedInputsProps = { sourceType: SourceType diff --git a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/DemographicForm/index.tsx b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/DemographicForm/index.tsx index 571852591..205b68ac3 100644 --- a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/DemographicForm/index.tsx +++ b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/DemographicForm/index.tsx @@ -181,7 +181,7 @@ const DemographicForm = (props: CriteriaDrawerComponentProps) => { /> setAge(value)} onError={(isError) => setError(isError ? Error.INCOHERENT_AGE_ERROR : Error.NO_ERROR)} deidentified={deidentified} diff --git a/src/components/CreationCohort/DiagramView/components/TemporalConstraintCard/components/TemporalConstraintModal/EpisodeConstraints.tsx b/src/components/CreationCohort/DiagramView/components/TemporalConstraintCard/components/TemporalConstraintModal/EpisodeConstraints.tsx index b9ebb6511..b9a8f2c9f 100644 --- a/src/components/CreationCohort/DiagramView/components/TemporalConstraintCard/components/TemporalConstraintModal/EpisodeConstraints.tsx +++ b/src/components/CreationCohort/DiagramView/components/TemporalConstraintCard/components/TemporalConstraintModal/EpisodeConstraints.tsx @@ -87,8 +87,8 @@ const EpisodeConstraints: React.FC = ({ constraints, on { + value={radioValues} + onChange={(e) => { if ( radioValues === TemporalConstraintsKind.PARTIAL_EPISODE_CONSTRAINT && constraints.find( @@ -101,7 +101,7 @@ const EpisodeConstraints: React.FC = ({ constraints, on onChangeValue(e as TemporalConstraintsKind) } }} - items={episodesTemporalConstraintsTypes} + options={episodesTemporalConstraintsTypes} style={{ margin: '1em', justifyContent: 'space-around' }} /> diff --git a/src/components/CreationCohort/DiagramView/components/TemporalConstraintCard/components/TemporalConstraintModal/StayConstraints.tsx b/src/components/CreationCohort/DiagramView/components/TemporalConstraintCard/components/TemporalConstraintModal/StayConstraints.tsx index 8cc66f965..77c23193a 100644 --- a/src/components/CreationCohort/DiagramView/components/TemporalConstraintCard/components/TemporalConstraintModal/StayConstraints.tsx +++ b/src/components/CreationCohort/DiagramView/components/TemporalConstraintCard/components/TemporalConstraintModal/StayConstraints.tsx @@ -79,8 +79,8 @@ const StayConstraints: React.FC = ({ constraints, onChange Contraintes sur les séjours { + value={radioValues} + onChange={(e) => { if ( radioValues === TemporalConstraintsKind.PARTIAL_CONSTRAINT && constraints.find((constraint) => constraint.constraintType === TemporalConstraintsKind.SAME_ENCOUNTER) @@ -91,7 +91,7 @@ const StayConstraints: React.FC = ({ constraints, onChange onChangeValue(e as TemporalConstraintsKind) } }} - items={temporalConstraintsTypes} + options={temporalConstraintsTypes} style={{ margin: '1em', justifyContent: 'space-around' }} /> diff --git a/src/components/Dashboard/BiologyList/index.tsx b/src/components/Dashboard/BiologyList/index.tsx index 66a9f6156..ebdb3b9f5 100644 --- a/src/components/Dashboard/BiologyList/index.tsx +++ b/src/components/Dashboard/BiologyList/index.tsx @@ -8,12 +8,9 @@ import { BlockWrapper } from 'components/ui/Layout' import Button from 'components/ui/Button' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import DisplayDigits from 'components/ui/Display/DisplayDigits' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import IppFilter from 'components/Filters/IppFilter' import List from 'components/ui/List' import Modal from 'components/ui/Modal' -import NdaFilter from 'components/Filters/NdaFilter' import SearchInput from 'components/ui/Searchbar/SearchInput' import TextInput from 'components/Filters/TextInput' @@ -34,6 +31,7 @@ import { getCodeList } from 'services/aphp/serviceValueSets' import { getConfig } from 'config' import CodeFilter from 'components/Filters/CodeFilter' import { getValueSetsFromSystems } from 'utils/valueSets' +import MultiSelectInput from 'components/Filters/MultiSelectInput' type BiologyListProps = { deidentified?: boolean @@ -79,6 +77,7 @@ const BiologyList = ({ deidentified }: BiologyListProps) => { }, { changeOrderBy, changeSearchInput, addFilters, removeFilter, addSearchCriterias } ] = useSearchCriterias(initBioSearchCriterias) + console.log('test filters', filters) const filtersAsArray = useMemo( () => selectFiltersAsArray({ @@ -319,8 +318,17 @@ const BiologyList = ({ deidentified }: BiologyListProps) => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - {!deidentified && } - {!deidentified && } + {!deidentified && ( + + )} + {!deidentified && ( + + )} { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { {!deidentified && ( - )} {!deidentified && ( - )} @@ -470,11 +483,12 @@ const BiologyList = ({ deidentified }: BiologyListProps) => { /> - diff --git a/src/components/Dashboard/Documents/index.tsx b/src/components/Dashboard/Documents/index.tsx index 776addafd..9f115794e 100644 --- a/src/components/Dashboard/Documents/index.tsx +++ b/src/components/Dashboard/Documents/index.tsx @@ -29,10 +29,7 @@ import useSearchCriterias, { initAllDocsSearchCriterias } from 'reducers/searchC import { AlertWrapper } from 'components/ui/Alert' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import DocTypesFilter from 'components/Filters/DocTypesFilter' -import DocStatusFilter from 'components/Filters/DocStatusFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import IppFilter from 'components/Filters/IppFilter' -import NdaFilter from 'components/Filters/NdaFilter' import { ResourceType } from 'types/requestCriterias' import { Save, SavedSearch } from '@mui/icons-material' import TextInput from 'components/Filters/TextInput' @@ -40,7 +37,6 @@ import { useSavedFilters } from 'hooks/filters/useSavedFilters' import List from 'components/ui/List' import { useAppDispatch, useAppSelector } from 'state' import Modal from 'components/ui/Modal' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' @@ -49,6 +45,7 @@ import { DocumentReference } from 'fhir/r4' import { getCodeList } from 'services/aphp/serviceValueSets' import { getConfig } from 'config' import { v4 as uuidv4 } from 'uuid' +import MultiSelectInput from 'components/Filters/MultiSelectInput' type DocumentsProps = { deidentified: boolean @@ -132,7 +129,10 @@ const Documents: React.FC = ({ deidentified }) => { const controllerRef = useRef(new AbortController()) const isFirstRender = useRef(true) - const docStatusesList = [FilterByDocumentStatus.VALIDATED, FilterByDocumentStatus.NOT_VALIDATED] + const docStatusesList = [ + { id: FilterByDocumentStatus.VALIDATED, label: FilterByDocumentStatus.VALIDATED }, + { id: FilterByDocumentStatus.NOT_VALIDATED, label: FilterByDocumentStatus.NOT_VALIDATED } + ] const fetchDocumentsList = async () => { try { @@ -385,9 +385,23 @@ const Documents: React.FC = ({ deidentified }) => { onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} color="secondary" > - {!deidentified && } - {!deidentified && } - + {!deidentified && ( + + )} + {!deidentified && ( + + )} + = ({ deidentified }) => { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - = ({ deidentified }) => { {!deidentified && ( - )} {!deidentified && ( - )} - @@ -559,11 +579,12 @@ const Documents: React.FC = ({ deidentified }) => { /> - diff --git a/src/components/Dashboard/ExportModal/exportUtils.ts b/src/components/Dashboard/ExportModal/exportUtils.ts index 2f066b7ab..c8843e739 100644 --- a/src/components/Dashboard/ExportModal/exportUtils.ts +++ b/src/components/Dashboard/ExportModal/exportUtils.ts @@ -299,7 +299,7 @@ const fetchDocumentsCount = async (cohortId: string, documentsFilters?: SearchCr size: 0, _list: [cohortId], searchBy: documentsFilters.searchBy, - docStatuses: docStatuses, + docStatuses: docStatuses.map((obj) => obj.id), _text: documentsFilters.searchInput, type: docTypes.map((docType) => docType.code).join(), 'encounter-identifier': nda, diff --git a/src/components/Dashboard/FormsList/index.tsx b/src/components/Dashboard/FormsList/index.tsx index 7a8ec9e9e..479b19fe7 100644 --- a/src/components/Dashboard/FormsList/index.tsx +++ b/src/components/Dashboard/FormsList/index.tsx @@ -5,12 +5,10 @@ import { CircularProgress, Grid, useMediaQuery, useTheme } from '@mui/material' import { FilterList } from '@mui/icons-material' import Button from 'components/ui/Button' import DisplayDigits from 'components/ui/Display/DisplayDigits' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import IppFilter from 'components/Filters/IppFilter' import Modal from 'components/ui/Modal' import { DTTB_ResultsType as ResultsType, LoadingStatus } from 'types' -import { FilterKeys, LabelObject } from 'types/searchCriterias' +import { FilterKeys, FormNames, LabelObject } from 'types/searchCriterias' import { CanceledError } from 'axios' import services from 'services/aphp' import useSearchCriterias, { initFormsCriterias } from 'reducers/searchCriteriasReducer' @@ -18,13 +16,27 @@ import { cancelPendingRequest } from 'utils/abortController' import { selectFiltersAsArray } from 'utils/filters' import { SourceType } from 'types/scope' import { Questionnaire } from 'fhir/r4' -import MaternityFormFilter from 'components/Filters/MaternityFormFilter' import DataTableForms from 'components/DataTable/DataTableForms' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' import Chip from 'components/ui/Chip' import { getCodeList } from 'services/aphp/serviceValueSets' import { getConfig } from 'config' +import TextInput from 'components/Filters/TextInput' +import MultiSelectInput from 'components/Filters/MultiSelectInput' +import labels from 'labels.json' +import CheckboxsFilter from 'components/Filters/CheckboxsFilter' + +const formOptions = [ + { + id: FormNames.PREGNANCY, + label: labels.formNames.pregnancy + }, + { + id: FormNames.HOSPIT, + label: labels.formNames.hospit + } +] const FormsList = () => { const theme = useTheme() @@ -206,17 +218,23 @@ const FormsList = () => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - - + + - diff --git a/src/components/Dashboard/ImagingList/index.tsx b/src/components/Dashboard/ImagingList/index.tsx index 7918ce82a..4e0cc77ab 100644 --- a/src/components/Dashboard/ImagingList/index.tsx +++ b/src/components/Dashboard/ImagingList/index.tsx @@ -1,28 +1,21 @@ import React, { useState, useEffect, useRef, useMemo, useContext } from 'react' import useSearchCriterias, { initImagingCriterias } from 'reducers/searchCriteriasReducer' import services from 'services/aphp' - import { CircularProgress, Grid, Tooltip } from '@mui/material' import { FilterList, Save, SavedSearch } from '@mui/icons-material' - import Button from 'components/ui/Button' import Chip from 'components/ui/Chip' import DataTableImaging from 'components/DataTable/DataTableImaging' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import DisplayDigits from 'components/ui/Display/DisplayDigits' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import IppFilter from 'components/Filters/IppFilter' import Modal from 'components/ui/Modal' -import ModalityFilter from 'components/Filters/ModalityFilter/ModalityFilter' -import NdaFilter from 'components/Filters/NdaFilter' import SearchInput from 'components/ui/Searchbar/SearchInput' - import { CohortImaging, LoadingStatus, DTTB_ResultsType as ResultsType } from 'types' import { Direction, FilterKeys, ImagingFilters, LabelObject, Order } from 'types/searchCriterias' import { cancelPendingRequest } from 'utils/abortController' import { selectFiltersAsArray } from 'utils/filters' - import { CanceledError } from 'axios' import { AlertWrapper } from 'components/ui/Alert' import { ResourceType } from 'types/requestCriterias' @@ -31,12 +24,12 @@ import TextInput from 'components/Filters/TextInput' import List from 'components/ui/List' import { useAppDispatch, useAppSelector } from 'state' import { BlockWrapper } from 'components/ui/Layout' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { AppConfig, getConfig } from 'config' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' import { getCodeList } from 'services/aphp/serviceValueSets' +import MultiSelectInput from 'components/Filters/MultiSelectInput' type ImagingListProps = { deidentified?: boolean @@ -289,19 +282,29 @@ const ImagingList = ({ deidentified }: ImagingListProps) => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - {!deidentified && } - {!deidentified && } - + {!deidentified && ( + + )} + {!deidentified && ( + + )} + - { )} {!deidentified && ( - )} - { onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} onClean={triggerClean} > - {!deidentified && } - {!deidentified && } + {!deidentified && ( + + )} + {!deidentified && ( + + )} {selectedTab.id === ResourceType.MEDICATION_REQUEST && prescriptionTypes && ( - )} {selectedTab.id === ResourceType.MEDICATION_ADMINISTRATION && administrationRoutes && ( - )} @@ -392,10 +397,11 @@ const MedicationList = ({ deidentified }: MedicationListProps) => { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { /> )} {!deidentified && ( - )} {!deidentified && ( - )} {selectedTab.id === ResourceType.MEDICATION_REQUEST && ( - )} {selectedTab.id === ResourceType.MEDICATION_ADMINISTRATION && ( - )} { name={FilterKeys.CODE} value={selectedSavedFilter?.filterParams.filters.code ?? []} /> + { value={selectedSavedFilter?.filterParams.filters.executiveUnits || []} name={FilterKeys.EXECUTIVE_UNITS} /> - diff --git a/src/components/Dashboard/PMSIList/index.tsx b/src/components/Dashboard/PMSIList/index.tsx index e6d925106..5d3396168 100644 --- a/src/components/Dashboard/PMSIList/index.tsx +++ b/src/components/Dashboard/PMSIList/index.tsx @@ -9,16 +9,11 @@ import Button from 'components/ui/Button' import CodeFilter from 'components/Filters/CodeFilter' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import DataTablePmsi from 'components/DataTable/DataTablePmsi' -import DiagnosticTypesFilter from 'components/Filters/DiagnosticTypesFilter' import DisplayDigits from 'components/ui/Display/DisplayDigits' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import IppFilter from 'components/Filters/IppFilter' import List from 'components/ui/List' import Modal from 'components/ui/Modal' -import NdaFilter from 'components/Filters/NdaFilter' import { PMSITabs } from 'components/Patient/PatientPMSI' -import SourceFilter from 'components/Filters/SourceFilter' import Searchbar from 'components/ui/Searchbar' import SearchInput from 'components/ui/Searchbar/SearchInput' import Tabs from 'components/ui/Tabs' @@ -42,11 +37,29 @@ import { getCodeList } from 'services/aphp/serviceValueSets' import { getConfig } from 'config' import { getValueSetsFromSystems } from 'utils/valueSets' import { getPMSITab } from 'utils/tabsUtils' +import MultiSelectInput from 'components/Filters/MultiSelectInput' +import RadioGroupFilter from 'components/Filters/RadioGroupFilter' type PMSIListProps = { deidentified?: boolean } +enum Source { + AREM = 'AREM', + ORBIS = 'ORBIS' +} + +const sourceOptions = [ + { + id: Source.AREM, + label: Source.AREM + }, + { + id: Source.ORBIS, + label: Source.ORBIS + } +] + const PMSIList = ({ deidentified }: PMSIListProps) => { const [toggleFilterByModal, setToggleFilterByModal] = useState(false) const [toggleSaveFiltersModal, setToggleSaveFiltersModal] = useState(false) @@ -368,23 +381,36 @@ const PMSIList = ({ deidentified }: PMSIListProps) => { onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} onClean={triggerClean} > - {!deidentified && } - {!deidentified && } + {!deidentified && ( + + )} + {!deidentified && ( + + )} {selectedTab.id === ResourceType.CONDITION && ( - )} - {selectedTab.id !== ResourceType.CLAIM && } + {selectedTab.id !== ResourceType.CLAIM && ( + + )} - @@ -483,19 +509,23 @@ const PMSIList = ({ deidentified }: PMSIListProps) => { {!deidentified && ( - )} {!deidentified && ( - )} @@ -509,20 +539,23 @@ const PMSIList = ({ deidentified }: PMSIListProps) => { {selectedTab.id === ResourceType.CONDITION && ( - )} {selectedTab.id !== ResourceType.CLAIM && ( - )} @@ -545,11 +578,12 @@ const PMSIList = ({ deidentified }: PMSIListProps) => { /> - diff --git a/src/components/Dashboard/PatientList/index.tsx b/src/components/Dashboard/PatientList/index.tsx index dba8d8797..3ad01adf4 100644 --- a/src/components/Dashboard/PatientList/index.tsx +++ b/src/components/Dashboard/PatientList/index.tsx @@ -23,10 +23,12 @@ import DisplayDigits from 'components/ui/Display/DisplayDigits' import { Direction, FilterKeys, + genderOptions, Order, PatientsFilters, searchByListPatients, - SearchByTypes + SearchByTypes, + vitalStatusesOptions } from 'types/searchCriterias' import Button from 'components/ui/Button' import Modal from 'components/ui/Modal' @@ -36,8 +38,7 @@ import useSearchCriterias, { initPatientsSearchCriterias } from 'reducers/search import { selectFiltersAsArray } from 'utils/filters' import Chip from 'components/ui/Chip' import BirthdatesRangesFilter from 'components/Filters/BirthdatesRangesFilters' -import GendersFilter from 'components/Filters/GendersFilter' -import VitalStatusesFilter from 'components/Filters/VitalStatusesFilter' +import CheckboxsFilter from 'components/Filters/CheckboxsFilter' import TextInput from 'components/Filters/TextInput' import { useSavedFilters } from 'hooks/filters/useSavedFilters' import { ResourceType } from 'types/requestCriterias' @@ -97,7 +98,6 @@ const PatientList = ({ total, deidentified }: PatientListProps) => { }, { changeOrderBy, changeSearchBy, changeSearchInput, addFilters, removeFilter, addSearchCriterias } ] = useSearchCriterias(initPatientsSearchCriterias) - const filtersAsArray = useMemo(() => { return selectFiltersAsArray({ genders, vitalStatuses, birthdatesRanges }) }, [genders, vitalStatuses, birthdatesRanges]) @@ -291,8 +291,20 @@ const PatientList = ({ total, deidentified }: PatientListProps) => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ genders, birthdatesRanges, vitalStatuses, ...newFilters })} > - - + searchCriteriaForm.changeInput(FilterKeys.GENDERS, value)} + /> + searchCriteriaForm.changeInput(FilterKeys.VITAL_STATUSES, value)} + /> { )} - - { - const context = useContext(FormContext) - const [administrationTypes, setAdministrationTypes] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, administrationTypes) - }, [administrationTypes]) - - return ( - - Voie d'administration : - { - setAdministrationTypes(value) - }} - options={allAdministrationTypes} - value={administrationTypes} - disableCloseOnSelect - getOptionLabel={(administrationRoute) => capitalizeFirstLetter(administrationRoute.label)} - renderOption={(props, administrationRoute) => ( -
  • {capitalizeFirstLetter(administrationRoute.label)}
  • - )} - renderInput={(params) => ( - - )} - /> -
    - ) -} - -export default AdministrationTypesFilter diff --git a/src/components/Filters/BirthdatesRangesFilters/index.tsx b/src/components/Filters/BirthdatesRangesFilters/index.tsx index 2084985d9..72fdf526b 100644 --- a/src/components/Filters/BirthdatesRangesFilters/index.tsx +++ b/src/components/Filters/BirthdatesRangesFilters/index.tsx @@ -1,4 +1,4 @@ -import { InputWrapper } from 'components/ui/Inputs' +import { InputWrapper } from 'components/ui/Inputs/styles' import DurationRange from 'components/ui/Inputs/DurationRange' import { FormContext } from 'components/ui/Modal' import React, { useContext, useEffect, useState } from 'react' @@ -31,7 +31,7 @@ const BirthdatesRangesFilter = ({ return ( { + const context = useContext(FormContext) + const [inputs, setInputs] = useState(value) + + useEffect(() => { + if (context?.updateFormData) context.updateFormData(name, inputs) + }, [inputs]) + + return ( + + {label && {label}} + setInputs(toggleFilter(inputs, (e.target as HTMLInputElement).value))}> + <> + {options.map((option) => ( + } + label={option.label} + /> + ))} + + + + ) +} + +export default CheckboxsFilter diff --git a/src/components/Filters/CodeFilter/index.tsx b/src/components/Filters/CodeFilter/index.tsx index fe9dddcc6..7cb7542ca 100644 --- a/src/components/Filters/CodeFilter/index.tsx +++ b/src/components/Filters/CodeFilter/index.tsx @@ -1,6 +1,6 @@ import { Typography } from '@mui/material' import ValueSetField from 'components/SearchValueSet/ValueSetField' -import { InputWrapper } from 'components/ui/Inputs' +import { InputWrapper } from 'components/ui/Inputs/styles' import { FormContext } from 'components/ui/Modal' import React, { useContext, useEffect, useState } from 'react' import { Hierarchy } from 'types/hierarchy' diff --git a/src/components/Filters/CohortStatusFilter/index.tsx b/src/components/Filters/CohortStatusFilter/index.tsx deleted file mode 100644 index 9946628e6..000000000 --- a/src/components/Filters/CohortStatusFilter/index.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Autocomplete, TextField, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import React, { useContext, useEffect, useState } from 'react' -import { ValueSet } from 'types' -import { capitalizeFirstLetter } from 'utils/capitalize' - -type CohortStatusFilterProps = { - value: ValueSet[] - name: string - allStatus: ValueSet[] -} - -const CohortStatusFilter = ({ name, value, allStatus }: CohortStatusFilterProps) => { - const context = useContext(FormContext) - const [status, setStatus] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, status) - }, [status]) - - return ( - - Statut : - { - setStatus(value) - }} - options={allStatus} - value={status} - disableCloseOnSelect - getOptionLabel={(status) => capitalizeFirstLetter(status.display)} - renderOption={(props, status) =>
  • {capitalizeFirstLetter(status.display)}
  • } - renderInput={(params) => } - /> -
    - ) -} - -export default CohortStatusFilter diff --git a/src/components/Filters/CohortsTypeFilter/index.tsx b/src/components/Filters/CohortsTypeFilter/index.tsx deleted file mode 100644 index d2d2e02d0..000000000 --- a/src/components/Filters/CohortsTypeFilter/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { FormControlLabel, Radio, RadioGroup, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import React, { useContext, useEffect, useState } from 'react' -import { CohortsType, CohortsTypeLabel } from 'types/cohorts' - -type CohortsTypesFilterProps = { - value: CohortsType - name: string -} - -const CohortsTypesFilter = ({ name, value }: CohortsTypesFilterProps) => { - const context = useContext(FormContext) - const [cohortsType, setCohortsType] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, cohortsType) - }, [cohortsType]) - - return ( - - Favoris : - setCohortsType(event.target.value as CohortsType)} - row={true} - > - } label={CohortsTypeLabel.ALL} /> - } - label={CohortsTypeLabel.FAVORITE} - /> - } - label={CohortsTypeLabel.NOT_FAVORITE} - /> - - - ) -} - -export default CohortsTypesFilter diff --git a/src/components/Filters/DiagnosticTypesFilter/index.tsx b/src/components/Filters/DiagnosticTypesFilter/index.tsx deleted file mode 100644 index 57c2a7fb5..000000000 --- a/src/components/Filters/DiagnosticTypesFilter/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Autocomplete, TextField, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import React, { useContext, useEffect, useState } from 'react' -import { LabelObject } from 'types/searchCriterias' -import { capitalizeFirstLetter } from 'utils/capitalize' - -type DiagnosticTypesFilterProps = { - value: LabelObject[] - name: string - allDiagnosticTypesList: LabelObject[] - disabled?: boolean -} - -const DiagnosticTypesFilter = ({ - name, - value, - allDiagnosticTypesList, - disabled = false -}: DiagnosticTypesFilterProps) => { - const context = useContext(FormContext) - const [diagnosticTypes, setDiagnosticTypes] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, diagnosticTypes) - }, [diagnosticTypes]) - - return ( - - Type de diagnostics : - { - setDiagnosticTypes(value) - }} - options={allDiagnosticTypesList} - value={diagnosticTypes} - disableCloseOnSelect - getOptionLabel={(diagnosticType) => capitalizeFirstLetter(diagnosticType.label)} - renderOption={(props, diagnosticType) =>
  • {capitalizeFirstLetter(diagnosticType.label)}
  • } - renderInput={(params) => ( - - )} - /> -
    - ) -} - -export default DiagnosticTypesFilter diff --git a/src/components/Filters/DocStatusFilter/index.tsx b/src/components/Filters/DocStatusFilter/index.tsx deleted file mode 100644 index 40de56190..000000000 --- a/src/components/Filters/DocStatusFilter/index.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Autocomplete, TextField, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import React, { useContext, useEffect, useState } from 'react' - -type DocStatusFilterProps = { - name: string - value: string[] - docStatusesList: string[] - disabled?: boolean -} - -const DocStatusFilter = ({ name, value, docStatusesList, disabled = false }: DocStatusFilterProps) => { - const context = useContext(FormContext) - const [docStatuses, setDocStatus] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, docStatuses) - }, [docStatuses]) - - return ( - - Statut de documents : - { - setDocStatus(val) - }} - options={docStatusesList} - value={docStatuses} - renderInput={(params) => } - /> - - ) -} - -export default DocStatusFilter diff --git a/src/components/Filters/DocTypesFilter/index.tsx b/src/components/Filters/DocTypesFilter/index.tsx index 864223fb8..d681ffa09 100644 --- a/src/components/Filters/DocTypesFilter/index.tsx +++ b/src/components/Filters/DocTypesFilter/index.tsx @@ -1,5 +1,5 @@ import { Autocomplete, AutocompleteRenderGroupParams, Checkbox, Grid, TextField, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' +import { InputWrapper } from 'components/ui/Inputs/styles' import { FormContext } from 'components/ui/Modal' import React, { useContext, useEffect, useState } from 'react' import { SimpleCodeType } from 'types' diff --git a/src/components/Filters/EncounterStatusFilter/index.tsx b/src/components/Filters/EncounterStatusFilter/index.tsx deleted file mode 100644 index 94c5ed380..000000000 --- a/src/components/Filters/EncounterStatusFilter/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react' -import { Autocomplete, TextField, Typography } from '@mui/material' -import { FormContext } from 'components/ui/Modal' -import { LabelObject } from 'types/searchCriterias' -import { InputWrapper } from 'components/ui/Inputs' - -type EncounterStatusFilterProps = { - name: string - encounterStatusList: LabelObject[] - value: LabelObject[] - disabled?: boolean -} - -const EncounterStatusFilter = ({ name, value, encounterStatusList, disabled = false }: EncounterStatusFilterProps) => { - const context = useContext(FormContext) - const [encounterStatus, setEncounterStatus] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, encounterStatus) - }, [encounterStatus]) - - return ( - - Statut de la visite associée : - { - setEncounterStatus(value) - }} - options={encounterStatusList} - value={encounterStatus} - disableCloseOnSelect - getOptionLabel={(encounterStatus: LabelObject) => encounterStatus.label} - renderOption={(props, encounterStatus: LabelObject) =>
  • {encounterStatus.label}
  • } - renderInput={(params) => ( - - )} - /> -
    - ) -} - -export default EncounterStatusFilter diff --git a/src/components/Filters/GendersFilter/index.tsx b/src/components/Filters/GendersFilter/index.tsx deleted file mode 100644 index 425a7f1fb..000000000 --- a/src/components/Filters/GendersFilter/index.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { Checkbox, FormControlLabel, FormGroup, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import React, { useContext, useEffect, useState } from 'react' -import { GenderStatus, GenderStatusLabel } from 'types/searchCriterias' -import { isChecked, toggleFilter } from 'utils/filters' - -type GendersFilterProps = { - value: GenderStatus[] - name: string - disabled?: boolean -} - -const GendersFilter = ({ name, value, disabled = false }: GendersFilterProps) => { - const context = useContext(FormContext) - const [genders, setGenders] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, genders) - }, [genders]) - - return ( - - Genre : - setGenders(toggleFilter(genders, (e.target as HTMLInputElement).value) as GenderStatus[])} - > - } - label={GenderStatusLabel.FEMALE} - /> - } - label={GenderStatusLabel.MALE} - /> - } - label={GenderStatusLabel.OTHER} - /> - } - label={GenderStatusLabel.UNKNOWN} - /> - - - ) -} - -export default GendersFilter diff --git a/src/components/Filters/IppFilter/index.tsx b/src/components/Filters/IppFilter/index.tsx deleted file mode 100644 index 755b89f6e..000000000 --- a/src/components/Filters/IppFilter/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { TextField, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import React, { useContext, useEffect, useState } from 'react' - -type IppFilterProps = { - value: string - name: string - disabled?: boolean -} - -const IppFilter = ({ name, value, disabled = false }: IppFilterProps) => { - const context = useContext(FormContext) - const [ipp, setIpp] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, ipp) - }, [ipp]) - - return ( - - IPP : - setIpp(event.target.value)} - /> - - ) -} - -export default IppFilter diff --git a/src/components/Filters/MaternityFormFilter/index.tsx b/src/components/Filters/MaternityFormFilter/index.tsx deleted file mode 100644 index 1d45be426..000000000 --- a/src/components/Filters/MaternityFormFilter/index.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react' -import { Checkbox, FormControlLabel, FormGroup, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import { FormNames } from 'types/searchCriterias' -import { isChecked, toggleFilter } from 'utils/filters' -import labels from 'labels.json' - -type MaternityFormFilterProps = { - value: FormNames[] - name: string - disabled?: boolean -} - -const MaternityFormFilter = ({ name, value, disabled = false }: MaternityFormFilterProps) => { - const context = useContext(FormContext) - const [formName, setFormName] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, formName) - }, [formName]) - - return ( - - Formulaire : - setFormName(toggleFilter(formName, (e.target as HTMLInputElement).value) as FormNames[])} - > - } - label={labels.formNames.pregnancy} - /> - } - label={labels.formNames.hospit} - /> - - - ) -} - -export default MaternityFormFilter diff --git a/src/components/Filters/ModalityFilter/ModalityFilter.tsx b/src/components/Filters/ModalityFilter/ModalityFilter.tsx deleted file mode 100644 index 27b5c996e..000000000 --- a/src/components/Filters/ModalityFilter/ModalityFilter.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react' -import { Autocomplete, TextField, Typography } from '@mui/material' -import { FormContext } from 'components/ui/Modal' -import { LabelObject } from 'types/searchCriterias' -import { InputWrapper } from 'components/ui/Inputs' - -type ModalityFilterProps = { - name: string - modalitiesList: LabelObject[] - value: LabelObject[] - disabled?: boolean -} - -const ModalityFilter = ({ name, value, modalitiesList, disabled = false }: ModalityFilterProps) => { - const context = useContext(FormContext) - const [modalities, setModalities] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, modalities) - }, [modalities]) - - return ( - - Modalités : - { - setModalities(value) - }} - options={modalitiesList} - value={modalities} - disableCloseOnSelect - getOptionLabel={(modality: LabelObject) => modality.label} - renderOption={(props, modality: LabelObject) =>
  • {modality.label}
  • } - renderInput={(params) => } - /> -
    - ) -} - -export default ModalityFilter diff --git a/src/components/Filters/MultiSelectInput/index.tsx b/src/components/Filters/MultiSelectInput/index.tsx new file mode 100644 index 000000000..595c6670d --- /dev/null +++ b/src/components/Filters/MultiSelectInput/index.tsx @@ -0,0 +1,44 @@ +import { Autocomplete, TextField, Typography } from '@mui/material' +import { InputWrapper } from 'components/ui/Inputs/styles' +import { FormContext } from 'components/ui/Modal' +import React, { useContext, useEffect, useState } from 'react' +import { LabelObject } from 'types/searchCriterias' +import { capitalizeFirstLetter } from 'utils/capitalize' + +type PrescriptionTypesFilterProps = { + value: LabelObject[] + name: string + label?: string + options: LabelObject[] + disabled?: boolean +} + +const MultiSelectInput = ({ name, value, label, options, disabled = false }: PrescriptionTypesFilterProps) => { + const context = useContext(FormContext) + const [input, setInput] = useState(value) + + useEffect(() => { + if (context?.updateFormData) context.updateFormData(name, input) + }, [input]) + + return ( + + {label && {label}} + { + setInput(value) + }} + options={options} + value={input} + disableCloseOnSelect + getOptionLabel={(elem) => capitalizeFirstLetter(elem.label)} + renderOption={(props, elem) =>
  • {capitalizeFirstLetter(elem.label)}
  • } + renderInput={(params) => } + /> +
    + ) +} + +export default MultiSelectInput diff --git a/src/components/Filters/NdaFilter/index.tsx b/src/components/Filters/NdaFilter/index.tsx deleted file mode 100644 index 3efaff883..000000000 --- a/src/components/Filters/NdaFilter/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { TextField, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import React, { useContext, useEffect, useState } from 'react' - -type NdaFilterProps = { - value: string - name: string - disabled?: boolean -} - -const NdaFilter = ({ name, value, disabled = false }: NdaFilterProps) => { - const context = useContext(FormContext) - const [nda, setNda] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, nda) - }, [nda]) - - return ( - - NDA : - setNda(event.target.value)} - /> - - ) -} - -export default NdaFilter diff --git a/src/components/Filters/OrderByFilter/index.tsx b/src/components/Filters/OrderByFilter/index.tsx deleted file mode 100644 index b217bbe4a..000000000 --- a/src/components/Filters/OrderByFilter/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react' -import { FormContext } from 'components/ui/Modal' -import Select from 'components/ui/Searchbar/Select' -import { Order } from 'types/searchCriterias' -import { PatientTableLabels } from 'types/patient' - -type OrderByFilterProps = { - orderByValue: Order - name: string - items: { - id: Order - label: PatientTableLabels - }[] -} - -const OrderByFilter = ({ orderByValue, name, items }: OrderByFilterProps) => { - const context = useContext(FormContext) - const [orderBy, setOrderBy] = useState(orderByValue) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, orderBy) - }, [orderBy]) - - return ( - + ) +} + +export default SelectInput diff --git a/src/components/Filters/SourceFilter/index.tsx b/src/components/Filters/SourceFilter/index.tsx deleted file mode 100644 index 8eafcea11..000000000 --- a/src/components/Filters/SourceFilter/index.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react' -import { RadioGroup, Radio, FormControlLabel, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' - -type SourceFilterProps = { - value: string - name: string - disabled?: boolean -} - -const SourceFilter = ({ name, value, disabled = false }: SourceFilterProps) => { - const context = useContext(FormContext) - const [source, setSource] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, source) - }, [source]) - - return ( - - Source : - setSource((e.target as HTMLInputElement).value)} - > - } label="AREM" /> - } label="ORBIS" /> - - - ) -} - -export default SourceFilter diff --git a/src/components/Filters/TextInput/index.tsx b/src/components/Filters/TextInput/index.tsx index 0cb46a92e..5fbbbc992 100644 --- a/src/components/Filters/TextInput/index.tsx +++ b/src/components/Filters/TextInput/index.tsx @@ -1,5 +1,5 @@ import { Grid, TextField, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' +import { InputWrapper } from 'components/ui/Inputs/styles' import { ErrorMessage } from 'components/ui/Inputs/Errors' import { FormContext } from 'components/ui/Modal' import React, { useContext, useEffect, useState } from 'react' diff --git a/src/components/Filters/VitalStatusesFilter.tsx/index.tsx b/src/components/Filters/VitalStatusesFilter.tsx/index.tsx deleted file mode 100644 index dd6abec68..000000000 --- a/src/components/Filters/VitalStatusesFilter.tsx/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Checkbox, FormControlLabel, FormGroup, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import React, { useContext, useEffect, useState } from 'react' -import { VitalStatusLabel } from 'types/searchCriterias' -import { VitalStatus } from 'types/searchCriterias' -import { isChecked, toggleFilter } from 'utils/filters' - -type VitalStatusesFilterProps = { - value: VitalStatus[] - name: string -} - -const VitalStatusesFilter = ({ name, value }: VitalStatusesFilterProps) => { - const context = useContext(FormContext) - const [vitalStatuses, setVitalStatuses] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, vitalStatuses) - }, [vitalStatuses]) - - return ( - - Statut vital : - - setVitalStatuses(toggleFilter(vitalStatuses, (e.target as HTMLInputElement).value) as VitalStatus[]) - } - row - > - } - label={VitalStatusLabel.ALIVE} - /> - } - label={VitalStatusLabel.DECEASED} - /> - - - ) -} - -export default VitalStatusesFilter diff --git a/src/components/Filters/VitalStatusesFilter/index.tsx b/src/components/Filters/VitalStatusesFilter/index.tsx deleted file mode 100644 index 6a92ddb60..000000000 --- a/src/components/Filters/VitalStatusesFilter/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react' -import { Checkbox, FormControlLabel, FormGroup, Typography } from '@mui/material' -import { InputWrapper } from 'components/ui/Inputs' -import { FormContext } from 'components/ui/Modal' -import { VitalStatus } from 'types/searchCriterias' -import { isChecked, toggleFilter } from 'utils/filters' - -type VitalStatusesFilterProps = { - value: VitalStatus[] - name: string - disabled?: boolean -} - -const VitalStatusesFilter = ({ name, value, disabled = false }: VitalStatusesFilterProps) => { - const context = useContext(FormContext) - const [vitalStatuses, setVitalStatuses] = useState(value) - - useEffect(() => { - if (context?.updateFormData) context.updateFormData(name, vitalStatuses) - }, [vitalStatuses]) - - return ( - - Statut vital : - - setVitalStatuses(toggleFilter(vitalStatuses, (e.target as HTMLInputElement).value) as VitalStatus[]) - } - row - > - } - label="Patients vivants" - /> - } - label="Patients décédés" - /> - - - ) -} - -export default VitalStatusesFilter diff --git a/src/components/Patient/PatientBiology/index.tsx b/src/components/Patient/PatientBiology/index.tsx index 40ba7e3fb..cb5c4acb7 100644 --- a/src/components/Patient/PatientBiology/index.tsx +++ b/src/components/Patient/PatientBiology/index.tsx @@ -1,15 +1,10 @@ import React, { useEffect, useMemo, useRef, useState } from 'react' - import { Checkbox, CircularProgress, Grid, Tooltip, Typography, useMediaQuery, useTheme } from '@mui/material' - import FilterList from 'assets/icones/filter.svg?react' - import DataTableObservation from 'components/DataTable/DataTableObservation' - import { useAppSelector, useAppDispatch } from 'state' import { fetchBiology } from 'state/patient' import { LoadingStatus } from 'types' - import useStyles from './styles' import { cancelPendingRequest } from 'utils/abortController' import { CanceledError } from 'axios' @@ -25,13 +20,11 @@ import Chip from 'components/ui/Chip' import { AlertWrapper } from 'components/ui/Alert' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import NdaFilter from 'components/Filters/NdaFilter' import { Save, SavedSearch } from '@mui/icons-material' import { ResourceType } from 'types/requestCriterias' import { useSavedFilters } from 'hooks/filters/useSavedFilters' import List from 'components/ui/List' import TextInput from 'components/Filters/TextInput' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' @@ -40,6 +33,7 @@ import { getCodeList } from 'services/aphp/serviceValueSets' import { getValueSetsFromSystems } from 'utils/valueSets' import CodeFilter from 'components/Filters/CodeFilter' import { v4 as uuidv4 } from 'uuid' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const PatientBiology = () => { const { classes } = useStyles() @@ -270,7 +264,9 @@ const PatientBiology = () => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - {!searchResults.deidentified && } + {!searchResults.deidentified && ( + + )} { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { />
    - @@ -399,11 +398,12 @@ const PatientBiology = () => { /> - diff --git a/src/components/Patient/PatientBiology/styles.js b/src/components/Patient/PatientBiology/styles.ts similarity index 100% rename from src/components/Patient/PatientBiology/styles.js rename to src/components/Patient/PatientBiology/styles.ts diff --git a/src/components/Patient/PatientDocs/index.tsx b/src/components/Patient/PatientDocs/index.tsx index e361b8ba1..95909f1e6 100644 --- a/src/components/Patient/PatientDocs/index.tsx +++ b/src/components/Patient/PatientDocs/index.tsx @@ -32,20 +32,18 @@ import Chip from 'components/ui/Chip' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import DocTypesFilter from 'components/Filters/DocTypesFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import NdaFilter from 'components/Filters/NdaFilter' import { ResourceType } from 'types/requestCriterias' import { useSavedFilters } from 'hooks/filters/useSavedFilters' import { Save, SavedSearch } from '@mui/icons-material' import TextInput from 'components/Filters/TextInput' import List from 'components/ui/List' -import DocStatusFilter from '../../Filters/DocStatusFilter' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' import { getCodeList } from 'services/aphp/serviceValueSets' import { getConfig } from 'config' import { v4 as uuidv4 } from 'uuid' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const PatientDocs = () => { const dispatch = useAppDispatch() @@ -113,7 +111,10 @@ const PatientDocs = () => { const maintenanceIsActive = meState?.maintenance?.active const isFirstRender = useRef(true) - const docStatusesList = [FilterByDocumentStatus.VALIDATED, FilterByDocumentStatus.NOT_VALIDATED] + const docStatusesList = [ + { id: FilterByDocumentStatus.VALIDATED, label: FilterByDocumentStatus.VALIDATED }, + { id: FilterByDocumentStatus.NOT_VALIDATED, label: FilterByDocumentStatus.NOT_VALIDATED } + ] const fetchDocumentsList = async () => { try { setLoadingStatus(LoadingStatus.FETCHING) @@ -329,8 +330,15 @@ const PatientDocs = () => { addFilters({ ...filters, ...newFilters }) }} > - {!searchResults.deidentified && } - + {!searchResults.deidentified && ( + + )} + { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { {!searchResults.deidentified && ( - )} - - - + { value={selectedSavedFilter?.filterParams.filters.executiveUnits ?? []} name={FilterKeys.EXECUTIVE_UNITS} /> - diff --git a/src/components/Patient/PatientForms/MaternityForms/index.tsx b/src/components/Patient/PatientForms/MaternityForms/index.tsx index 1c53224e3..0c7db7f84 100644 --- a/src/components/Patient/PatientForms/MaternityForms/index.tsx +++ b/src/components/Patient/PatientForms/MaternityForms/index.tsx @@ -4,7 +4,6 @@ import { Grid } from '@mui/material' import { FilterList } from '@mui/icons-material' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import MaternityFormFilter from 'components/Filters/MaternityFormFilter' import Button from 'components/ui/Button' import Chip from 'components/ui/Chip' import { BlockWrapper } from 'components/ui/Layout' @@ -17,15 +16,29 @@ import { cancelPendingRequest } from 'utils/abortController' import { selectFiltersAsArray } from 'utils/filters' import { Questionnaire } from 'fhir/r4' import { LoadingStatus } from 'types' -import { FilterKeys, LabelObject } from 'types/searchCriterias' +import { FilterKeys, FormNames, LabelObject } from 'types/searchCriterias' import Timeline from './Timeline' import services from 'services/aphp' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { useSearchParams } from 'react-router-dom' import { getCleanGroupId } from 'utils/paginationUtils' import { getCodeList } from 'services/aphp/serviceValueSets' import { getConfig } from 'config' +import MultiSelectInput from 'components/Filters/MultiSelectInput' +import CheckboxsFilter from 'components/Filters/CheckboxsFilter' +import labels from 'labels.json' + +const formOptions = [ + { + id: FormNames.PREGNANCY, + label: labels.formNames.pregnancy + }, + { + id: FormNames.HOSPIT, + label: labels.formNames.hospit + } +] + const MaternityForm = () => { const [toggleModal, setToggleModal] = useState(false) @@ -126,17 +139,23 @@ const MaternityForm = () => { onClose={() => setToggleModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - + - )} diff --git a/src/components/Patient/PatientImaging/index.tsx b/src/components/Patient/PatientImaging/index.tsx index 017293340..8c048daeb 100644 --- a/src/components/Patient/PatientImaging/index.tsx +++ b/src/components/Patient/PatientImaging/index.tsx @@ -12,8 +12,6 @@ import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import DisplayDigits from 'components/ui/Display/DisplayDigits' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' import Modal from 'components/ui/Modal' -import ModalityFilter from 'components/Filters/ModalityFilter/ModalityFilter' -import NdaFilter from 'components/Filters/NdaFilter' import SearchInput from 'components/ui/Searchbar/SearchInput' import { cancelPendingRequest } from 'utils/abortController' import { selectFiltersAsArray } from 'utils/filters' @@ -26,13 +24,13 @@ import { Save, SavedSearch } from '@mui/icons-material' import TextInput from 'components/Filters/TextInput' import List from 'components/ui/List' import { BlockWrapper } from 'components/ui/Layout' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { AppConfig, getConfig } from 'config' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' import { getCodeList } from 'services/aphp/serviceValueSets' import { v4 as uuidv4 } from 'uuid' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const PatientImaging = () => { const dispatch = useAppDispatch() @@ -251,18 +249,21 @@ const PatientImaging = () => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - {!searchResults.deidentified && } - + {!searchResults.deidentified && ( + + )} + - { )} {!searchResults.deidentified && ( - )} - { value={selectedSavedFilter?.filterParams.filters.executiveUnits ?? []} name={FilterKeys.EXECUTIVE_UNITS} /> - diff --git a/src/components/Patient/PatientMedication/index.tsx b/src/components/Patient/PatientMedication/index.tsx index 424d2873d..da5f30fba 100644 --- a/src/components/Patient/PatientMedication/index.tsx +++ b/src/components/Patient/PatientMedication/index.tsx @@ -18,11 +18,9 @@ import Modal from 'components/ui/Modal' import { selectFiltersAsArray } from 'utils/filters' import useSearchCriterias, { initMedSearchCriterias } from 'reducers/searchCriteriasReducer' import Chip from 'components/ui/Chip' -import AdministrationTypesFilter from 'components/Filters/AdministrationTypesFilter' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import NdaFilter from 'components/Filters/NdaFilter' -import PrescriptionTypesFilter from 'components/Filters/PrescriptionTypesFilter' +import MultiSelectInput from 'components/Filters/MultiSelectInput' import { Save, SavedSearch } from '@mui/icons-material' import { MedicationLabel, ResourceType } from 'types/requestCriterias' import { useSavedFilters } from 'hooks/filters/useSavedFilters' @@ -30,7 +28,6 @@ import { MedicationAdministration, MedicationRequest } from 'fhir/r4' import TextInput from 'components/Filters/TextInput' import List from 'components/ui/List' import { mapToAttribute, mapToLabel } from 'mappers/pmsi' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' @@ -358,19 +355,23 @@ const PatientMedication = () => { onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} onClean={triggerClean} > - {!searchResults.deidentified && } + {!searchResults.deidentified && ( + + )} {selectedTab.id === ResourceType.MEDICATION_REQUEST && prescriptionTypes && ( - )} {selectedTab.id === ResourceType.MEDICATION_ADMINISTRATION && administrationRoutes && ( - )} @@ -380,10 +381,11 @@ const PatientMedication = () => { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { value={selectedSavedFilter?.filterParams.searchInput} /> )} + {!searchResults.deidentified && ( - )} {selectedTab.id === ResourceType.MEDICATION_REQUEST && ( - )} {selectedTab.id === ResourceType.MEDICATION_ADMINISTRATION && ( - )} { value={selectedSavedFilter?.filterParams.filters.executiveUnits ?? []} name={FilterKeys.EXECUTIVE_UNITS} /> - diff --git a/src/components/Patient/PatientMedication/styles.js b/src/components/Patient/PatientMedication/styles.ts similarity index 100% rename from src/components/Patient/PatientMedication/styles.js rename to src/components/Patient/PatientMedication/styles.ts diff --git a/src/components/Patient/PatientPMSI/index.tsx b/src/components/Patient/PatientPMSI/index.tsx index c1fa51490..c44d0a771 100644 --- a/src/components/Patient/PatientPMSI/index.tsx +++ b/src/components/Patient/PatientPMSI/index.tsx @@ -22,17 +22,13 @@ import { BlockWrapper } from 'components/ui/Layout' import useSearchCriterias, { initPmsiSearchCriterias } from 'reducers/searchCriteriasReducer' import CodeFilter from 'components/Filters/CodeFilter' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' -import DiagnosticTypesFilter from 'components/Filters/DiagnosticTypesFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' -import NdaFilter from 'components/Filters/NdaFilter' -import SourceFilter from 'components/Filters/SourceFilter' import { ResourceType } from 'types/requestCriterias' import { useSavedFilters } from 'hooks/filters/useSavedFilters' import { Save, SavedSearch } from '@mui/icons-material' import TextInput from 'components/Filters/TextInput' import { mapToAttribute, mapToLabel, mapToSourceType } from 'mappers/pmsi' import List from 'components/ui/List' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { AlertWrapper } from 'components/ui/Alert' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' @@ -41,6 +37,24 @@ import { getConfig } from 'config' import { getCodeList } from 'services/aphp/serviceValueSets' import { getValueSetsFromSystems } from 'utils/valueSets' import { v4 as uuidv4 } from 'uuid' +import MultiSelectInput from 'components/Filters/MultiSelectInput' +import RadioGroupFilter from 'components/Filters/RadioGroupFilter' + +enum Source { + AREM = 'AREM', + ORBIS = 'ORBIS' +} + +const sourceOptions = [ + { + id: Source.AREM, + label: Source.AREM + }, + { + id: Source.ORBIS, + label: Source.ORBIS + } +] type PmsiSearchResults = { deidentified: boolean @@ -345,22 +359,28 @@ const PatientPMSI = () => { onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} onClean={triggerClean} > - {!searchResults.deidentified && } + {!searchResults.deidentified && ( + + )} {selectedTab.id === ResourceType.CONDITION && ( - )} - {selectedTab.id !== ResourceType.CLAIM && } + {selectedTab.id !== ResourceType.CLAIM && ( + + )} - @@ -448,10 +468,11 @@ const PatientPMSI = () => { {!searchResults.deidentified && ( - )} @@ -465,20 +486,23 @@ const PatientPMSI = () => { {selectedTab.id === ResourceType.CONDITION && ( - )} {selectedTab.id !== ResourceType.CLAIM && ( - )} @@ -501,11 +525,12 @@ const PatientPMSI = () => { /> - diff --git a/src/components/Patient/PatientSidebar/PatientSidebar.tsx b/src/components/Patient/PatientSidebar/PatientSidebar.tsx index 5e2a9bbf1..e651674fd 100644 --- a/src/components/Patient/PatientSidebar/PatientSidebar.tsx +++ b/src/components/Patient/PatientSidebar/PatientSidebar.tsx @@ -18,9 +18,12 @@ import { OrderBy, OrderByKeys, SearchByTypes, + genderOptions, orderByListPatients, orderByListPatientsDeidentified, - searchByListPatients + orderDirection, + searchByListPatients, + vitalStatusesOptions } from 'types/searchCriterias' import Button from 'components/ui/Button' @@ -38,10 +41,9 @@ import ListPatient from 'components/DataTable/ListPatient' import DisplayLocked from 'components/ui/Display/DisplayLocked' import useSearchCriterias, { initPatientsSearchCriterias } from 'reducers/searchCriteriasReducer' import BirthdatesRangesFilter from 'components/Filters/BirthdatesRangesFilters' -import GendersFilter from 'components/Filters/GendersFilter' -import OrderByFilter from 'components/Filters/OrderByFilter' -import OrderDirectionFilter from 'components/Filters/OrderDirectionFilter' -import VitalStatusesFilter from 'components/Filters/VitalStatusesFilter' +import CheckboxsFilter from 'components/Filters/CheckboxsFilter' +import RadioGroupFilter from 'components/Filters/RadioGroupFilter' +import SelectFilter from 'components/Filters/SelectFilter' type PatientSidebarProps = { total: number @@ -177,8 +179,13 @@ const PatientSidebar = ({ total, patients, openDrawer, onClose, deidentifiedBool onClose={() => setToggleFiltersModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - - + + changeOrderBy(newOrder)} > - - + - diff --git a/src/components/SearchValueSet/index.tsx b/src/components/SearchValueSet/index.tsx index c52034d21..e405b257a 100644 --- a/src/components/SearchValueSet/index.tsx +++ b/src/components/SearchValueSet/index.tsx @@ -75,6 +75,7 @@ const SearchValueSet = ({ references, selectedNodes, onSelect }: SearchValueSetP onChangeSearchInput(event.target.value)} endAdornment={ diff --git a/src/components/ui/Inputs/CheckboxGroup/index.tsx b/src/components/ui/Inputs/CheckboxGroup/index.tsx new file mode 100644 index 000000000..65803f0c5 --- /dev/null +++ b/src/components/ui/Inputs/CheckboxGroup/index.tsx @@ -0,0 +1,52 @@ +import { Checkbox, FormControlLabel, FormGroup, Typography } from '@mui/material' +import { InputWrapper } from 'components/ui/Inputs/styles' +import React, { useEffect, useState } from 'react' +import { LabelObject } from 'types/searchCriterias' +import { isChecked, toggleFilter } from 'utils/filters' + +type CheckboxGroupProps = { + value: T[] + label?: string + disabled?: boolean + options: LabelObject[] + onChange: (value: T[]) => void +} + +const CheckboxGroup = ({ + value, + label, + options, + onChange, + disabled = false +}: CheckboxGroupProps) => { + const [inputs, setInputs] = useState(value) + + useEffect(() => { + onChange(inputs) + }, [inputs]) + + return ( + + {label && {label}} + setInputs(toggleFilter(inputs, (e.target as HTMLInputElement).value as T))} + > + <> + {options.map((option) => ( + } + label={option.label} + /> + ))} + + + + ) +} + +export default CheckboxGroup diff --git a/src/components/ui/Inputs/DurationRange/index.tsx b/src/components/ui/Inputs/DurationRange/index.tsx index 8f6bc0ada..26e5c8468 100644 --- a/src/components/ui/Inputs/DurationRange/index.tsx +++ b/src/components/ui/Inputs/DurationRange/index.tsx @@ -13,9 +13,8 @@ type DurationRangeProps = { value: DurationRangeType label?: string deidentified?: boolean - active?: boolean + disabled?: boolean unit?: string - // placeholderType?: string onChange: (newDuration: DurationRangeType) => void onError: (isError: boolean) => void } @@ -29,15 +28,15 @@ const defaultMaxDuration: DurationType = { month: null, day: null } -const DurationRange: React.FC = ({ +const DurationRange = ({ value, label, deidentified = false, - active = true, + disabled = false, unit = 'Âge', onChange, onError -}) => { +}: DurationRangeProps) => { const [minDuration, setMinDuration] = useState(convertStringToDuration(value[0]) || defaultMinDuration) const [maxDuration, setMaxDuration] = useState(convertStringToDuration(value[1]) || defaultMaxDuration) const [error, setError] = useState({ isError: false, errorMessage: '' }) @@ -47,23 +46,21 @@ const DurationRange: React.FC = ({ onError(false) if (!checkMinMaxValue(minDuration, maxDuration)) { setError({ isError: true, errorMessage: 'La date maximale doit être supérieure à la date minimale.' }) - onError(true) - onChange([convertDurationToString(minDuration), convertDurationToString(maxDuration)]) - } else { onChange([convertDurationToString(minDuration), convertDurationToString(maxDuration)]) - } + onError(true) + } else onChange([convertDurationToString(minDuration), convertDurationToString(maxDuration)]) }, [minDuration, maxDuration]) return ( {label && ( - {label} : + {label} )} = ({ /> void + onError?: (isError: boolean) => void +} + +const TextInput = ({ + value = '', + placeholder = '', + label, + disabled, + minLimit, + maxLimit, + onChange, + onError +}: TextInputProps) => { + const [input, setFiltersName] = useState(value) + const [isError, setIsError] = useState({ min: false, max: false }) + + useEffect(() => { + if (onError) { + onError(false) + if (isError.min || isError.max) onError(true) + } + }, [isError]) + + useEffect(() => { + let min = false + let max = false + if (maxLimit && input.length > maxLimit) max = true + else if (minLimit && input.length < minLimit) min = true + onChange(input) + setIsError({ min, max }) + }, [input]) + + return ( + <> + + {label && {label}} + setFiltersName(event.target.value)} + /> + + {isError.max && ( + + Le champ dépasse la limite de {maxLimit} caractères. + + )} + + ) +} + +export default TextInput diff --git a/src/components/ui/Inputs/index.tsx b/src/components/ui/Inputs/styles.ts similarity index 100% rename from src/components/ui/Inputs/index.tsx rename to src/components/ui/Inputs/styles.ts diff --git a/src/components/ui/RadioGroup/index.tsx b/src/components/ui/RadioGroup/index.tsx index 46b6d70d3..93dbeb72a 100644 --- a/src/components/ui/RadioGroup/index.tsx +++ b/src/components/ui/RadioGroup/index.tsx @@ -2,23 +2,23 @@ import React from 'react' import { FormControlLabel, Radio, RadioGroup as RadioGroupMui, SxProps } from '@mui/material' type RadioProps = { - selectedValue: T - items: { id: T; label: string; disabled?: boolean }[] - onchange: (value: T) => void + value: T + options: { id: T; label: string; disabled?: boolean }[] + onChange: (value: T) => void row?: boolean style?: SxProps } -const RadioGroup = ({ selectedValue, items, onchange, row, style }: RadioProps) => { +const RadioGroup = ({ value, options, onChange, row, style }: RadioProps) => { return ( - onchange(value as T)} row={row} sx={style}> - {items.map((item) => ( + onChange(value as T)} row={row} sx={style}> + {options.map((option) => ( } - label={item.label} - disabled={item.disabled} + label={option.label} + disabled={option.disabled} /> ))} diff --git a/src/hooks/filters/useSavedFilters.ts b/src/hooks/filters/useSavedFilters.ts index cc8807b50..e228930b7 100644 --- a/src/hooks/filters/useSavedFilters.ts +++ b/src/hooks/filters/useSavedFilters.ts @@ -59,7 +59,7 @@ export const useSavedFilters = (type: ResourceType) => { setSavedFiltersErrors({ isError: false }) await getSavedFilters() } catch { - setSavedFiltersErrors({ isError: true, errorMessage: 'Nom déjà existant.' }) + setSavedFiltersErrors({ isError: true, errorMessage: "Il y a eu une erreur lors de l'enregistrement du filtre. Vérifiez que le nom n'existe pas déjà." }) throw 'Nom déjà existant' } } diff --git a/src/mappers/filters.ts b/src/mappers/filters.ts index 7450cca95..cfcf1494f 100644 --- a/src/mappers/filters.ts +++ b/src/mappers/filters.ts @@ -144,7 +144,7 @@ const mapDocumentsFromRequestParams = async (parameters: URLSearchParams) => { const docTypesParams = parameters.get(DocumentsParamsKeys.DOC_TYPES) const docStatusesParams = parameters.get(DocumentsParamsKeys.DOC_STATUSES) let docTypes: SimpleCodeType[] = [] - let docStatuses: string[] = [] + let docStatuses: LabelObject[] = [] if (docTypesParams) { docTypes = decodeURIComponent(docTypesParams) ?.split(',') @@ -158,7 +158,10 @@ const mapDocumentsFromRequestParams = async (parameters: URLSearchParams) => { if (docStatusesParams) { docStatuses = decodeURIComponent(docStatusesParams) ?.split(',') - ?.map((e) => mapDocumentStatusesFromRequestParam(e.split('|')?.[1])) + ?.map((e) => ({ + id: mapDocumentStatusesFromRequestParam(e.split('|')?.[1]), + label: mapDocumentStatusesFromRequestParam(e.split('|')?.[1]) + })) } const onlyPdfAvailable = true const { nda, startDate, endDate, executiveUnits, encounterStatus } = await mapGenericFromRequestParams( @@ -356,7 +359,7 @@ const mapDocumentsToRequestParams = (filters: DocumentsFilters) => { if (docStatuses && docStatuses.length > 0) { requestParams.push( `${DocumentsParamsKeys.DOC_STATUSES}=${encodeURIComponent( - docStatuses.map((status) => `${docStatusCodeSystem}|${mapDocumentStatusesToRequestParam(status)}`).toString() + docStatuses.map((status) => `${docStatusCodeSystem}|${mapDocumentStatusesToRequestParam(status.id)}`).toString() )}` ) } diff --git a/src/services/aphp/callApi.ts b/src/services/aphp/callApi.ts index ded5b37ad..1a788f049 100644 --- a/src/services/aphp/callApi.ts +++ b/src/services/aphp/callApi.ts @@ -1141,6 +1141,7 @@ export const fetchAccessExpirations: ( return response } + export const fetchPerimeterAccesses = async (perimeter: string): Promise> => { const response = await apiBackend.get(`accesses/accesses/my-data-rights/?perimeters_ids=${perimeter}`) return response diff --git a/src/services/aphp/serviceCohorts.ts b/src/services/aphp/serviceCohorts.ts index 15cae5c17..741d6621a 100644 --- a/src/services/aphp/serviceCohorts.ts +++ b/src/services/aphp/serviceCohorts.ts @@ -957,7 +957,7 @@ const servicesCohorts: IServiceCohorts = { searchBy: searchBy, _sort: orderBy.orderBy, sortDirection: orderBy.orderDirection, - docStatuses: docStatuses, + docStatuses: docStatuses.map((obj) => obj.id), _elements: searchInput ? [] : undefined, _list: groupId ? [groupId] : [], _text: searchInput, diff --git a/src/services/aphp/serviceProjects.ts b/src/services/aphp/serviceProjects.ts index 2634ecae9..dc030bbe6 100644 --- a/src/services/aphp/serviceProjects.ts +++ b/src/services/aphp/serviceProjects.ts @@ -412,7 +412,7 @@ const servicesProjects: IServiceProjects = { let options: string[] = [] const { status, favorite, minPatients, maxPatients, startDate, endDate } = filters - const _status = status.map((stat) => stat.code) + const _status = status.map((stat) => stat.id) if (limit) options = [...options, `limit=${limit}`] if (offset) options = [...options, `offset=${offset}`] diff --git a/src/state/patient.ts b/src/state/patient.ts index 1cc209758..7c75de04a 100644 --- a/src/state/patient.ts +++ b/src/state/patient.ts @@ -526,7 +526,7 @@ const fetchDocuments = createAsyncThunk< patientId, searchInput, selectedDocTypes, - docStatuses, + docStatuses.map((obj) => obj.id), nda, onlyPdfAvailable, startDate, diff --git a/src/types/searchCriterias.ts b/src/types/searchCriterias.ts index 28189943e..8f9443d30 100644 --- a/src/types/searchCriterias.ts +++ b/src/types/searchCriterias.ts @@ -73,6 +73,25 @@ export enum VitalStatusLabel { ALL = 'Tous les patients' } +export const genderOptions = [ + { + id: GenderStatus.FEMALE, + label: GenderStatusLabel.FEMALE + }, + { + id: GenderStatus.MALE, + label: GenderStatusLabel.MALE + }, + { + id: GenderStatus.OTHER, + label: GenderStatusLabel.OTHER + }, + { + id: GenderStatus.UNKNOWN, + label: GenderStatusLabel.UNKNOWN + } +] + export enum VitalStatusOptions { birth = 'birth', age = 'age', @@ -92,6 +111,17 @@ export enum VitalStatus { DECEASED = 'DECEASED' } +export const vitalStatusesOptions = [ + { + id: VitalStatus.ALIVE, + label: VitalStatusLabel.ALIVE + }, + { + id: VitalStatus.DECEASED, + label: VitalStatusLabel.DECEASED + } +] + export enum Direction { ASC = 'asc', DESC = 'desc' @@ -271,7 +301,7 @@ export type GenericFilter = { encounterStatus: LabelObject[] } -export interface PatientsFilters { +export type PatientsFilters = { genders: GenderStatus[] birthdatesRanges: DurationRangeType vitalStatuses: VitalStatus[] @@ -314,11 +344,11 @@ export type MaternityFormFilters = { export type DocumentsFilters = GenericFilter & { ipp?: string docTypes: SimpleCodeType[] - docStatuses: string[] + docStatuses: LabelObject[] onlyPdfAvailable: boolean } export interface CohortsFilters { - status: ValueSet[] + status: LabelObject[] favorite: CohortsType minPatients: null | string maxPatients: null | string diff --git a/src/utils/filters.ts b/src/utils/filters.ts index af8418827..9b8b0553a 100644 --- a/src/utils/filters.ts +++ b/src/utils/filters.ts @@ -12,7 +12,7 @@ import { } from 'types/searchCriterias' import moment from 'moment' import { capitalizeFirstLetter } from './capitalize' -import { ScopeElement, SimpleCodeType, ValueSet } from 'types' +import { ScopeElement, SimpleCodeType } from 'types' import { getDurationRangeLabel } from './age' import { CohortsType, CohortsTypeLabel } from 'types/cohorts' import { Hierarchy } from 'types/hierarchy' @@ -134,7 +134,7 @@ export const getFilterLabel = (key: FilterKeys, value: FilterValue): string => { }` } if (key === FilterKeys.DOC_STATUSES) { - return `Documents : ${value}` + return `Documents : ${(value as LabelObject).label}` } if (key === FilterKeys.DOC_TYPES) { return (value as SimpleCodeType).label @@ -149,7 +149,7 @@ export const getFilterLabel = (key: FilterKeys, value: FilterValue): string => { return `Type de prescription : ${capitalizeFirstLetter((value as LabelObject)?.label as string)}` } if (key === FilterKeys.STATUS) { - return `Statut : ${(value as ValueSet)?.display}` + return `Statut : ${(value as LabelObject)?.label}` } if (key === FilterKeys.MIN_PATIENTS) { return `Au moins ${value} patients` diff --git a/src/views/MyCohorts/index.tsx b/src/views/MyCohorts/index.tsx index c57fcadaf..9389755c1 100644 --- a/src/views/MyCohorts/index.tsx +++ b/src/views/MyCohorts/index.tsx @@ -1,12 +1,9 @@ import React, { useEffect, useMemo, useRef, useState } from 'react' import { useAppDispatch, useAppSelector } from 'state' - import { Chip, CircularProgress, CssBaseline, Grid, Typography } from '@mui/material' - import useStyles from './styles' import { FilterList } from '@mui/icons-material' -import CohortStatusFilter from 'components/Filters/CohortStatusFilter' -import CohortsTypesFilter from 'components/Filters/CohortsTypeFilter' +import RadioGroupFilter from 'components/Filters/RadioGroupFilter' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import PatientsNbFilter from 'components/Filters/PatientsNbFilter' import DisplayDigits from 'components/ui/Display/DisplayDigits' @@ -14,7 +11,7 @@ import { BlockWrapper } from 'components/ui/Layout' import Searchbar from 'components/ui/Searchbar' import SearchInput from 'components/ui/Searchbar/SearchInput' import { LoadingStatus } from 'types' -import { CohortsType } from 'types/cohorts' +import { CohortsType, CohortsTypeLabel } from 'types/cohorts' import { FilterKeys, OrderBy } from 'types/searchCriterias' import { selectFiltersAsArray } from 'utils/filters' import { CanceledError } from 'axios' @@ -28,22 +25,28 @@ import useCohortList from 'hooks/useCohortList' import { Pagination } from 'components/ui/Pagination' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, handlePageError } from 'utils/paginationUtils' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const statusOptions = [ { - display: 'Terminé', - code: 'finished' + label: 'Terminé', + id: 'finished' }, { - display: 'En attente', - code: 'pending,started' + label: 'En attente', + id: 'pending,started' }, { - display: 'Erreur', - code: 'failed' + label: 'Erreur', + id: 'failed' } ] +const favoriteOptions = [ + { id: CohortsType.FAVORITE, label: CohortsTypeLabel.FAVORITE }, + { id: CohortsType.NOT_FAVORITE, label: CohortsTypeLabel.NOT_FAVORITE } +] + type MyCohortsProps = { favoriteUrl?: boolean } @@ -51,13 +54,10 @@ type MyCohortsProps = { const MyCohorts = ({ favoriteUrl = false }: MyCohortsProps) => { const [searchParams, setSearchParams] = useSearchParams() const getPageParam = searchParams.get('page') - const { classes, cx } = useStyles() const openDrawer = useAppSelector((state) => state.drawer) const cohortState = useAppSelector((state) => state.cohort) - const dispatch = useAppDispatch() - const cohortList = useCohortList() const [toggleModal, setToggleModal] = useState(false) const [page, setPage] = useState(getPageParam ? parseInt(getPageParam, 10) : 1) @@ -73,9 +73,10 @@ const MyCohorts = ({ favoriteUrl = false }: MyCohortsProps) => { { changeOrderBy, changeSearchInput, addFilters, removeFilter } ] = useSearchCriterias(initCohortsSearchCriterias) - const filtersAsArray = useMemo(() => { - return selectFiltersAsArray({ status, startDate, endDate, minPatients, maxPatients, favorite }) - }, [status, startDate, endDate, minPatients, maxPatients, favorite]) + const filtersAsArray = useMemo( + () => selectFiltersAsArray({ status, startDate, endDate, minPatients, maxPatients, favorite }), + [status, startDate, endDate, minPatients, maxPatients, favorite] + ) const controllerRef = useRef(new AbortController()) const isFirstRender = useRef(true) @@ -192,8 +193,18 @@ const MyCohorts = ({ favoriteUrl = false }: MyCohortsProps) => { onClose={() => setToggleModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - - + +