@openmrs/esm-patient-medications-app 11.3.1-pre.9641 → 11.3.1-pre.9651
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +16 -16
- package/dist/1918.js +1 -1
- package/dist/1918.js.map +1 -1
- package/dist/2102.js +1 -1
- package/dist/2102.js.map +1 -1
- package/dist/4300.js +1 -1
- package/dist/4341.js +1 -1
- package/dist/4341.js.map +1 -1
- package/dist/4549.js +1 -0
- package/dist/4549.js.map +1 -0
- package/dist/6877.js +2 -0
- package/dist/6877.js.map +1 -0
- package/dist/7160.js +1 -1
- package/dist/8437.js +1 -1
- package/dist/8437.js.map +1 -1
- package/dist/8812.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-medications-app.js +1 -1
- package/dist/openmrs-esm-patient-medications-app.js.buildmanifest.json +65 -114
- package/dist/routes.json +1 -1
- package/package.json +2 -2
- package/src/add-drug-order/add-drug-order.component.tsx +23 -18
- package/src/add-drug-order/add-drug-order.test.tsx +2 -3
- package/src/add-drug-order/add-drug-order.workspace.tsx +22 -7
- package/src/add-drug-order/drug-order-form.component.tsx +20 -107
- package/src/add-drug-order/drug-order-form.resource.ts +5 -22
- package/src/add-drug-order/drug-search/drug-search-combobox.component.tsx +17 -5
- package/src/add-drug-order/drug-search/drug-search-combobox.test.tsx +3 -1
- package/src/add-drug-order/drug-search/drug-search.resource.tsx +0 -4
- package/src/add-drug-order/exported-add-drug-order.workspace.tsx +6 -4
- package/src/api/api.ts +71 -36
- package/src/components/medications-details-table.component.tsx +7 -53
- package/src/config-schema.ts +0 -14
- package/src/index.ts +0 -5
- package/src/routes.json +0 -8
- package/translations/en.json +1 -13
- package/dist/1022.js +0 -1
- package/dist/1022.js.map +0 -1
- package/dist/3338.js +0 -2
- package/dist/3338.js.map +0 -1
- package/dist/4138.js +0 -1
- package/dist/4138.js.map +0 -1
- package/dist/4953.js +0 -1
- package/dist/4953.js.map +0 -1
- package/src/add-drug-order/fill-prescription-form.workspace.tsx +0 -110
- /package/dist/{3338.js.LICENSE.txt → 6877.js.LICENSE.txt} +0 -0
|
@@ -32,9 +32,7 @@ import {
|
|
|
32
32
|
parseDate,
|
|
33
33
|
showSnackbar,
|
|
34
34
|
useConfig,
|
|
35
|
-
useFeatureFlag,
|
|
36
35
|
useLayoutType,
|
|
37
|
-
useSession,
|
|
38
36
|
Workspace2,
|
|
39
37
|
type Visit,
|
|
40
38
|
} from '@openmrs/esm-framework';
|
|
@@ -51,31 +49,21 @@ import {
|
|
|
51
49
|
} from '@openmrs/esm-patient-common-lib';
|
|
52
50
|
import { useOrderConfig } from '../api/order-config';
|
|
53
51
|
import { type ConfigObject } from '../config-schema';
|
|
54
|
-
import {
|
|
52
|
+
import { useActivePatientOrders } from '../api';
|
|
55
53
|
import styles from './drug-order-form.scss';
|
|
56
|
-
import {
|
|
57
|
-
drugOrderBasketItemToFormValue,
|
|
58
|
-
type MedicationOrderFormData,
|
|
59
|
-
useDrugOrderForm,
|
|
60
|
-
} from './drug-order-form.resource';
|
|
61
|
-
import DrugSearchComboBox from './drug-search/drug-search-combobox.component';
|
|
54
|
+
import { type MedicationOrderFormData, useDrugOrderForm } from './drug-order-form.resource';
|
|
62
55
|
|
|
63
56
|
export interface DrugOrderFormProps {
|
|
64
|
-
|
|
57
|
+
/**
|
|
58
|
+
* This is either an order pending in the order basket, or an existing order saved to the backend for editing.
|
|
59
|
+
*/
|
|
60
|
+
initialOrderBasketItem: DrugOrderBasketItem | null;
|
|
65
61
|
patient: fhir.Patient;
|
|
66
62
|
visitContext: Visit;
|
|
67
63
|
onSave: (finalizedOrder: DrugOrderBasketItem) => Promise<void>;
|
|
68
64
|
saveButtonText: string;
|
|
69
65
|
onCancel: () => void;
|
|
70
66
|
workspaceTitle: string;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* If true, allows user to select the prescribing provider when ordering medications from the order basket.
|
|
74
|
-
* (Otherwise, the prescribing provider always defaults to the current user.)
|
|
75
|
-
* The `prescriberProviderRoles` config must be set for this to work properly.
|
|
76
|
-
*/
|
|
77
|
-
allowSelectingPrescribingClinician: boolean;
|
|
78
|
-
allowSelectingDrug: boolean;
|
|
79
67
|
}
|
|
80
68
|
|
|
81
69
|
function MedicationInfoHeader({
|
|
@@ -125,37 +113,21 @@ function InputWrapper({ children }) {
|
|
|
125
113
|
}
|
|
126
114
|
|
|
127
115
|
export function DrugOrderForm({
|
|
128
|
-
initialOrderBasketItem,
|
|
116
|
+
initialOrderBasketItem: initialOrderBasketItem,
|
|
129
117
|
patient,
|
|
130
118
|
onSave,
|
|
131
119
|
saveButtonText,
|
|
132
120
|
onCancel,
|
|
133
|
-
allowSelectingPrescribingClinician,
|
|
134
|
-
allowSelectingDrug,
|
|
135
121
|
visitContext,
|
|
136
122
|
workspaceTitle,
|
|
137
123
|
}: DrugOrderFormProps) {
|
|
138
124
|
const { t } = useTranslation();
|
|
139
|
-
const { daysDurationUnit
|
|
125
|
+
const { daysDurationUnit } = useConfig<ConfigObject>();
|
|
140
126
|
const isTablet = useLayoutType() === 'tablet';
|
|
141
127
|
const { orderConfigObject, error: errorFetchingOrderConfig } = useOrderConfig();
|
|
142
128
|
|
|
143
|
-
const isProviderManagementModuleInstalled = useFeatureFlag('providermanagement-module');
|
|
144
|
-
const allowAndSupportSelectingPrescribingClinician =
|
|
145
|
-
isProviderManagementModuleInstalled && allowSelectingPrescribingClinician;
|
|
146
|
-
|
|
147
|
-
const {
|
|
148
|
-
data: providers,
|
|
149
|
-
isLoading: isLoadingProviders,
|
|
150
|
-
error: errorLoadingProviders,
|
|
151
|
-
} = useProviders(allowAndSupportSelectingPrescribingClinician ? prescriberProviderRoles : null);
|
|
152
129
|
const [isSaving, setIsSaving] = useState(false);
|
|
153
|
-
|
|
154
|
-
const { currentProvider } = useSession();
|
|
155
|
-
const defaultPrescribingProvider = allowAndSupportSelectingPrescribingClinician
|
|
156
|
-
? providers?.find((p) => p.uuid === currentProvider.uuid)
|
|
157
|
-
: currentProvider;
|
|
158
|
-
const drugOrderForm = useDrugOrderForm(initialOrderBasketItem, defaultPrescribingProvider?.uuid);
|
|
130
|
+
const drugOrderForm = useDrugOrderForm(initialOrderBasketItem);
|
|
159
131
|
const {
|
|
160
132
|
control,
|
|
161
133
|
formState: { isDirty },
|
|
@@ -198,11 +170,9 @@ export function DrugOrderForm({
|
|
|
198
170
|
const startDate = watch('startDate');
|
|
199
171
|
|
|
200
172
|
const handleFormSubmission = async (data: MedicationOrderFormData) => {
|
|
201
|
-
const
|
|
173
|
+
const newBasketItem = {
|
|
202
174
|
...initialOrderBasketItem,
|
|
203
175
|
drug: data.drug,
|
|
204
|
-
orderer: data.orderer.uuid,
|
|
205
|
-
careSetting: data.careSetting,
|
|
206
176
|
isFreeTextDosage: data.isFreeTextDosage,
|
|
207
177
|
freeTextDosage: data.freeTextDosage,
|
|
208
178
|
dosage: data.dosage,
|
|
@@ -219,9 +189,14 @@ export function DrugOrderForm({
|
|
|
219
189
|
indication: data.indication,
|
|
220
190
|
frequency: data.frequency,
|
|
221
191
|
startDate: data.startDate,
|
|
192
|
+
action: initialOrderBasketItem?.action ?? 'NEW',
|
|
193
|
+
commonMedicationName: data.drug.display,
|
|
194
|
+
display: data.drug.display,
|
|
195
|
+
visit: initialOrderBasketItem?.visit ?? visitContext, // TODO: they really should be the same
|
|
222
196
|
} as DrugOrderBasketItem;
|
|
197
|
+
|
|
223
198
|
setIsSaving(true);
|
|
224
|
-
await onSave(
|
|
199
|
+
await onSave(newBasketItem);
|
|
225
200
|
setIsSaving(false);
|
|
226
201
|
};
|
|
227
202
|
|
|
@@ -281,10 +256,6 @@ export function DrugOrderForm({
|
|
|
281
256
|
return menu?.item?.value?.toLowerCase().includes(menu?.inputValue?.toLowerCase());
|
|
282
257
|
}, []);
|
|
283
258
|
|
|
284
|
-
const filterItemsByProviderName = useCallback((menu) => {
|
|
285
|
-
return menu?.item?.person?.display?.toLowerCase().includes(menu?.inputValue?.toLowerCase());
|
|
286
|
-
}, []);
|
|
287
|
-
|
|
288
259
|
const filterItemsBySynonymNames = useCallback((menu) => {
|
|
289
260
|
if (menu?.inputValue?.length) {
|
|
290
261
|
return menu.item?.names?.some((abbr: string) => abbr.toLowerCase().includes(menu.inputValue.toLowerCase()));
|
|
@@ -325,8 +296,10 @@ export function DrugOrderForm({
|
|
|
325
296
|
// See: https://openmrs.atlassian.net/browse/RESTWS-1003
|
|
326
297
|
const { data: activeOrders } = useActivePatientOrders(patient.id);
|
|
327
298
|
const drugAlreadyPrescribedForNewOrder = useMemo(
|
|
328
|
-
() =>
|
|
329
|
-
|
|
299
|
+
() =>
|
|
300
|
+
(initialOrderBasketItem == null || initialOrderBasketItem?.action == 'NEW') &&
|
|
301
|
+
activeOrders?.some((order) => order?.drug?.uuid === drug?.uuid),
|
|
302
|
+
[activeOrders, drug, initialOrderBasketItem],
|
|
330
303
|
);
|
|
331
304
|
|
|
332
305
|
return (
|
|
@@ -361,66 +334,6 @@ export function DrugOrderForm({
|
|
|
361
334
|
/>
|
|
362
335
|
)}
|
|
363
336
|
<h1 className={styles.orderFormHeading}>{t('orderForm', 'Order Form')}</h1>
|
|
364
|
-
{(allowSelectingDrug || allowSelectingPrescribingClinician) && (
|
|
365
|
-
<section className={styles.formSection}>
|
|
366
|
-
<h3 className={styles.sectionHeader}>{t('prescriptionInfo', 'Prescription info')}</h3>
|
|
367
|
-
<Stack gap={5}>
|
|
368
|
-
{allowSelectingDrug && (
|
|
369
|
-
<InputWrapper>
|
|
370
|
-
<DrugSearchComboBox
|
|
371
|
-
setSelectedDrugItem={(item) => {
|
|
372
|
-
// when selecting a new drug, it can have its own order template that populates many fields
|
|
373
|
-
// we should just reset the entire form
|
|
374
|
-
reset(drugOrderBasketItemToFormValue(item, startDate, currentProvider.uuid));
|
|
375
|
-
}}
|
|
376
|
-
visit={visitContext}
|
|
377
|
-
/>
|
|
378
|
-
{drugAlreadyPrescribedForNewOrder && (
|
|
379
|
-
<FormLabel className={styles.errorLabel}>
|
|
380
|
-
{t('activePrescriptionExists', 'Active prescription exists for this drug')}
|
|
381
|
-
</FormLabel>
|
|
382
|
-
)}
|
|
383
|
-
<FormLabel className={styles.errorLabel}>{drugFieldError?.message}</FormLabel>
|
|
384
|
-
</InputWrapper>
|
|
385
|
-
)}
|
|
386
|
-
{allowAndSupportSelectingPrescribingClinician &&
|
|
387
|
-
!isLoadingProviders &&
|
|
388
|
-
(providers?.length > 0 ? (
|
|
389
|
-
<ControlledFieldInput
|
|
390
|
-
control={control}
|
|
391
|
-
name="orderer"
|
|
392
|
-
type="comboBox"
|
|
393
|
-
getValues={getValues}
|
|
394
|
-
id="orderer"
|
|
395
|
-
shouldFilterItem={filterItemsByProviderName}
|
|
396
|
-
placeholder={t('prescribingClinician', 'Prescribing Clinician')}
|
|
397
|
-
titleText={t('prescribingClinician', 'Prescribing Clinician')}
|
|
398
|
-
items={providers}
|
|
399
|
-
itemToString={(item: Provider) => item?.person?.display}
|
|
400
|
-
/>
|
|
401
|
-
) : errorLoadingProviders ? (
|
|
402
|
-
<InlineNotification
|
|
403
|
-
kind="warning"
|
|
404
|
-
lowContrast
|
|
405
|
-
className={styles.inlineNotification}
|
|
406
|
-
title={t('errorLoadingClinicians', 'Error loading clinicians')}
|
|
407
|
-
subtitle={t('tryReopeningTheForm', 'Please try launching the form again')}
|
|
408
|
-
/>
|
|
409
|
-
) : (
|
|
410
|
-
<InlineNotification
|
|
411
|
-
kind="warning"
|
|
412
|
-
lowContrast
|
|
413
|
-
className={styles.inlineNotification}
|
|
414
|
-
title={t('noCliniciansFound', 'No clinicians found')}
|
|
415
|
-
subtitle={t(
|
|
416
|
-
'noCliniciansFoundDescription',
|
|
417
|
-
'Cannot select prescribing clinician because no clinicians with appropriate roles are found. Check configuration.',
|
|
418
|
-
)}
|
|
419
|
-
/>
|
|
420
|
-
))}
|
|
421
|
-
</Stack>
|
|
422
|
-
</section>
|
|
423
|
-
)}
|
|
424
337
|
<div ref={medicationInfoHeaderRef}>
|
|
425
338
|
<MedicationInfoHeader dosage={dosage} drug={drug} routeValue={routeValue} unitValue={unitValue} />
|
|
426
339
|
</div>
|
|
@@ -5,10 +5,10 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { parseDate, useConfig } from '@openmrs/esm-framework';
|
|
7
7
|
import { type Drug, type DrugOrderBasketItem } from '@openmrs/esm-patient-common-lib';
|
|
8
|
-
import {
|
|
8
|
+
import { useRequireOutpatientQuantity } from '../api';
|
|
9
9
|
import { type ConfigObject } from '../config-schema';
|
|
10
10
|
|
|
11
|
-
export function useDrugOrderForm(initialOrderBasketItem: DrugOrderBasketItem
|
|
11
|
+
export function useDrugOrderForm(initialOrderBasketItem: DrugOrderBasketItem) {
|
|
12
12
|
const medicationOrderFormSchema = useCreateMedicationOrderFormSchema();
|
|
13
13
|
|
|
14
14
|
const defaultValues = useMemo(() => {
|
|
@@ -17,8 +17,8 @@ export function useDrugOrderForm(initialOrderBasketItem: DrugOrderBasketItem, de
|
|
|
17
17
|
? parseDate(initialOrderBasketItem?.startDate)
|
|
18
18
|
: (initialOrderBasketItem?.startDate as Date) ?? new Date();
|
|
19
19
|
|
|
20
|
-
return drugOrderBasketItemToFormValue(initialOrderBasketItem, defaultStartDate
|
|
21
|
-
}, [initialOrderBasketItem
|
|
20
|
+
return drugOrderBasketItemToFormValue(initialOrderBasketItem, defaultStartDate);
|
|
21
|
+
}, [initialOrderBasketItem]);
|
|
22
22
|
|
|
23
23
|
const drugOrderForm: UseFormReturn<MedicationOrderFormData> = useForm<MedicationOrderFormData>({
|
|
24
24
|
mode: 'all',
|
|
@@ -29,17 +29,9 @@ export function useDrugOrderForm(initialOrderBasketItem: DrugOrderBasketItem, de
|
|
|
29
29
|
return drugOrderForm;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
export function drugOrderBasketItemToFormValue(
|
|
33
|
-
item: DrugOrderBasketItem,
|
|
34
|
-
startDate: Date,
|
|
35
|
-
providerUuid: string,
|
|
36
|
-
): MedicationOrderFormData {
|
|
32
|
+
export function drugOrderBasketItemToFormValue(item: DrugOrderBasketItem, startDate: Date): MedicationOrderFormData {
|
|
37
33
|
return {
|
|
38
|
-
orderer: {
|
|
39
|
-
uuid: providerUuid,
|
|
40
|
-
},
|
|
41
34
|
drug: item?.drug as Partial<Drug>,
|
|
42
|
-
careSetting: careSettingUuid,
|
|
43
35
|
isFreeTextDosage: item?.isFreeTextDosage ?? false,
|
|
44
36
|
freeTextDosage: item?.freeTextDosage,
|
|
45
37
|
dosage: item?.dosage ?? null,
|
|
@@ -95,15 +87,6 @@ function useCreateMedicationOrderFormSchema() {
|
|
|
95
87
|
},
|
|
96
88
|
)
|
|
97
89
|
.passthrough(),
|
|
98
|
-
orderer: z.object(
|
|
99
|
-
{
|
|
100
|
-
uuid: z.string(),
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
message: t('prescribingClinicianRequiredErrorMessage', 'Prescribing clinician is required'),
|
|
104
|
-
},
|
|
105
|
-
),
|
|
106
|
-
careSetting: z.string(),
|
|
107
90
|
freeTextDosage: z.string().refine((value) => !!value, {
|
|
108
91
|
message: t('freeDosageErrorMessage', 'Add free dosage note'),
|
|
109
92
|
}),
|
|
@@ -7,17 +7,22 @@ import { type ConfigObject } from '../../config-schema';
|
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
|
|
9
9
|
interface DrugSearchComboBoxProps {
|
|
10
|
-
|
|
10
|
+
initialOrderBasketItem: DrugOrderBasketItem;
|
|
11
|
+
setSelectedDrugItem(drug: DrugOrderBasketItem): void;
|
|
11
12
|
visit: Visit;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* This component is a ComboBox for searching for drugs. Similar to drug-search.component.tsx,
|
|
16
17
|
* but allows for custom behavior when a drug is selected.
|
|
17
|
-
* This
|
|
18
|
-
*
|
|
18
|
+
* This component is currently not used anywhere in the patient-medications-app, but can be used
|
|
19
|
+
* in the future for a drug form with an inlined drug search.
|
|
19
20
|
*/
|
|
20
|
-
const DrugSearchComboBox: React.FC<DrugSearchComboBoxProps> = ({
|
|
21
|
+
const DrugSearchComboBox: React.FC<DrugSearchComboBoxProps> = ({
|
|
22
|
+
initialOrderBasketItem,
|
|
23
|
+
setSelectedDrugItem,
|
|
24
|
+
visit,
|
|
25
|
+
}) => {
|
|
21
26
|
const { daysDurationUnit } = useConfig<ConfigObject>();
|
|
22
27
|
const { t } = useTranslation();
|
|
23
28
|
const [drugSearchTerm, setDrugSearchTerm] = useState('');
|
|
@@ -42,10 +47,17 @@ const DrugSearchComboBox: React.FC<DrugSearchComboBoxProps> = ({ setSelectedDrug
|
|
|
42
47
|
onChange={({ selectedItem }) => {
|
|
43
48
|
setSelectedDrugItem(selectedItem);
|
|
44
49
|
}}
|
|
50
|
+
initialSelectedItem={initialOrderBasketItem}
|
|
45
51
|
onInputChange={(inputText) => {
|
|
46
52
|
setDrugSearchTerm(inputText);
|
|
47
53
|
}}
|
|
48
|
-
itemToString={(item: DrugOrderBasketItem) =>
|
|
54
|
+
itemToString={(item: DrugOrderBasketItem) =>
|
|
55
|
+
item.display +
|
|
56
|
+
' — ' +
|
|
57
|
+
item.drug?.strength?.toLowerCase() +
|
|
58
|
+
' — ' +
|
|
59
|
+
item.drug?.dosageForm?.display?.toLowerCase()
|
|
60
|
+
}
|
|
49
61
|
placeholder={t('searchFieldPlaceholder', 'Search for a drug or orderset (e.g. "Aspirin")')}
|
|
50
62
|
titleText={t('drugName', 'Drug name')}
|
|
51
63
|
/>
|
|
@@ -52,5 +52,7 @@ describe('DrugSearchComboBox', () => {
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
function renderDrugSearchComboBox() {
|
|
55
|
-
render(
|
|
55
|
+
render(
|
|
56
|
+
<DrugSearchComboBox initialOrderBasketItem={null} setSelectedDrugItem={mockSetSelectedDrugItem} visit={null} />,
|
|
57
|
+
);
|
|
56
58
|
}
|
|
@@ -180,8 +180,6 @@ export function getTemplateOrderBasketItem(
|
|
|
180
180
|
freeTextDosage: '',
|
|
181
181
|
indication: '',
|
|
182
182
|
template: template.template,
|
|
183
|
-
orderer: null,
|
|
184
|
-
careSetting: null,
|
|
185
183
|
quantityUnits:
|
|
186
184
|
getDefault(template.template, 'quantityUnits') ?? drug?.dosageForm
|
|
187
185
|
? {
|
|
@@ -221,8 +219,6 @@ export function getTemplateOrderBasketItem(
|
|
|
221
219
|
numRefills: null,
|
|
222
220
|
freeTextDosage: '',
|
|
223
221
|
indication: '',
|
|
224
|
-
orderer: null,
|
|
225
|
-
careSetting: null,
|
|
226
222
|
quantityUnits: drug?.dosageForm
|
|
227
223
|
? {
|
|
228
224
|
value: drug?.dosageForm?.display,
|
|
@@ -4,7 +4,8 @@ import { type ExportedOrderBasketWindowProps, type DrugOrderBasketItem } from '@
|
|
|
4
4
|
import AddDrugOrder from './add-drug-order.component';
|
|
5
5
|
|
|
6
6
|
export interface AddDrugOrderWorkspaceAdditionalProps {
|
|
7
|
-
order
|
|
7
|
+
order?: DrugOrderBasketItem;
|
|
8
|
+
orderToEditOrdererUuid?: string;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -12,13 +13,14 @@ export interface AddDrugOrderWorkspaceAdditionalProps {
|
|
|
12
13
|
* @see add-drug-order.workspace.tsx
|
|
13
14
|
*/
|
|
14
15
|
export default function ExportedAddDrugOrderWorkspace({
|
|
15
|
-
workspaceProps: { order
|
|
16
|
+
workspaceProps: { order, orderToEditOrdererUuid },
|
|
16
17
|
windowProps: { patient, patientUuid, visitContext },
|
|
17
18
|
closeWorkspace,
|
|
18
|
-
}: Workspace2DefinitionProps<AddDrugOrderWorkspaceAdditionalProps, ExportedOrderBasketWindowProps
|
|
19
|
+
}: Workspace2DefinitionProps<AddDrugOrderWorkspaceAdditionalProps, ExportedOrderBasketWindowProps>) {
|
|
19
20
|
return (
|
|
20
21
|
<AddDrugOrder
|
|
21
|
-
initialOrder={
|
|
22
|
+
initialOrder={order}
|
|
23
|
+
orderToEditOrdererUuid={orderToEditOrdererUuid}
|
|
22
24
|
patient={patient}
|
|
23
25
|
patientUuid={patientUuid}
|
|
24
26
|
visitContext={visitContext}
|
package/src/api/api.ts
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { useCallback, useMemo } from 'react';
|
|
2
2
|
import useSWR, { useSWRConfig } from 'swr';
|
|
3
3
|
import useSWRImmutable from 'swr/immutable';
|
|
4
|
-
import { openmrsFetch, restBaseUrl, useConfig,
|
|
5
|
-
import
|
|
6
|
-
DrugOrderBasketItem,
|
|
7
|
-
DrugOrderPost,
|
|
8
|
-
PatientOrderFetchResponse,
|
|
9
|
-
Order,
|
|
4
|
+
import { openmrsFetch, restBaseUrl, useConfig, type FetchResponse } from '@openmrs/esm-framework';
|
|
5
|
+
import {
|
|
6
|
+
type DrugOrderBasketItem,
|
|
7
|
+
type DrugOrderPost,
|
|
8
|
+
type PatientOrderFetchResponse,
|
|
9
|
+
type Order,
|
|
10
|
+
type PostDataPrepFunction,
|
|
11
|
+
careSettingUuid,
|
|
12
|
+
type OrderAction,
|
|
10
13
|
} from '@openmrs/esm-patient-common-lib';
|
|
11
14
|
import { type ConfigObject } from '../config-schema';
|
|
12
15
|
|
|
13
|
-
export const careSettingUuid = '6f0c9a92-6f24-11e3-af88-005056821db0';
|
|
14
|
-
|
|
15
16
|
const customRepresentation =
|
|
16
17
|
'custom:(uuid,dosingType,orderNumber,accessionNumber,' +
|
|
17
18
|
'patient:ref,action,careSetting:ref,previousOrder:ref,dateActivated,scheduledDate,dateStopped,autoExpireDate,' +
|
|
18
19
|
'orderType:ref,encounter:(uuid,display,visit),orderer:(uuid,display,person:(display)),orderReason,orderReasonNonCoded,orderType,urgency,instructions,' +
|
|
19
20
|
'commentToFulfiller,fulfillerStatus,drug:(uuid,display,strength,dosageForm:(display,uuid),concept),dose,doseUnits:ref,' +
|
|
20
21
|
'frequency:ref,asNeeded,asNeededCondition,quantity,quantityUnits:ref,numRefills,dosingInstructions,' +
|
|
21
|
-
'duration,durationUnits:ref,route:ref,brandName,dispenseAsWritten)';
|
|
22
|
+
'duration,durationUnits:ref,route:ref,brandName,dispenseAsWritten,concept)';
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* Sorts orders by date activated in descending order.
|
|
@@ -130,18 +131,22 @@ export function usePastPatientOrders(patientUuid: string) {
|
|
|
130
131
|
};
|
|
131
132
|
}
|
|
132
133
|
|
|
133
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Converts a DrugOrderBasketItem into an Order POST payload
|
|
136
|
+
*/
|
|
137
|
+
export const prepMedicationOrderPostData: PostDataPrepFunction = (
|
|
134
138
|
order: DrugOrderBasketItem,
|
|
135
|
-
patientUuid
|
|
136
|
-
encounterUuid
|
|
137
|
-
|
|
139
|
+
patientUuid,
|
|
140
|
+
encounterUuid,
|
|
141
|
+
orderingProviderUuid,
|
|
142
|
+
): DrugOrderPost => {
|
|
138
143
|
if (order.action === 'NEW' || order.action === 'RENEW') {
|
|
139
144
|
return {
|
|
140
145
|
action: 'NEW',
|
|
141
146
|
patient: patientUuid,
|
|
142
147
|
type: 'drugorder',
|
|
143
|
-
careSetting:
|
|
144
|
-
orderer:
|
|
148
|
+
careSetting: careSettingUuid,
|
|
149
|
+
orderer: orderingProviderUuid,
|
|
145
150
|
encounter: encounterUuid,
|
|
146
151
|
drug: order.drug.uuid,
|
|
147
152
|
dose: order.dosage,
|
|
@@ -168,8 +173,8 @@ export function prepMedicationOrderPostData(
|
|
|
168
173
|
patient: patientUuid,
|
|
169
174
|
type: 'drugorder',
|
|
170
175
|
previousOrder: order.previousOrder,
|
|
171
|
-
careSetting:
|
|
172
|
-
orderer:
|
|
176
|
+
careSetting: careSettingUuid,
|
|
177
|
+
orderer: orderingProviderUuid,
|
|
173
178
|
encounter: encounterUuid,
|
|
174
179
|
drug: order.drug.uuid,
|
|
175
180
|
dose: order.dosage,
|
|
@@ -196,9 +201,9 @@ export function prepMedicationOrderPostData(
|
|
|
196
201
|
type: 'drugorder',
|
|
197
202
|
previousOrder: order.previousOrder,
|
|
198
203
|
patient: patientUuid,
|
|
199
|
-
careSetting:
|
|
204
|
+
careSetting: careSettingUuid,
|
|
200
205
|
encounter: encounterUuid,
|
|
201
|
-
orderer:
|
|
206
|
+
orderer: orderingProviderUuid,
|
|
202
207
|
concept: order.drug.concept.uuid,
|
|
203
208
|
drug: order.drug.uuid,
|
|
204
209
|
orderReasonNonCoded: null,
|
|
@@ -206,6 +211,53 @@ export function prepMedicationOrderPostData(
|
|
|
206
211
|
} else {
|
|
207
212
|
throw new Error(`Unknown order action ${order.action}. This is a development error.`);
|
|
208
213
|
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* The inverse of prepMedicationOrderPostData - converts an Order into a DrugOrderBasketItem
|
|
218
|
+
* See also the same function defined in esm-patient-orders-app/src/utils/index.ts
|
|
219
|
+
*/
|
|
220
|
+
export function buildMedicationOrder(order: Order, action: OrderAction): DrugOrderBasketItem {
|
|
221
|
+
return {
|
|
222
|
+
display: order.drug?.display,
|
|
223
|
+
previousOrder: action !== 'NEW' ? order.uuid : null,
|
|
224
|
+
action: action,
|
|
225
|
+
drug: order.drug,
|
|
226
|
+
dosage: order.dose,
|
|
227
|
+
unit: {
|
|
228
|
+
value: order.doseUnits?.display,
|
|
229
|
+
valueCoded: order.doseUnits?.uuid,
|
|
230
|
+
},
|
|
231
|
+
frequency: {
|
|
232
|
+
valueCoded: order.frequency?.uuid,
|
|
233
|
+
value: order.frequency?.display,
|
|
234
|
+
},
|
|
235
|
+
route: {
|
|
236
|
+
valueCoded: order.route?.uuid,
|
|
237
|
+
value: order.route?.display,
|
|
238
|
+
},
|
|
239
|
+
commonMedicationName: order.drug?.display,
|
|
240
|
+
isFreeTextDosage: order.dosingType === 'org.openmrs.FreeTextDosingInstructions',
|
|
241
|
+
freeTextDosage: order.dosingType === 'org.openmrs.FreeTextDosingInstructions' ? order.dosingInstructions : '',
|
|
242
|
+
patientInstructions: order.dosingType !== 'org.openmrs.FreeTextDosingInstructions' ? order.dosingInstructions : '',
|
|
243
|
+
asNeeded: order.asNeeded,
|
|
244
|
+
asNeededCondition: order.asNeededCondition,
|
|
245
|
+
startDate: action === 'DISCONTINUE' ? order.dateActivated : new Date(),
|
|
246
|
+
duration: order.duration,
|
|
247
|
+
durationUnit: {
|
|
248
|
+
valueCoded: order.durationUnits?.uuid,
|
|
249
|
+
value: order.durationUnits?.display,
|
|
250
|
+
},
|
|
251
|
+
pillsDispensed: order.quantity,
|
|
252
|
+
numRefills: order.numRefills,
|
|
253
|
+
indication: order.orderReasonNonCoded,
|
|
254
|
+
quantityUnits: {
|
|
255
|
+
value: order.quantityUnits?.display,
|
|
256
|
+
valueCoded: order.quantityUnits?.uuid,
|
|
257
|
+
},
|
|
258
|
+
encounterUuid: order.encounter?.uuid,
|
|
259
|
+
visit: order.encounter.visit,
|
|
260
|
+
};
|
|
209
261
|
}
|
|
210
262
|
|
|
211
263
|
/**
|
|
@@ -238,20 +290,3 @@ export function useRequireOutpatientQuantity(): {
|
|
|
238
290
|
|
|
239
291
|
return results;
|
|
240
292
|
}
|
|
241
|
-
|
|
242
|
-
export interface Provider {
|
|
243
|
-
uuid: string;
|
|
244
|
-
person: {
|
|
245
|
-
display?: string;
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
export function useProviders(providerRoles: Array<string>) {
|
|
250
|
-
const rep = 'custom:(uuid,person:(display)';
|
|
251
|
-
const ret = useOpenmrsFetchAll<Provider>(
|
|
252
|
-
providerRoles != null ? `${restBaseUrl}/provider?providerRoles=${providerRoles.join(',')}&v=${rep})` : null,
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
ret.data?.sort((a, b) => (a.person?.display ?? '').localeCompare(b.person?.display ?? ''));
|
|
256
|
-
return ret;
|
|
257
|
-
}
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
UserIcon,
|
|
44
44
|
launchWorkspace2,
|
|
45
45
|
type Encounter,
|
|
46
|
+
showModal,
|
|
46
47
|
} from '@openmrs/esm-framework';
|
|
47
48
|
import { useTranslation } from 'react-i18next';
|
|
48
49
|
import { useReactToPrint } from 'react-to-print';
|
|
@@ -51,6 +52,7 @@ import PrintComponent from '../print/print.component';
|
|
|
51
52
|
import styles from './medications-details-table.scss';
|
|
52
53
|
import { useSWRConfig } from 'swr';
|
|
53
54
|
import { type AddDrugOrderWorkspaceProps } from '../add-drug-order/add-drug-order.workspace';
|
|
55
|
+
import { buildMedicationOrder } from '../api';
|
|
54
56
|
|
|
55
57
|
export interface MedicationsDetailsTableProps {
|
|
56
58
|
isValidating?: boolean;
|
|
@@ -414,8 +416,6 @@ function OrderBasketItemActions({
|
|
|
414
416
|
pillsDispensed: medication.quantity,
|
|
415
417
|
numRefills: medication.numRefills,
|
|
416
418
|
indication: medication.orderReasonNonCoded,
|
|
417
|
-
orderer: medication.orderer.uuid,
|
|
418
|
-
careSetting: medication.careSetting.uuid,
|
|
419
419
|
quantityUnits: {
|
|
420
420
|
value: medication.quantityUnits?.display,
|
|
421
421
|
valueCoded: medication.quantityUnits?.uuid,
|
|
@@ -433,60 +433,16 @@ function OrderBasketItemActions({
|
|
|
433
433
|
}, [items, setItems, medication, workspaceGroupProps]);
|
|
434
434
|
|
|
435
435
|
const handleModifyClick = useCallback(() => {
|
|
436
|
-
const newItem: DrugOrderBasketItem = {
|
|
437
|
-
uuid: medication.uuid,
|
|
438
|
-
display: medication.drug?.display,
|
|
439
|
-
previousOrder: medication.uuid,
|
|
440
|
-
startDate: new Date(),
|
|
441
|
-
action: 'REVISE',
|
|
442
|
-
drug: medication.drug,
|
|
443
|
-
dosage: medication.dose,
|
|
444
|
-
unit: {
|
|
445
|
-
value: medication.doseUnits?.display,
|
|
446
|
-
valueCoded: medication.doseUnits?.uuid,
|
|
447
|
-
},
|
|
448
|
-
frequency: {
|
|
449
|
-
valueCoded: medication.frequency?.uuid,
|
|
450
|
-
value: medication.frequency?.display,
|
|
451
|
-
},
|
|
452
|
-
route: {
|
|
453
|
-
valueCoded: medication.route?.uuid,
|
|
454
|
-
value: medication.route?.display,
|
|
455
|
-
},
|
|
456
|
-
commonMedicationName: medication.drug?.display,
|
|
457
|
-
isFreeTextDosage: medication.dosingType === 'org.openmrs.FreeTextDosingInstructions',
|
|
458
|
-
freeTextDosage:
|
|
459
|
-
medication.dosingType === 'org.openmrs.FreeTextDosingInstructions' ? medication.dosingInstructions : '',
|
|
460
|
-
patientInstructions:
|
|
461
|
-
medication.dosingType !== 'org.openmrs.FreeTextDosingInstructions' ? medication.dosingInstructions : '',
|
|
462
|
-
asNeeded: medication.asNeeded,
|
|
463
|
-
asNeededCondition: medication.asNeededCondition,
|
|
464
|
-
duration: medication.duration,
|
|
465
|
-
durationUnit: {
|
|
466
|
-
valueCoded: medication.durationUnits?.uuid,
|
|
467
|
-
value: medication.durationUnits?.display,
|
|
468
|
-
},
|
|
469
|
-
pillsDispensed: medication.quantity,
|
|
470
|
-
numRefills: medication.numRefills,
|
|
471
|
-
indication: medication.orderReasonNonCoded,
|
|
472
|
-
orderer: medication.orderer?.uuid,
|
|
473
|
-
careSetting: medication.careSetting?.uuid,
|
|
474
|
-
quantityUnits: {
|
|
475
|
-
value: medication.quantityUnits?.display,
|
|
476
|
-
valueCoded: medication.quantityUnits?.uuid,
|
|
477
|
-
},
|
|
478
|
-
encounterUuid: medication.encounter?.uuid,
|
|
479
|
-
visit: medication.encounter?.visit,
|
|
480
|
-
};
|
|
481
|
-
setItems([...items, newItem]);
|
|
482
|
-
|
|
483
436
|
launchWorkspace2<AddDrugOrderWorkspaceProps, OrderBasketWindowProps, PatientWorkspaceGroupProps>(
|
|
484
437
|
'add-drug-order',
|
|
485
|
-
{
|
|
438
|
+
{
|
|
439
|
+
order: buildMedicationOrder(medication, 'REVISE'),
|
|
440
|
+
orderToEditOrdererUuid: medication.orderer.uuid,
|
|
441
|
+
},
|
|
486
442
|
{ encounterUuid: medication.encounter.uuid },
|
|
487
443
|
workspaceGroupProps,
|
|
488
444
|
);
|
|
489
|
-
}, [
|
|
445
|
+
}, [medication, workspaceGroupProps]);
|
|
490
446
|
|
|
491
447
|
const handleReorderClick = useCallback(() => {
|
|
492
448
|
setItems([
|
|
@@ -527,8 +483,6 @@ function OrderBasketItemActions({
|
|
|
527
483
|
pillsDispensed: medication.quantity,
|
|
528
484
|
numRefills: medication.numRefills,
|
|
529
485
|
indication: medication.orderReasonNonCoded,
|
|
530
|
-
orderer: medication.orderer?.uuid,
|
|
531
|
-
careSetting: medication.careSetting?.uuid,
|
|
532
486
|
quantityUnits: {
|
|
533
487
|
value: medication.quantityUnits?.display,
|
|
534
488
|
valueCoded: medication.quantityUnits?.uuid,
|
package/src/config-schema.ts
CHANGED
|
@@ -36,18 +36,6 @@ export const configSchema = {
|
|
|
36
36
|
_description: 'Whether to require an indication when placing a medication order',
|
|
37
37
|
_default: true,
|
|
38
38
|
},
|
|
39
|
-
prescriberProviderRoles: {
|
|
40
|
-
_type: Type.Array,
|
|
41
|
-
_description:
|
|
42
|
-
'Array of provider roles uuids. If specified, the drug order form shows the "Prescribing Clinician" dropdown listing all providers with one of the specified roles. (The dropdown is hidden if no providers match the role criteria.) This feature requires the providermanagement backend module. Note that, in any case, any user who can submit the drug order form may still do so with themselves as the prescriber.',
|
|
43
|
-
_default: [],
|
|
44
|
-
},
|
|
45
|
-
drugOrderEncounterType: {
|
|
46
|
-
_type: Type.UUID,
|
|
47
|
-
_description:
|
|
48
|
-
'The encounter type of the encounter for the Fill Prescription form. Defaults to the "Order" encounter type.',
|
|
49
|
-
_default: '39da3525-afe4-45ff-8977-c53b7b359158',
|
|
50
|
-
},
|
|
51
39
|
};
|
|
52
40
|
|
|
53
41
|
export interface ConfigObject {
|
|
@@ -59,6 +47,4 @@ export interface ConfigObject {
|
|
|
59
47
|
showPrintButton: boolean;
|
|
60
48
|
debounceDelayInMs: number;
|
|
61
49
|
requireIndication: boolean;
|
|
62
|
-
prescriberProviderRoles: Array<string>;
|
|
63
|
-
drugOrderEncounterType: string;
|
|
64
50
|
}
|
package/src/index.ts
CHANGED
|
@@ -46,8 +46,3 @@ export const exportedAddDrugOrderWorkspace = getAsyncLifecycle(
|
|
|
46
46
|
() => import('./add-drug-order/exported-add-drug-order.workspace'),
|
|
47
47
|
options,
|
|
48
48
|
);
|
|
49
|
-
|
|
50
|
-
export const fillPrescriptionFormWorkspace = getAsyncLifecycle(
|
|
51
|
-
() => import('./add-drug-order/fill-prescription-form.workspace'),
|
|
52
|
-
options,
|
|
53
|
-
);
|
package/src/routes.json
CHANGED
|
@@ -73,14 +73,6 @@
|
|
|
73
73
|
"component": "drugSearchComboBox"
|
|
74
74
|
}
|
|
75
75
|
],
|
|
76
|
-
"workspaces": [
|
|
77
|
-
{
|
|
78
|
-
"name": "fill-prescription-form",
|
|
79
|
-
"title": "fillPrescription",
|
|
80
|
-
"component": "fillPrescriptionFormWorkspace",
|
|
81
|
-
"type": "order"
|
|
82
|
-
}
|
|
83
|
-
],
|
|
84
76
|
"workspaces2": [
|
|
85
77
|
{
|
|
86
78
|
"name": "add-drug-order",
|