Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
pl-buiquang committed Sep 27, 2024
1 parent 42e77fb commit 362e873
Show file tree
Hide file tree
Showing 26 changed files with 2,121 additions and 142 deletions.
21 changes: 15 additions & 6 deletions src/components/CreationCohort/DataList_Criteria.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@ import DocumentsForm from './DiagramView/components/LogicalOperator/components/C
import EncounterForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/EncounterForm'
import CCAMForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/CCAM'
import Cim10Form from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/Cim10Form'
import GhmForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/GHM'
import MedicationForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/MedicationForm'
import BiologyForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/BiologyForm'
import DemographicForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/DemographicForm'
import ImagingForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/ImagingForm'
import PregnantForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/PregnantForm'
import HospitForm from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/HospitForm'

import services from 'services/aphp'

import { CriteriaType, CriteriaTypeLabels } from 'types/requestCriterias'
import { getConfig } from 'config'
import GHMForm2, {
form as ghmForm
} from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/GHM/GHMForm2'
import HospitForm2, {
form as hospitForm
} from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/HospitForm/HospitForm2'
import ImagingForm2, {
form as imagingForm
} from './DiagramView/components/LogicalOperator/components/CriteriaRightPanel/ImagingForm/ImagingForm2'

const criteriaList: () => CriteriaItemType[] = () => {
const ODD_QUESTIONNAIRE = getConfig().features.questionnaires.enabled
Expand Down Expand Up @@ -115,7 +121,8 @@ const criteriaList: () => CriteriaItemType[] = () => {
title: CriteriaTypeLabels.CLAIM,
color: '#0063AF',
fontWeight: 'normal',
components: GhmForm,
formDefinition: ghmForm(),
components: GHMForm2,
fetch: {
ghmData: services.cohortCreation.fetchGhmData,
encounterStatus: services.cohortCreation.fetchEncounterStatus
Expand Down Expand Up @@ -204,7 +211,8 @@ const criteriaList: () => CriteriaItemType[] = () => {
color: ODD_QUESTIONNAIRE ? '#0063AF' : '#808080',
fontWeight: 'normal',
disabled: !ODD_QUESTIONNAIRE,
components: HospitForm,
formDefinition: hospitForm(),
components: HospitForm2,
fetch: {
inUteroTransfer: services.cohortCreation.fetchInUteroTransfer,
pregnancyMonitoring: services.cohortCreation.fetchPregnancyMonitoring,
Expand Down Expand Up @@ -247,7 +255,8 @@ const criteriaList: () => CriteriaItemType[] = () => {
title: CriteriaTypeLabels.IMAGING,
color: ODD_IMAGING ? '#0063AF' : '#808080',
fontWeight: 'bold',
components: ImagingForm,
formDefinition: imagingForm(),
components: ImagingForm2,
disabled: !ODD_IMAGING,
fetch: {
modalities: services.cohortCreation.fetchModalities,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { FormLabel, Tooltip } from '@mui/material'
import React, { PropsWithChildren } from 'react'
import {
CriteriaDataType,
CriteriaFormItemView,
CriteriaFormItemViewProps,
CriteriaItem,
CriteriaItemType,
CriteriaSection,
DataTypeMapping
} from '../types'
import useStyles from '../style'
import { BlockWrapper } from 'components/ui/Layout'
import Collapse from 'components/ui/Collapse'
import { CriteriaLabel } from 'components/ui/CriteriaLabel'
import InfoIcon from '@mui/icons-material/Info'
import { isFunction, isString } from 'lodash'

type CriteriaItemRuntimeProps<T extends CriteriaDataType> = {
setError: (error?: string) => void
updateData: (data: T) => void
data: T
getValueSetOptions: CriteriaFormItemViewProps<never>['getValueSetOptions']
searchCode: CriteriaFormItemViewProps<never>['searchCode']
viewRenderers: { [key in CriteriaItemType]: CriteriaFormItemView<key> }
}

type CritieraItemProps<T extends CriteriaDataType, U extends CriteriaItem<T>> = CriteriaItemRuntimeProps<T> & U

export const CFLabel = (props: { label: string; tooltip?: string; altStyle?: boolean }) => {
const { label, tooltip, altStyle } = props
if (altStyle) {
return (
<FormLabel
style={{ padding: '0 0 1em', fontWeight: 600, fontSize: 12, display: 'flex', alignItems: 'center' }}
component="legend"
>
Fin de prise en charge
{tooltip && (
<Tooltip title={tooltip}>
<InfoIcon fontSize="small" color="primary" style={{ marginLeft: 4 }} />
</Tooltip>
)}
</FormLabel>
)
}
return label
}

export const CFItem = <T extends CriteriaDataType, U extends CriteriaItem<T>>(props: CritieraItemProps<T, U>) => {
const { valueKey, updateData, data, setError, getValueSetOptions, searchCode, viewRenderers } = props
const View = viewRenderers[props.type] as CriteriaFormItemView<U['type']>
const fieldValue = data[valueKey] as DataTypeMapping[U['type']]['dataType']
const condition = props.condition
if (condition && ((isFunction(condition) && !condition(data)) || (isString(condition) && !eval(condition)))) {
return null
}
return (
<View
value={fieldValue}
definition={props}
updateData={(value) => updateData({ ...data, [valueKey]: value })}
getValueSetOptions={getValueSetOptions}
searchCode={searchCode}
setError={setError}
/>
)
}

export const CFSection = <T extends CriteriaDataType>(
props: PropsWithChildren<Omit<CriteriaSection<T>, 'items'> & { collapsed?: boolean }>
) => {
const { classes } = useStyles()
return props.title ? (
<BlockWrapper className={classes.inputItem}>
<Collapse title={props.title} value={!props.defaulCollapsed || !props.collapsed} margin="0">
{props.children}
</Collapse>
</BlockWrapper>
) : (
<>{props.children}</>
)
}

export const CFItemWrapper = (props: PropsWithChildren<{ label?: string; info?: string }>) => {
const { classes } = useStyles()
return (
<BlockWrapper className={classes.inputItem}>
{props.label ? (
<CriteriaLabel label={props.label} style={{ padding: 0, marginTop: '1em' }}>
{props.info && (
<Tooltip title={props.info}>
<InfoIcon fontSize="small" color="primary" style={{ marginLeft: 4 }} />
</Tooltip>
)}
</CriteriaLabel>
) : (
''
)}
{props.children}
</BlockWrapper>
)
}

export default { CFItemWrapper, CFSection, CFLabel, CFItem }
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useEffect, useState } from 'react'
import CriteriaLayout from 'components/ui/CriteriaLayout'
import {
CriteriaData,
CriteriaForm as CriteriaFormDefinition,
CriteriaDataType,
CriteriaFormItemViewProps,
NumberAndComparatorDataType,
NewDurationRangeType
} from './types'
import { CFItem, CFItemWrapper, CFSection } from './components'
import FORM_ITEM_RENDERER from './renderers'
import { useAppSelector } from 'state'
import { LabelObject } from 'types/searchCriterias'

export type CriteriaFormRuntimeProps<T extends CriteriaDataType> = {
goBack: () => void
data?: CriteriaData<T>
updateData: (data: CriteriaData<T>) => void
searchCode: CriteriaFormItemViewProps<never>['searchCode']
}

type CriteriaFormProps<T extends CriteriaDataType> = CriteriaFormDefinition<T> & CriteriaFormRuntimeProps<T>

export default function CriteriaForm<T extends CriteriaDataType>(props: CriteriaFormProps<T>) {
const [criteriaData, setCriteriaData] = useState<CriteriaData<T>>(props.data || props.initialData)
const valueSets = useAppSelector((state) => state.valueSets)
const { goBack, updateData, label, warningAlert, itemSections, errorMessages, onDataChange } = props
const isEdition = !!props.data
const [error, setError] = useState<string>()

useEffect(() => {
onDataChange?.(criteriaData)
}, [criteriaData, onDataChange])

console.log('rendering form')

return (
<CriteriaLayout
criteriaLabel={`${label}`}
title={criteriaData.title}
onChangeTitle={(title) => setCriteriaData({ ...criteriaData, title })}
isEdition={isEdition}
goBack={goBack}
onSubmit={() => updateData(criteriaData)}
disabled={error !== undefined}
isInclusive={criteriaData.isInclusive}
onChangeIsInclusive={(isInclusive) => setCriteriaData({ ...criteriaData, isInclusive: isInclusive })}
infoAlert={['Tous les éléments des champs multiples sont liés par une contrainte OU']}
warningAlert={warningAlert}
errorAlert={error ? [errorMessages[error]] : undefined}
>
{itemSections.map((section, index) => (
<CFSection
key={index}
title={section.title}
defaulCollapsed={section.defaulCollapsed}
collapsed={section.items.every((item) => {
const value = criteriaData[item.valueKey]
let isNull = !value || (Array.isArray(value) && value.length === 0)
if (item.type === 'numberAndComparator') {
isNull = isNull || !(value as NumberAndComparatorDataType).value
} else if (item.type === 'duration') {
const duration = value as NewDurationRangeType
isNull = isNull || (duration.start === null && duration.end === null)
}
if (!isNull) console.log(isNull, item.valueKey, value)

return isNull
})}
>
{section.items.map((item, index) => (
<CFItemWrapper key={index} label={item.extraLabel} info={item.extraInfo}>
<CFItem
{...{
viewRenderers: FORM_ITEM_RENDERER,
...item,
data: criteriaData,
getValueSetOptions: (valueSetId) => {
return (valueSets.entities[valueSetId]?.options || []) as LabelObject[]
},
searchCode: props.searchCode,
updateData: (newData: T) => {
setCriteriaData({ ...criteriaData, ...newData })
},
setError
}}
/>
</CFItemWrapper>
))}
</CFSection>
))}
</CriteriaLayout>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react'
import { CriteriaDrawerComponentProps, CriteriaItemDataCache } from 'types'
import { CriteriaData, CriteriaDataType } from './types'
import CriteriaForm from '.'
import { CriteriaForm as CriteriaFormDefinition } from './types'
import { SelectedCriteriaType } from 'types/requestCriterias'
import { fetchValueSet } from 'services/aphp/callApi'

export type LegacyAdapterProps<T extends CriteriaDataType, U extends SelectedCriteriaType> = {
form: () => CriteriaFormDefinition<T>
adapter: {
mapFromLegacyDataType: (legacyData: U, criteriaData: CriteriaItemDataCache) => CriteriaData<T>
mapToLegacyDataType: (data: CriteriaData<T>) => Omit<U, 'id'>
}
}

/**
* Enable the use of the new CriteriaForm component with the legacy data format
* @param props contains the form definition and the adapter to convert the legacy data to the new data format
* @returns the legacy Drawer component with the new CriteriaForm component
*/
export default function withLegacyAdapter<T extends CriteriaDataType, U extends SelectedCriteriaType>(
props: LegacyAdapterProps<T, U>
) {
return (legacyProps: CriteriaDrawerComponentProps) => {
const { criteriaData, goBack, selectedCriteria, onChangeSelectedCriteria } = legacyProps
const formDefinition = props.form()
const runtimeProps = {
data: selectedCriteria
? props.adapter.mapFromLegacyDataType(selectedCriteria as U, criteriaData)
: formDefinition.initialData,
updateData: (data: CriteriaData<T>) => onChangeSelectedCriteria(props.adapter.mapToLegacyDataType(data) as U),
goBack
}
return (
<CriteriaForm
{...formDefinition}
{...runtimeProps}
searchCode={(code: string, codeSystemUrl: string, abortSignal: AbortSignal) =>
fetchValueSet(
codeSystemUrl,
{ valueSetTitle: 'Toute la hiérarchie', search: code, noStar: false },
abortSignal
)
}
/>
)
}
}
Loading

0 comments on commit 362e873

Please sign in to comment.