diff --git a/src/adapters/encounter-diagnosis-adapter.ts b/src/adapters/encounter-diagnosis-adapter.ts new file mode 100644 index 000000000..8e3441c87 --- /dev/null +++ b/src/adapters/encounter-diagnosis-adapter.ts @@ -0,0 +1,73 @@ +import { type OpenmrsResource } from '@openmrs/esm-framework'; +import { type FormFieldValueAdapter, type FormProcessorContextProps } from '..'; +import { type FormContextProps } from '../provider/form-provider'; +import { type FormField } from '../types'; +import { clearSubmission, gracefullySetSubmission } from '../utils/common-utils'; + +export let assignedEncounterDiagnosisIds: string[] = []; + +export const EncounterDiagnosisAdapter: FormFieldValueAdapter = { + transformFieldValue: function (field: FormField, value: any, context: FormContextProps) { + if (context.sessionMode == 'edit' && field.meta?.previousValue?.uuid) { + return editDiagnosis(value, field, context.currentProvider.uuid); + } + const newValue = constructNewDiagnosis(value, field, context.currentProvider.uuid); + gracefullySetSubmission(field, newValue, null); + return newValue; + }, + getInitialValue: function ( + field: FormField, + sourceObject: OpenmrsResource, + context: FormProcessorContextProps, + ): Promise { + // if (context.encounter?.diagnoses?.length > 0) { + // assignedEncounterDiagnosisIds.push(encounter.diagnoses[0].diagnosis.coded.uuid); + // return encounter.diagnoses[0].diagnosis.coded.uuid; + // } else { + // return; + // } + return; + }, + getPreviousValue: function ( + field: FormField, + sourceObject: OpenmrsResource, + context: FormProcessorContextProps, + ): Promise { + return null; + }, + getDisplayValue: (field: FormField, value: any) => { + field.questionOptions; + return field.questionOptions.answers?.find((option) => option.concept == value)?.label || value; + }, + tearDown: function (): void { + assignedEncounterDiagnosisIds = []; + }, +}; + +const constructNewDiagnosis = (value: any, field: FormField, patientUuid: string) => { + if (!value) { + return null; + } + return { + patient: patientUuid, + condition: null, + diagnosis: { + coded: value, + }, + certainty: 'CONFIRMED', + rank: field.questionOptions.rank, // rank 1 denotes a diagnosis is primary, else secondary + }; +}; + +function editDiagnosis(newEncounterDiagnosis: any, field: FormField, EncounterDiagnosiser: string) { + if (newEncounterDiagnosis === field.meta.previousValue?.concept?.uuid) { + clearSubmission(field); + return null; + } + const voided = { + uuid: field.meta.previousValue?.uuid, + voided: true, + }; + gracefullySetSubmission(field, constructNewDiagnosis(newEncounterDiagnosis, field, null), voided); + return field.meta.submission.newValue || null; +} diff --git a/src/components/repeat/repeat.component.tsx b/src/components/repeat/repeat.component.tsx index 28aaba4ae..0450038d0 100644 --- a/src/components/repeat/repeat.component.tsx +++ b/src/components/repeat/repeat.component.tsx @@ -16,6 +16,7 @@ import { useFormFactory } from '../../provider/form-factory-provider'; const renderingByTypeMap: Record = { obsGroup: 'group', testOrder: 'select', + diagnosis: 'ui-select-extended', }; const Repeat: React.FC = ({ field }) => { diff --git a/src/constants.ts b/src/constants.ts index 567569286..0a967e7e3 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -5,6 +5,7 @@ export const encounterRepresentation = 'custom:(uuid,encounterDatetime,encounterType:(uuid,name,description),location:(uuid,name),' + 'patient:(uuid,display),encounterProviders:(uuid,provider:(uuid,name),encounterRole:(uuid,name)),' + 'orders:(uuid,display,concept:(uuid,display),voided),' + + 'diagnoses:(uuid,certainty,condition,display,rank,voided,diagnosis:(coded:(uuid,display))),' + 'obs:(uuid,obsDatetime,comment,voided,groupMembers,formFieldNamespace,formFieldPath,concept:(uuid,name:(uuid,name)),value:(uuid,name:(uuid,name),' + 'names:(uuid,conceptNameType,name))))'; export const FormsStore = 'forms-engine-store'; diff --git a/src/processors/encounter/encounter-processor-helper.ts b/src/processors/encounter/encounter-processor-helper.ts index 852187109..35a4da525 100644 --- a/src/processors/encounter/encounter-processor-helper.ts +++ b/src/processors/encounter/encounter-processor-helper.ts @@ -16,6 +16,7 @@ import { ConceptTrue } from '../../constants'; import { DefaultValueValidator } from '../../validators/default-value-validator'; import { cloneRepeatField } from '../../components/repeat/helpers'; import { assignedOrderIds } from '../../adapters/orders-adapter'; +import { assignedEncounterDiagnosisIds } from '../../adapters/encounter-diagnosis-adapter'; export function prepareEncounter( context: FormContextProps, @@ -300,6 +301,26 @@ export async function hydrateRepeatField( }), ); } + //handle diagnoses + const unMappedDiagnosis = encounter.diagnoses.filter((diagnosis) => { + const availableOrderables = field.questionOptions.answers?.map((answer) => answer.concept) || []; + return availableOrderables.includes(diagnosis?.uuid) && !assignedEncounterDiagnosisIds.includes(diagnosis.uuid); + }); + if (field.type === 'diagnosis') { + return Promise.all( + unMappedDiagnosis + .filter((diagnosis) => !diagnosis.voided) + .map(async (diagnosis) => { + const clone = cloneRepeatField(field, diagnosis, counter++); + initialValues[clone.id] = await formFieldAdapters[field.type].getInitialValue( + clone, + { diagnosiss: [diagnosis] } as any, + context, + ); + return clone; + }), + ); + } // handle obs groups return Promise.all( unMappedGroups.map(async (group) => { diff --git a/src/registry/inbuilt-components/inbuiltFieldValueAdapters.ts b/src/registry/inbuilt-components/inbuiltFieldValueAdapters.ts index 9a4c3d850..2a5632bf7 100644 --- a/src/registry/inbuilt-components/inbuiltFieldValueAdapters.ts +++ b/src/registry/inbuilt-components/inbuiltFieldValueAdapters.ts @@ -10,6 +10,7 @@ import { ObsCommentAdapter } from '../../adapters/obs-comment-adapter'; import { OrdersAdapter } from '../../adapters/orders-adapter'; import { PatientIdentifierAdapter } from '../../adapters/patient-identifier-adapter'; import { ProgramStateAdapter } from '../../adapters/program-state-adapter'; +import { EncounterDiagnosisAdapter } from '../../adapters/encounter-diagnosis-adapter'; import { type FormFieldValueAdapter } from '../../types'; export const inbuiltFieldValueAdapters: RegistryItem[] = [ @@ -61,4 +62,8 @@ export const inbuiltFieldValueAdapters: RegistryItem[] = type: 'patientIdentifier', component: PatientIdentifierAdapter, }, + { + type: 'diagnosis', + component: EncounterDiagnosisAdapter, + }, ]; diff --git a/src/transformers/default-schema-transformer.ts b/src/transformers/default-schema-transformer.ts index 40447a5fe..785dea821 100644 --- a/src/transformers/default-schema-transformer.ts +++ b/src/transformers/default-schema-transformer.ts @@ -131,6 +131,9 @@ function transformByType(question: FormField) { ? 'date' : question.questionOptions.rendering; break; + case 'diagnosis': + handleDiagnosesDataSource(question); + break; } } @@ -237,3 +240,12 @@ function handleQuestionsWithObsComments(sectionQuestions: Array): Arr return augmentedQuestions; } + +function handleDiagnosesDataSource(question: FormField) { + if ('dataSource' in question.questionOptions && question.questionOptions['dataSource'] === 'diagnoses') { + question.questionOptions.datasource = { + name: 'problem_datasource', + }; + delete question.questionOptions['dataSource']; + } +} diff --git a/src/types/domain.ts b/src/types/domain.ts index 010e349b6..f833d7dbe 100644 --- a/src/types/domain.ts +++ b/src/types/domain.ts @@ -12,6 +12,7 @@ export interface OpenmrsEncounter { visit?: OpenmrsResource | string; encounterProviders?: Array>; form?: OpenmrsFormResource; + diagnoses?: Array; } export interface OpenmrsObs extends OpenmrsResource { @@ -127,3 +128,28 @@ export interface PatientIdentifier { location?: string; preferred?: boolean; } + +export interface DiagnosisPayload { + encounter: string; + patient: string; + condition: null; + diagnosis: { + coded: string; + }; + certainty: string; + rank: number; +} + +export interface Diagnosis { + patient: string; + diagnosis: { + coded: { + uuid: string; + }; + }; + certainty: string; + rank: number; + display: string; + voided: boolean; + uuid: string; +} diff --git a/src/types/schema.ts b/src/types/schema.ts index 56f453390..4d473bc27 100644 --- a/src/types/schema.ts +++ b/src/types/schema.ts @@ -174,6 +174,7 @@ export interface FormQuestionOptions { comment?: string; orientation?: 'vertical' | 'horizontal'; shownCommentOptions?: { validators?: Array>; hide?: { hideWhenExpression: string } }; + rank?: number; } export interface QuestionAnswerOption {