Skip to content

Commit

Permalink
Introduce Encounter Provider Control
Browse files Browse the repository at this point in the history
  • Loading branch information
kajambiya committed Mar 12, 2024
1 parent 8c5cf5b commit a22b6d6
Show file tree
Hide file tree
Showing 15 changed files with 105 additions and 13 deletions.
6 changes: 6 additions & 0 deletions src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ export function getAllLocations(): Observable<{ uuid: string; display: string }[
);
}

export function getEncounterProviders(): Observable<{ uuid: string; display: string }[]> {
return openmrsObservableFetch(`/ws/rest/v1/provider?v=custom:(uuid,display)`).pipe(
map(({ data }) => data['results']),
);
}

export async function getPreviousEncounter(patientUuid: string, encounterType: string) {
const query = `patient=${patientUuid}&_sort=-_lastUpdated&_count=1&type=${encounterType}`;
let response = await openmrsFetch(`/ws/fhir2/R4/Encounter?${query}`);
Expand Down
11 changes: 8 additions & 3 deletions src/components/encounter/ohri-encounter-form.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export const OHRIEncounterForm: React.FC<OHRIEncounterFormProps> = ({
const [fields, setFields] = useState<Array<OHRIFormField>>([]);
const [encounterLocation, setEncounterLocation] = useState(null);
const [encounterDate, setEncounterDate] = useState(formSessionDate);
const [encounterProvider, setEncounterProvider] = useState(provider);
const { encounter, isLoading: isLoadingEncounter } = useEncounter(formJson);
const [previousEncounter, setPreviousEncounter] = useState<OpenmrsEncounter>(null);
const [isLoadingPreviousEncounter, setIsLoadingPreviousEncounter] = useState(true);
Expand All @@ -92,6 +93,7 @@ export const OHRIEncounterForm: React.FC<OHRIEncounterFormProps> = ({
const [invalidFields, setInvalidFields] = useState([]);
const [initValues, setInitValues] = useState({});
const [obsGroupCounter, setObsGroupCounter] = useState<Array<RepeatObsGroupCounter>>([]);

const layoutType = useLayoutType();

const encounterContext = useMemo(
Expand All @@ -102,9 +104,11 @@ export const OHRIEncounterForm: React.FC<OHRIEncounterFormProps> = ({
location: location,
sessionMode: sessionMode || (form?.encounter ? 'edit' : 'enter'),
encounterDate: formSessionDate,
encounterProvider: provider,
form: form,
visit: visit,
setEncounterDate,
setEncounterProvider,
initValues: initValues,
obsGroupCounter: obsGroupCounter,
setObsGroupCounter: setObsGroupCounter,
Expand Down Expand Up @@ -478,13 +482,13 @@ export const OHRIEncounterForm: React.FC<OHRIEncounterFormProps> = ({
// update encounter providers
const hasCurrentProvider =
encounterForSubmission['encounterProviders'].findIndex(
(encProvider) => encProvider.provider.uuid == provider,
(encProvider) => encProvider.provider.uuid == encounterProvider,
) !== -1;
if (!hasCurrentProvider) {
encounterForSubmission['encounterProviders'] = [
...encounterForSubmission.encounterProviders,
{
provider: provider,
provider: encounterProvider,
encounterRole: encounterRole?.uuid,
},
];
Expand All @@ -504,7 +508,7 @@ export const OHRIEncounterForm: React.FC<OHRIEncounterFormProps> = ({
encounterType: formJson.encounterType,
encounterProviders: [
{
provider: provider,
provider: encounterProvider,
encounterRole: encounterRole?.uuid,
},
],
Expand Down Expand Up @@ -709,6 +713,7 @@ export const OHRIEncounterForm: React.FC<OHRIEncounterFormProps> = ({
value={{
values,
setFieldValue,
setEncounterProvider: setEncounterProvider,
setEncounterLocation: setEncounterLocation,
setObsGroupsToVoid: setObsGroupsToVoid,
obsGroupsToVoid: obsGroupsToVoid,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ const UISelectExtended: React.FC<OHRIFormFieldProps> = ({ question, handler, onC
}, [encounterContext.sessionMode, question.readonly, question.inlineRendering, layoutType, workspaceLayout]);

useEffect(() => {
const datasourceName = question.questionOptions?.datasource?.name;
let datasourceName = question.questionOptions?.datasource?.name;
if (question.type === 'encounterProvider') {
datasourceName = question.type;
}
setConfig(
datasourceName
? question.questionOptions.datasource?.config
Expand Down
4 changes: 3 additions & 1 deletion src/components/section/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ export function getFieldControlWithFallback(question: OHRIFormField) {
if (question.type === 'encounterLocation') {
question.questionOptions.rendering = 'encounter-location';
}

if (question.type === 'encounterProvider') {
return getRegisteredControl('encounterProvider');
}
// Retrieve the registered control based on the specified rendering
return getRegisteredControl(question.questionOptions.rendering);
}
Expand Down
2 changes: 1 addition & 1 deletion src/datasources/concept-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class ConceptDataSource extends BaseOpenMRSDataSource {
} else {
return openmrsFetch(searchTerm ? `${apiUrl}&q=${searchTerm}` : apiUrl).then(({ data }) => {
return data.results.filter(
concept => concept.conceptClass && config.class.includes(concept.conceptClass.uuid),
(concept) => concept.conceptClass && config.class.includes(concept.conceptClass.uuid),
);
});
}
Expand Down
6 changes: 3 additions & 3 deletions src/datasources/location-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ export class LocationDataSource extends BaseOpenMRSDataSource {
fetchData(searchTerm: string, config?: Record<string, any>, uuid?: string): Promise<any[]> {
let apiUrl = this.url;
const urlParts = apiUrl.split('?');
if (config?.tag) {
if (config?.tag) {
apiUrl = `${urlParts[0]}?tag=${config.tag}&${urlParts[1]}`;
}
//overwrite url if there's a uuid value, meaning we are in edit mode
if(uuid){
if (uuid) {
apiUrl = `${urlParts[0]}/${uuid}?${urlParts[1]}`;
}

return openmrsFetch(searchTerm ? `${apiUrl}&q=${searchTerm}` : apiUrl).then(({ data }) => {
if(data.results){
if (data.results) {
return data.results;
}
return data;
Expand Down
28 changes: 28 additions & 0 deletions src/datasources/provider-datasource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { openmrsFetch } from '@openmrs/esm-framework';
import { BaseOpenMRSDataSource } from './data-source';

export class ProviderDataSource extends BaseOpenMRSDataSource {
constructor() {
super('/ws/rest/v1/provider?v=custom:(uuid,display)');
}

fetchData(searchTerm: string, config?: Record<string, any>, uuid?: string): Promise<any[]> {
let apiUrl = this.url;
const urlParts = apiUrl.split('?');
if (config?.tag) {
apiUrl = `${urlParts[0]}?tag=${config.tag}&${urlParts[1]}`;
}
//overwrite url if there's a uuid value, meaning we are in edit mode
if (uuid) {
apiUrl = `${urlParts[0]}/${uuid}?${urlParts[1]}`;
}

return openmrsFetch(searchTerm ? `${apiUrl}&q=${searchTerm}` : apiUrl).then(({ data }) => {
if (data.results) {
console.log(data.results);
return data.results;
}
return data;
});
}
}
2 changes: 1 addition & 1 deletion src/hooks/useEncounterRole.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export function useEncounterRole() {
'/ws/rest/v1/encounterrole?v=custom:(uuid,display,name)',
openmrsFetch,
);
const clinicalEncounterRole = data?.data.results.find(encounterRole => encounterRole.name === 'Clinician');
const clinicalEncounterRole = data?.data.results.find((encounterRole) => encounterRole.name === 'Clinician');

if (clinicalEncounterRole) {
return { encounterRole: clinicalEncounterRole, error, isLoading };
Expand Down
3 changes: 3 additions & 0 deletions src/ohri-form-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type OHRIFormContextProps = {
values: Record<string, any>;
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void;
setEncounterLocation: (value: any) => void;
setEncounterProvider: (value: any) => void;
obsGroupsToVoid: Array<any>;
setObsGroupsToVoid: (value: any) => void;
encounterContext: EncounterContext;
Expand All @@ -25,6 +26,8 @@ export interface EncounterContext {
sessionMode: SessionMode;
encounterDate: Date;
setEncounterDate(value: Date): void;
encounterProvider: string;
setEncounterProvider(value: string): void;
initValues?: Record<string, any>;
setObsGroupCounter?: any;
}
Expand Down
6 changes: 6 additions & 0 deletions src/registry/inbuilt-components/control-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ export const controlTemplates: Array<ControlTemplate> = [
},
},
},
{
name: 'encounterProvider',
datasource: {
name: 'provider_datasource',
},
},
{
name: 'problem',
datasource: {
Expand Down
2 changes: 1 addition & 1 deletion src/registry/inbuilt-components/inbuiltControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,6 @@ export const inbuiltControls: Array<RegistryItem<React.ComponentType<OHRIFormFie
...controlTemplates.map((template) => ({
name: `${template.name}Control`,
component: templateToComponentMap.find((component) => component.name === template.name).baseControlComponent,
type: template.name.toLowerCase(),
type: template.name,
})),
];
7 changes: 6 additions & 1 deletion src/registry/inbuilt-components/inbuiltDataSources.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataSource } from '../../api/types';
import { ConceptDataSource } from '../../datasources/concept-data-source';
import { LocationDataSource } from '../../datasources/location-data-source';
import { ProviderDataSource } from '../../datasources/provider-datasource';
import { RegistryItem } from '../registry';

/**
Expand All @@ -19,8 +20,12 @@ export const inbuiltDataSources: Array<RegistryItem<DataSource<any>>> = [
name: 'problem_datasource',
component: new ConceptDataSource(),
},
{
name: 'provider_datasource',
component: new ProviderDataSource(),
},
];

export const validateInbuiltDatasource = (name: string) => {
return inbuiltDataSources.some(datasource => datasource.name === name);
return inbuiltDataSources.some((datasource) => datasource.name === name);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SubmissionHandler } from '../../api/types';
import { ObsSubmissionHandler, EncounterLocationSubmissionHandler } from '../../submission-handlers/base-handlers';
import { EncounterDatetimeHandler } from '../../submission-handlers/encounterDatetimeHandler';
import { EncounterProviderHandler } from '../../submission-handlers/encounterProviderHandler';
import { RegistryItem } from '../registry';

/**
Expand All @@ -27,4 +28,9 @@ export const inbuiltFieldSubmissionHandlers: Array<RegistryItem<SubmissionHandle
component: EncounterDatetimeHandler,
type: 'encounterDatetime',
},
{
name: 'EncounterProviderHandler',
component: EncounterProviderHandler,
type: 'encounterProvider',
},
];
6 changes: 5 additions & 1 deletion src/registry/inbuilt-components/template-component-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@ export const templateToComponentMap = [
{
name: 'problem',
baseControlComponent: UISelectExtended,
}
},
{
name: 'encounterProvider',
baseControlComponent: UISelectExtended,
},
];
24 changes: 24 additions & 0 deletions src/submission-handlers/encounterProviderHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { SubmissionHandler } from '..';
import { getEncounterProviders } from '../api/api';
import { OpenmrsEncounter, OHRIFormField } from '../api/types';
import { EncounterContext } from '../ohri-form-context';

export const EncounterProviderHandler: SubmissionHandler = {
handleFieldSubmission: (field: OHRIFormField, value: any, context: EncounterContext) => {
context.setEncounterProvider(value);
return value;
},
getInitialValue: (encounter: OpenmrsEncounter, field: OHRIFormField, allFormFields?: OHRIFormField[]) => {
return new Date(); // TO DO: pick it from the visit if present
},

getDisplayValue: (field: OHRIFormField, value: any) => {
if (!field.value) {
return null;
}
return value;
},
getPreviousValue: (field: OHRIFormField, encounter: OpenmrsEncounter, allFormFields: Array<OHRIFormField>) => {
return null;
},
};

0 comments on commit a22b6d6

Please sign in to comment.