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 34a4947aa..0e1a16c9c 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' @@ -37,6 +34,7 @@ import { fetchAnabioCodes as fetchAnabioCodesApi } from 'services/aphp/serviceBiology' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' +import MultiSelectInput from 'components/Filters/MultiSelectInput' type BiologyListProps = { deidentified?: boolean @@ -82,6 +80,7 @@ const BiologyList = ({ deidentified }: BiologyListProps) => { }, { changeOrderBy, changeSearchInput, addFilters, removeFilter, addSearchCriterias } ] = useSearchCriterias(initBioSearchCriterias) + console.log("test filters", filters) const filtersAsArray = useMemo( () => selectFiltersAsArray({ @@ -317,8 +316,17 @@ const BiologyList = ({ deidentified }: BiologyListProps) => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - {!deidentified && } - {!deidentified && } + {!deidentified && ( + + )} + {!deidentified && ( + + )} @@ -327,10 +335,11 @@ const BiologyList = ({ deidentified }: BiologyListProps) => { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { {!deidentified && ( - )} {!deidentified && ( - )} @@ -479,11 +492,12 @@ const BiologyList = ({ deidentified }: BiologyListProps) => { /> - diff --git a/src/components/Dashboard/Documents/Documents.tsx b/src/components/Dashboard/Documents/Documents.tsx index 49bd8fc98..6ba5ad822 100644 --- a/src/components/Dashboard/Documents/Documents.tsx +++ b/src/components/Dashboard/Documents/Documents.tsx @@ -28,10 +28,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' @@ -39,13 +36,13 @@ 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 { Hierarchy } from 'types/hierarchy' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' import { CanceledError } from 'axios' import { DocumentReference } from 'fhir/r4' +import MultiSelectInput from 'components/Filters/MultiSelectInput' type DocumentsProps = { deidentified: boolean @@ -129,7 +126,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 { @@ -382,9 +382,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 && ( - )} - @@ -556,11 +576,12 @@ const Documents: React.FC = ({ deidentified }) => { /> - diff --git a/src/components/Dashboard/ExportModal/exportUtils.ts b/src/components/Dashboard/ExportModal/exportUtils.ts index 44bb55a55..f37035ddb 100644 --- a/src/components/Dashboard/ExportModal/exportUtils.ts +++ b/src/components/Dashboard/ExportModal/exportUtils.ts @@ -302,7 +302,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 289ec9748..53e2590f0 100644 --- a/src/components/Dashboard/FormsList/index.tsx +++ b/src/components/Dashboard/FormsList/index.tsx @@ -5,9 +5,7 @@ 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 { Hierarchy } from 'types/hierarchy' import { DTTB_ResultsType as ResultsType, LoadingStatus } from 'types' @@ -24,6 +22,8 @@ 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 TextInput from 'components/Filters/TextInput' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const FormsList = () => { const theme = useTheme() @@ -206,17 +206,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 cf9d350a8..c017a72d6 100644 --- a/src/components/Dashboard/ImagingList/index.tsx +++ b/src/components/Dashboard/ImagingList/index.tsx @@ -1,28 +1,20 @@ 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, 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 +23,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 { Hierarchy } from 'types/hierarchy' import { AppConfig } from 'config' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' +import MultiSelectInput from 'components/Filters/MultiSelectInput' type ImagingListProps = { deidentified?: boolean @@ -290,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 && ( - )} @@ -377,10 +384,11 @@ const MedicationList = ({ deidentified }: MedicationListProps) => { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { )} {!deidentified && ( - )} {!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/Dashboard/PMSIList/index.tsx b/src/components/Dashboard/PMSIList/index.tsx index 77777b9e6..269ecaf6b 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/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' @@ -41,11 +36,29 @@ import { mapToLabel, mapToSourceType } from 'mappers/pmsi' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' 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) @@ -369,23 +382,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 && ( + + )} - @@ -484,19 +510,23 @@ const PMSIList = ({ deidentified }: PMSIListProps) => { {!deidentified && ( - )} {!deidentified && ( - )} @@ -510,20 +540,23 @@ const PMSIList = ({ deidentified }: PMSIListProps) => { {selectedTab.id === ResourceType.CONDITION && ( - )} {selectedTab.id !== ResourceType.CLAIM && ( - )} @@ -546,11 +579,12 @@ const PMSIList = ({ deidentified }: PMSIListProps) => { /> - diff --git a/src/components/Dashboard/PatientList/PatientList.tsx b/src/components/Dashboard/PatientList/PatientList.tsx index e75183ea6..db5260a81 100644 --- a/src/components/Dashboard/PatientList/PatientList.tsx +++ b/src/components/Dashboard/PatientList/PatientList.tsx @@ -28,10 +28,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' @@ -41,8 +43,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' @@ -297,8 +298,13 @@ const PatientList = ({ total, deidentified }: PatientListProps) => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ genders, birthdatesRanges, vitalStatuses, ...newFilters })} > - - + + { )} - - [] - disabled?: boolean -} - -const AdministrationTypesFilter = ({ - name, - value, - allAdministrationTypes, - disabled = false -}: AdministrationTypesFilterProps) => { - 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/CheckboxsFilter/index.tsx b/src/components/Filters/CheckboxsFilter/index.tsx new file mode 100644 index 000000000..d24b19bf5 --- /dev/null +++ b/src/components/Filters/CheckboxsFilter/index.tsx @@ -0,0 +1,44 @@ +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 { LabelObject } from 'types/searchCriterias' +import { isChecked, toggleFilter } from 'utils/filters' + +type CheckboxsFilterProps = { + value: string[] + name: string + label?: string + disabled?: boolean + options: LabelObject[] +} + +const CheckboxsFilter = ({ name, value, label, options, disabled = false }: CheckboxsFilterProps) => { + 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/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 fa01bfb43..000000000 --- a/src/components/Filters/DiagnosticTypesFilter/index.tsx +++ /dev/null @@ -1,51 +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 { Hierarchy } from 'types/hierarchy' -import { LabelObject } from 'types/searchCriterias' -import { capitalizeFirstLetter } from 'utils/capitalize' - -type DiagnosticTypesFilterProps = { - value: LabelObject[] - name: string - allDiagnosticTypesList: Hierarchy[] - 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/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/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..5b8733be6 --- /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' +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 SelectInput = ({ 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 SelectInput 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/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/PatientBiology.tsx b/src/components/Patient/PatientBiology/PatientBiology.tsx index a42bd3348..e8b973a88 100644 --- a/src/components/Patient/PatientBiology/PatientBiology.tsx +++ b/src/components/Patient/PatientBiology/PatientBiology.tsx @@ -27,7 +27,6 @@ import AnabioFilter from 'components/Filters/AnabioFilter' import DatesRangeFilter from 'components/Filters/DatesRangeFilter' import ExecutiveUnitsFilter from 'components/Filters/ExecutiveUnitsFilter' import LoincFilter from 'components/Filters/LoincFilter' -import NdaFilter from 'components/Filters/NdaFilter' import { Save, SavedSearch } from '@mui/icons-material' import { ResourceType } from 'types/requestCriterias' import { useSavedFilters } from 'hooks/filters/useSavedFilters' @@ -38,11 +37,11 @@ import { fetchAnabioCodes as fetchAnabioCodesApi } from 'services/aphp/serviceBiology' import services from 'services/aphp' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { Hierarchy } from 'types/hierarchy' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const PatientBiology = () => { const { classes } = useStyles() @@ -267,7 +266,9 @@ const PatientBiology = () => { onClose={() => setToggleFilterByModal(false)} onSubmit={(newFilters) => addFilters({ ...filters, ...newFilters })} > - {!searchResults.deidentified && } + {!searchResults.deidentified && ( + + )} @@ -276,10 +277,11 @@ const PatientBiology = () => { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { />
    - @@ -406,11 +410,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/PatientDocs.tsx b/src/components/Patient/PatientDocs/PatientDocs.tsx index 93b59f682..9e0ff5bc5 100644 --- a/src/components/Patient/PatientDocs/PatientDocs.tsx +++ b/src/components/Patient/PatientDocs/PatientDocs.tsx @@ -38,19 +38,17 @@ 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 services from 'services/aphp' import { SourceType } from 'types/scope' import { Hierarchy } from 'types/hierarchy' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const PatientDocs = () => { const dispatch = useAppDispatch() @@ -118,7 +116,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) @@ -334,8 +335,15 @@ const PatientDocs = () => { addFilters({ ...filters, ...newFilters }) }} > - {!searchResults.deidentified && } - + {!searchResults.deidentified && ( + + )} + { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { {!searchResults.deidentified && ( - )} - @@ -487,11 +499,12 @@ const PatientDocs = () => { 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 8b5a9c71d..6a60d9676 100644 --- a/src/components/Patient/PatientForms/MaternityForms/index.tsx +++ b/src/components/Patient/PatientForms/MaternityForms/index.tsx @@ -20,11 +20,11 @@ import { LoadingStatus } from 'types' import { FilterKeys } from 'types/searchCriterias' import Timeline from './Timeline' import services from 'services/aphp' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { Hierarchy } from 'types/hierarchy' import { useSearchParams } from 'react-router-dom' import { getCleanGroupId } from 'utils/paginationUtils' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const MaternityForm = () => { const [toggleModal, setToggleModal] = useState(false) @@ -132,10 +132,11 @@ const MaternityForm = () => { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - )} diff --git a/src/components/Patient/PatientImaging/PatientImaging.tsx b/src/components/Patient/PatientImaging/PatientImaging.tsx index a0895cbc4..e5884c5e0 100644 --- a/src/components/Patient/PatientImaging/PatientImaging.tsx +++ b/src/components/Patient/PatientImaging/PatientImaging.tsx @@ -14,8 +14,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' @@ -30,12 +28,12 @@ import TextInput from 'components/Filters/TextInput' import List from 'components/ui/List' import services from 'services/aphp' import { BlockWrapper } from 'components/ui/Layout' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { Hierarchy } from 'types/hierarchy' import { AppConfig } from 'config' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' +import MultiSelectInput from 'components/Filters/MultiSelectInput' const PatientImaging = () => { const dispatch = useAppDispatch() @@ -254,18 +252,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/PatientMedication.tsx b/src/components/Patient/PatientMedication/PatientMedication.tsx index 06c478ee6..c693f9d48 100644 --- a/src/components/Patient/PatientMedication/PatientMedication.tsx +++ b/src/components/Patient/PatientMedication/PatientMedication.tsx @@ -1,16 +1,10 @@ import React, { useEffect, useMemo, useRef, useState } from 'react' - import Grid from '@mui/material/Grid' - import FilterList from 'assets/icones/filter.svg?react' - import DataTableMedication from 'components/DataTable/DataTableMedication' - import { LoadingStatus, MedicationTab, TabType } from 'types' - import { useAppSelector, useAppDispatch } from 'state' import { fetchMedication } from 'state/patient' - import useStyles from './styles' import { cancelPendingRequest } from 'utils/abortController' import { CanceledError } from 'axios' @@ -24,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' @@ -37,7 +29,6 @@ import TextInput from 'components/Filters/TextInput' import List from 'components/ui/List' import { mapToAttribute, mapToLabel } from 'mappers/pmsi' import services from 'services/aphp' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { SourceType } from 'types/scope' import { Hierarchy } from 'types/hierarchy' import { useSearchParams } from 'react-router-dom' @@ -343,19 +334,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 && ( - )} @@ -364,10 +359,11 @@ const PatientMedication = () => { value={executiveUnits} name={FilterKeys.EXECUTIVE_UNITS} /> - { )} {!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/PatientPMSI.tsx b/src/components/Patient/PatientPMSI/PatientPMSI.tsx index ac3489b22..cfbd66286 100644 --- a/src/components/Patient/PatientPMSI/PatientPMSI.tsx +++ b/src/components/Patient/PatientPMSI/PatientPMSI.tsx @@ -1,11 +1,8 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' - import { CircularProgress, Grid, Tooltip } from '@mui/material' import Chip from 'components/ui/Chip' import FilterList from 'assets/icones/filter.svg?react' - import DataTablePmsi from 'components/DataTable/DataTablePmsi' - import { useAppSelector, useAppDispatch } from 'state' import { fetchPmsi } from 'state/patient' import { CohortPMSI, LoadingStatus, PmsiTab } from 'types' @@ -26,10 +23,7 @@ import useSearchCriterias, { initPmsiSearchCriterias } from 'reducers/searchCrit import services from 'services/aphp' 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' @@ -37,12 +31,29 @@ import TextInput from 'components/Filters/TextInput' import { mapToAttribute, mapToLabel, mapToSourceType } from 'mappers/pmsi' import List from 'components/ui/List' import { fetchClaimCodes, fetchConditionCodes, fetchProcedureCodes } from 'services/aphp/servicePmsi' -import EncounterStatusFilter from 'components/Filters/EncounterStatusFilter' import { AlertWrapper } from 'components/ui/Alert' import { Hierarchy } from 'types/hierarchy' import { useSearchParams } from 'react-router-dom' import { checkIfPageAvailable, cleanSearchParams, handlePageError } from 'utils/paginationUtils' import { getPMSITab } from 'utils/tabsUtils' +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 @@ -347,22 +358,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 && ( + + )} - @@ -450,10 +467,12 @@ const PatientPMSI = () => { {!searchResults.deidentified && ( - )} @@ -467,20 +486,23 @@ const PatientPMSI = () => { {selectedTab.id === ResourceType.CONDITION && ( - )} {selectedTab.id !== ResourceType.CLAIM && ( - )} @@ -503,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/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/useForm.ts b/src/hooks/useForm.ts new file mode 100644 index 000000000..d66722d6b --- /dev/null +++ b/src/hooks/useForm.ts @@ -0,0 +1,22 @@ +import { useState } from 'react' +import { T } from 'vitest/dist/chunks/environment.C5eAp3K6' + +type InputName = string + +type Inputs = { + [key in InputName]: T +} + +export const useForm = (values: Inputs) => { + const [inputs, setInputs] = useState(values) + + const changeInput = (name: string, value: T) => { + const newInputs = { ...inputs } + newInputs[name] = value + setInputs(newInputs) + } + + return { + changeInput + } +} diff --git a/src/mappers/filters.ts b/src/mappers/filters.ts index 291cf546e..896847eba 100644 --- a/src/mappers/filters.ts +++ b/src/mappers/filters.ts @@ -121,7 +121,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(',') @@ -135,7 +135,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( @@ -372,7 +375,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/serviceCohorts.ts b/src/services/aphp/serviceCohorts.ts index 0c3ba5906..33a9f4996 100644 --- a/src/services/aphp/serviceCohorts.ts +++ b/src/services/aphp/serviceCohorts.ts @@ -956,7 +956,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 9efbf64f5..11347be94 100644 --- a/src/state/patient.ts +++ b/src/state/patient.ts @@ -535,7 +535,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 4973aa40c..36e210eb8 100644 --- a/src/types/searchCriterias.ts +++ b/src/types/searchCriterias.ts @@ -72,6 +72,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', @@ -91,6 +110,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' @@ -313,11 +343,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 f12c027ff..78c68c129 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' @@ -135,7 +135,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 @@ -156,7 +156,7 @@ export const getFilterLabel = (key: FilterKeys, value: FilterValue): string => { return `Code LOINC : ${(value as LabelObject).label}` } 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 })} > - - + +