@openmrs/esm-patient-orders-app 11.3.1-patch.9310 → 11.3.1-patch.9508
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 +15 -18
- package/dist/1119.js +1 -1
- package/dist/1197.js +1 -1
- package/dist/1571.js +1 -0
- package/dist/1571.js.map +1 -0
- package/dist/2146.js +1 -1
- package/dist/2690.js +1 -1
- package/dist/2717.js +1 -0
- package/dist/2717.js.map +1 -0
- package/dist/3099.js +1 -1
- package/dist/3584.js +1 -1
- package/dist/4055.js +1 -1
- package/dist/4132.js +1 -1
- package/dist/4300.js +1 -1
- package/dist/4335.js +1 -1
- package/dist/439.js +1 -0
- package/dist/4618.js +1 -1
- package/dist/4652.js +1 -1
- package/dist/4937.js +1 -1
- package/dist/4937.js.map +1 -1
- package/dist/4944.js +1 -1
- package/dist/5134.js +2 -0
- package/dist/5134.js.map +1 -0
- package/dist/5173.js +1 -1
- package/dist/5241.js +1 -1
- package/dist/5442.js +1 -1
- package/dist/5661.js +1 -1
- package/dist/5670.js +1 -1
- package/dist/5670.js.map +1 -1
- package/dist/6022.js +1 -1
- package/dist/6468.js +1 -1
- package/dist/6589.js +1 -0
- package/dist/6679.js +1 -1
- package/dist/6840.js +1 -1
- package/dist/6859.js +1 -1
- package/dist/7097.js +1 -1
- package/dist/7159.js +1 -1
- package/dist/723.js +1 -1
- package/dist/7617.js +1 -1
- package/dist/795.js +1 -1
- package/dist/8163.js +1 -1
- package/dist/8349.js +1 -1
- package/dist/8371.js +1 -0
- package/dist/8618.js +1 -1
- package/dist/8625.js +1 -0
- package/dist/8625.js.map +1 -0
- package/dist/8803.js +1 -0
- package/dist/8803.js.map +1 -0
- package/dist/890.js +1 -1
- package/dist/8960.js +1 -0
- package/dist/8960.js.map +1 -0
- package/dist/9214.js +1 -1
- package/dist/9538.js +1 -1
- package/dist/9569.js +1 -1
- package/dist/986.js +1 -1
- package/dist/9879.js +1 -1
- package/dist/9895.js +1 -1
- package/dist/9900.js +1 -1
- package/dist/9913.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-orders-app.js +1 -1
- package/dist/openmrs-esm-patient-orders-app.js.buildmanifest.json +276 -259
- package/dist/openmrs-esm-patient-orders-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +2 -2
- package/src/api/api.ts +25 -0
- package/src/components/order-details-table.component.tsx +40 -53
- package/src/components/test-order.component.tsx +53 -49
- package/src/index.ts +9 -12
- package/src/lab-results/lab-results-form.component.tsx +343 -0
- package/src/lab-results/lab-results-form.test.tsx +455 -306
- package/src/lab-results/lab-results-schema.resource.tsx +13 -4
- package/src/lab-results/lab-results.resource.ts +113 -0
- package/src/order-basket/general-order-type/general-order-form/general-order-form.component.tsx +25 -71
- package/src/order-basket/general-order-type/{general-order-panel.component.tsx → general-order-type.component.tsx} +41 -23
- package/src/order-basket/general-order-type/{add-general-order/add-general-order.component.tsx → orderable-concept-search/orderable-concept-search.workspace.tsx} +83 -78
- package/src/order-basket/general-order-type/{add-general-order → orderable-concept-search}/search-results.component.tsx +14 -15
- package/src/order-basket/general-order-type/resources.ts +2 -3
- package/src/order-basket/order-basket.workspace.tsx +251 -35
- package/src/order-basket-action-button/order-basket-action-button.extension.tsx +31 -0
- package/src/order-basket-action-button/order-basket-action-button.test.tsx +36 -27
- package/src/order-cancellation-form/cancel-order-form.component.tsx +85 -82
- package/src/routes.json +25 -17
- package/src/utils/index.ts +3 -15
- package/translations/am.json +6 -20
- package/translations/ar.json +6 -20
- package/translations/ar_SY.json +6 -20
- package/translations/bn.json +6 -20
- package/translations/cs.json +114 -0
- package/translations/de.json +6 -20
- package/translations/en.json +12 -4
- package/translations/en_US.json +6 -20
- package/translations/es.json +6 -20
- package/translations/es_MX.json +6 -20
- package/translations/fr.json +7 -21
- package/translations/he.json +6 -20
- package/translations/hi.json +6 -20
- package/translations/hi_IN.json +6 -20
- package/translations/id.json +6 -20
- package/translations/it.json +6 -20
- package/translations/ka.json +6 -20
- package/translations/km.json +6 -20
- package/translations/ku.json +6 -20
- package/translations/ky.json +6 -20
- package/translations/lg.json +6 -20
- package/translations/ne.json +6 -20
- package/translations/pl.json +6 -20
- package/translations/pt.json +6 -20
- package/translations/pt_BR.json +6 -20
- package/translations/qu.json +6 -20
- package/translations/ro_RO.json +6 -20
- package/translations/ru_RU.json +6 -20
- package/translations/si.json +6 -20
- package/translations/sq.json +114 -0
- package/translations/sw.json +6 -20
- package/translations/sw_KE.json +6 -20
- package/translations/tr.json +6 -20
- package/translations/tr_TR.json +6 -20
- package/translations/uk.json +6 -20
- package/translations/uz.json +6 -20
- package/translations/uz@Latn.json +6 -20
- package/translations/uz_UZ.json +6 -20
- package/translations/vi.json +6 -20
- package/translations/zh.json +6 -20
- package/translations/zh_CN.json +6 -20
- package/translations/zh_TW.json +114 -0
- package/dist/1253.js +0 -1
- package/dist/1253.js.map +0 -1
- package/dist/1268.js +0 -2
- package/dist/1268.js.map +0 -1
- package/dist/375.js +0 -1
- package/dist/375.js.map +0 -1
- package/dist/4341.js +0 -1
- package/dist/4341.js.map +0 -1
- package/dist/4687.js +0 -1
- package/dist/4687.js.map +0 -1
- package/dist/6364.js +0 -1
- package/dist/6364.js.map +0 -1
- package/dist/6473.js +0 -1
- package/dist/6473.js.map +0 -1
- package/dist/8416.js +0 -1
- package/dist/8416.js.map +0 -1
- package/src/lab-results/exported-lab-results-form.workspace.tsx +0 -264
- package/src/lab-results/lab-results-form.workspace.tsx +0 -25
- package/src/order-basket/exported-order-basket.workspace.tsx +0 -54
- package/src/order-basket/general-order-type/add-general-order/add-general-order.workspace.tsx +0 -35
- package/src/order-basket/general-order-type/add-general-order/exported-add-general-order.workspace.tsx +0 -32
- package/src/order-basket/order-basket.component.tsx +0 -213
- package/src/order-basket-action-button/order-basket-action-button.component.tsx +0 -35
- /package/dist/{1268.js.LICENSE.txt → 5134.js.LICENSE.txt} +0 -0
- /package/src/order-basket/general-order-type/{add-general-order → orderable-concept-search}/orderable-concept-search.scss +0 -0
- /package/src/order-basket/general-order-type/{add-general-order → orderable-concept-search}/search-results.scss +0 -0
|
@@ -25,17 +25,26 @@ function createSchemaForConcept(labOrderConcept: LabOrderConcept): SchemaRecord
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
function createSchemaForConceptArray(labOrderConcepts: Array<LabOrderConcept>): SchemaRecord {
|
|
29
|
+
return labOrderConcepts.reduce((acc, concept) => {
|
|
30
|
+
return {
|
|
31
|
+
...acc,
|
|
32
|
+
...createSchemaForConcept(concept), // reuses recursive logic
|
|
33
|
+
};
|
|
34
|
+
}, {});
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
/**
|
|
29
|
-
* Custom hook to generate a Zod schema for lab results form based on
|
|
38
|
+
* Custom hook to generate a Zod schema for lab results form based on multiple lab order concepts.
|
|
30
39
|
* This function is used to generate the schema for the lab results form.
|
|
31
|
-
* @param labOrderConceptUuid - The UUID of the lab order
|
|
40
|
+
* @param {Array<string>} labOrderConceptUuid - The List of UUID of the lab order concepts.
|
|
32
41
|
* @returns A Zod schema object for the lab results form.
|
|
33
42
|
*/
|
|
34
|
-
export const
|
|
43
|
+
export const createLabResultsFormCompositeSchema = (labOrderConcepts: Array<LabOrderConcept>) => {
|
|
35
44
|
if (!labOrderConcepts) {
|
|
36
45
|
return z.object({});
|
|
37
46
|
}
|
|
38
|
-
const schema =
|
|
47
|
+
const schema = createSchemaForConceptArray(labOrderConcepts);
|
|
39
48
|
|
|
40
49
|
return z.object(schema);
|
|
41
50
|
};
|
|
@@ -130,6 +130,26 @@ export function useOrderConceptByUuid(uuid: string) {
|
|
|
130
130
|
return results;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
export function useOrderConceptsByUuids(uuids: Array<string>) {
|
|
134
|
+
const { data, error, isLoading, isValidating, mutate } = useSWR<Array<LabOrderConcept>, Error>(
|
|
135
|
+
uuids.length ? ['concepts', ...uuids] : null,
|
|
136
|
+
() => Promise.all(uuids.map((uuid) => fetchAllSetMembers(uuid))),
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const results = useMemo(
|
|
140
|
+
() => ({
|
|
141
|
+
concepts: data ?? [],
|
|
142
|
+
isLoading,
|
|
143
|
+
error,
|
|
144
|
+
isValidating,
|
|
145
|
+
mutate,
|
|
146
|
+
}),
|
|
147
|
+
[data, error, isLoading, isValidating, mutate],
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
return results;
|
|
151
|
+
}
|
|
152
|
+
|
|
133
153
|
export function useLabEncounter(encounterUuid: string) {
|
|
134
154
|
const apiUrl = `${restBaseUrl}/encounter/${encounterUuid}?v=${labEncounterRepresentation}`;
|
|
135
155
|
|
|
@@ -163,6 +183,33 @@ export function useObservation(obsUuid: string) {
|
|
|
163
183
|
};
|
|
164
184
|
}
|
|
165
185
|
|
|
186
|
+
export function useObservations(obsUuids: Array<string>) {
|
|
187
|
+
const fetchMultipleObservations = async (): Promise<Array<Observation>> => {
|
|
188
|
+
const results = await Promise.all(
|
|
189
|
+
obsUuids.map(async (uuid) => {
|
|
190
|
+
const url = `${restBaseUrl}/obs/${uuid}?v=${conceptObsRepresentation}`;
|
|
191
|
+
const res = await openmrsFetch(url);
|
|
192
|
+
return res.data;
|
|
193
|
+
}),
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
return results;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const { data, error, isLoading, isValidating, mutate } = useSWR<Observation[], Error>(
|
|
200
|
+
obsUuids && obsUuids.length > 0 ? ['observations', ...obsUuids] : null,
|
|
201
|
+
fetchMultipleObservations,
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
data: data ?? [],
|
|
206
|
+
isLoading,
|
|
207
|
+
error,
|
|
208
|
+
isValidating,
|
|
209
|
+
mutate,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
166
213
|
export function useCompletedLabResults(order: Order) {
|
|
167
214
|
const {
|
|
168
215
|
encounter,
|
|
@@ -188,6 +235,29 @@ export function useCompletedLabResults(order: Order) {
|
|
|
188
235
|
};
|
|
189
236
|
}
|
|
190
237
|
|
|
238
|
+
export function useCompletedLabResultsArray(order: Order) {
|
|
239
|
+
const {
|
|
240
|
+
encounter,
|
|
241
|
+
isLoading: isLoadingEncounter,
|
|
242
|
+
mutate: mutateLabOrders,
|
|
243
|
+
error: encounterError,
|
|
244
|
+
} = useLabEncounter(order.encounter.uuid);
|
|
245
|
+
|
|
246
|
+
const obsUuids = encounter?.obs.filter((o) => o?.order.uuid === order?.uuid).map((o) => o.uuid);
|
|
247
|
+
|
|
248
|
+
const { data: observations, isLoading: isLoadingObs, error: errorObs, mutate: mutateObs } = useObservations(obsUuids);
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
isLoading: isLoadingEncounter || isLoadingObs,
|
|
252
|
+
completeLabResults: observations,
|
|
253
|
+
mutate: () => {
|
|
254
|
+
mutateLabOrders();
|
|
255
|
+
mutateObs();
|
|
256
|
+
},
|
|
257
|
+
error: errorObs ?? encounterError,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
191
261
|
// TODO: the calls to update order and observations for results should be transactional to allow for rollback
|
|
192
262
|
export async function updateOrderResult(
|
|
193
263
|
orderUuid: string,
|
|
@@ -256,6 +326,33 @@ export function createObservationPayload(
|
|
|
256
326
|
}
|
|
257
327
|
}
|
|
258
328
|
|
|
329
|
+
export function createCompositeObservationPayload(
|
|
330
|
+
concepts: LabOrderConcept[],
|
|
331
|
+
order: Order,
|
|
332
|
+
values: Record<string, unknown>,
|
|
333
|
+
status: string,
|
|
334
|
+
) {
|
|
335
|
+
if (!concepts || concepts.length === 0) return { obs: [] };
|
|
336
|
+
|
|
337
|
+
const allObs = concepts.flatMap((concept) => {
|
|
338
|
+
if (concept.set && concept.setMembers.length > 0) {
|
|
339
|
+
const groupMembers = concept.setMembers
|
|
340
|
+
.map((member) => createGroupMember(member, order, values, status))
|
|
341
|
+
.filter((member) => member !== null && member.value !== null && member.value !== undefined);
|
|
342
|
+
|
|
343
|
+
if (groupMembers.length === 0) return [];
|
|
344
|
+
|
|
345
|
+
return [createObservationByConcept(concept, order, groupMembers, null, status)];
|
|
346
|
+
} else {
|
|
347
|
+
const value = getValue(concept, values);
|
|
348
|
+
if (value === null || value === undefined) return [];
|
|
349
|
+
return [createObservationByConcept(concept, order, null, value, status)];
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
return { obs: allObs };
|
|
354
|
+
}
|
|
355
|
+
|
|
259
356
|
export function updateObservation(observationUuid: string, payload: Record<string, any>) {
|
|
260
357
|
return openmrsFetch(`${restBaseUrl}/obs/${observationUuid}`, {
|
|
261
358
|
method: 'POST',
|
|
@@ -289,6 +386,22 @@ function createObservation(order: Order, groupMembers = null, value = null, stat
|
|
|
289
386
|
};
|
|
290
387
|
}
|
|
291
388
|
|
|
389
|
+
function createObservationByConcept(
|
|
390
|
+
concept: LabOrderConcept,
|
|
391
|
+
order: Order,
|
|
392
|
+
groupMembers = null,
|
|
393
|
+
value = null,
|
|
394
|
+
status: string,
|
|
395
|
+
) {
|
|
396
|
+
return {
|
|
397
|
+
concept: { uuid: concept.uuid },
|
|
398
|
+
status: status,
|
|
399
|
+
order: { uuid: order.uuid },
|
|
400
|
+
...(groupMembers && groupMembers.length > 0 && { groupMembers }),
|
|
401
|
+
...(value !== null && value !== undefined && { value }),
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
292
405
|
function getValue(concept: LabOrderConcept, values: Record<string, unknown>) {
|
|
293
406
|
const { datatype, uuid } = concept;
|
|
294
407
|
const value = values[uuid];
|
package/src/order-basket/general-order-type/general-order-form/general-order-form.component.tsx
CHANGED
|
@@ -19,12 +19,11 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
19
19
|
import { z } from 'zod';
|
|
20
20
|
import {
|
|
21
21
|
priorityOptions,
|
|
22
|
+
type DefaultPatientWorkspaceProps,
|
|
22
23
|
type OrderBasketItem,
|
|
23
24
|
type OrderUrgency,
|
|
24
25
|
useOrderBasket,
|
|
25
26
|
useOrderType,
|
|
26
|
-
postOrder,
|
|
27
|
-
useMutatePatientOrders,
|
|
28
27
|
} from '@openmrs/esm-patient-common-lib';
|
|
29
28
|
import {
|
|
30
29
|
useLayoutType,
|
|
@@ -32,40 +31,37 @@ import {
|
|
|
32
31
|
useConfig,
|
|
33
32
|
ExtensionSlot,
|
|
34
33
|
OpenmrsDatePicker,
|
|
35
|
-
|
|
36
|
-
showSnackbar,
|
|
37
|
-
useAbortController,
|
|
34
|
+
launchWorkspace,
|
|
38
35
|
} from '@openmrs/esm-framework';
|
|
39
36
|
import { ordersEqual, prepOrderPostData } from '../resources';
|
|
40
37
|
import { type ConfigObject } from '../../../config-schema';
|
|
41
38
|
import styles from './general-order-form.scss';
|
|
42
39
|
|
|
43
|
-
export interface OrderFormProps {
|
|
40
|
+
export interface OrderFormProps extends DefaultPatientWorkspaceProps {
|
|
44
41
|
initialOrder: OrderBasketItem;
|
|
45
42
|
orderTypeUuid: string;
|
|
46
|
-
|
|
47
|
-
setHasUnsavedChanges: (hasUnsavedChanges: boolean) => void;
|
|
48
|
-
patient: fhir.Patient;
|
|
43
|
+
orderableConceptSets: Array<string>;
|
|
49
44
|
}
|
|
50
45
|
|
|
51
46
|
// Designs:
|
|
52
47
|
// https://app.zeplin.io/project/60d5947dd636aebbd63dce4c/screen/640b06c440ee3f7af8747620
|
|
53
48
|
// https://app.zeplin.io/project/60d5947dd636aebbd63dce4c/screen/640b06d286e0aa7b0316db4a
|
|
54
49
|
export function OrderForm({
|
|
55
|
-
patient,
|
|
56
50
|
initialOrder,
|
|
57
|
-
orderTypeUuid,
|
|
58
51
|
closeWorkspace,
|
|
59
|
-
|
|
52
|
+
closeWorkspaceWithSavedChanges,
|
|
53
|
+
promptBeforeClosing,
|
|
54
|
+
patient,
|
|
55
|
+
orderTypeUuid,
|
|
60
56
|
}: OrderFormProps) {
|
|
61
57
|
const { t } = useTranslation();
|
|
62
58
|
const isTablet = useLayoutType() === 'tablet';
|
|
63
59
|
const session = useSession();
|
|
64
|
-
const
|
|
60
|
+
const isEditing = useMemo(() => initialOrder && initialOrder.action === 'REVISE', [initialOrder]);
|
|
61
|
+
const { orders, setOrders } = useOrderBasket<OrderBasketItem>(patient, orderTypeUuid, prepOrderPostData);
|
|
65
62
|
const [showErrorNotification, setShowErrorNotification] = useState(false);
|
|
66
63
|
const { orderType } = useOrderType(orderTypeUuid);
|
|
67
64
|
const config = useConfig<ConfigObject>();
|
|
68
|
-
const { mutate: mutateOrders } = useMutatePatientOrders(patient.id);
|
|
69
65
|
|
|
70
66
|
const OrderFormSchema = useMemo(
|
|
71
67
|
() =>
|
|
@@ -112,7 +108,7 @@ export function OrderForm({
|
|
|
112
108
|
return menu?.item?.value?.toLowerCase().includes(menu?.inputValue?.toLowerCase());
|
|
113
109
|
}, []);
|
|
114
110
|
|
|
115
|
-
const
|
|
111
|
+
const handleFormSubmission = useCallback(
|
|
116
112
|
(data: OrderBasketItem) => {
|
|
117
113
|
const finalizedOrder: OrderBasketItem = {
|
|
118
114
|
...initialOrder,
|
|
@@ -135,55 +131,22 @@ export function OrderForm({
|
|
|
135
131
|
|
|
136
132
|
setOrders(newOrders);
|
|
137
133
|
|
|
138
|
-
|
|
134
|
+
closeWorkspaceWithSavedChanges({
|
|
135
|
+
onWorkspaceClose: () => launchWorkspace('order-basket'),
|
|
136
|
+
closeWorkspaceGroup: false,
|
|
137
|
+
});
|
|
139
138
|
},
|
|
140
|
-
[orders, setOrders, session?.currentProvider?.uuid,
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
const submitDrugOrderToServer = useCallback(
|
|
144
|
-
(data: OrderBasketItem) => {
|
|
145
|
-
const finalizedOrder: OrderBasketItem = {
|
|
146
|
-
...initialOrder,
|
|
147
|
-
...data,
|
|
148
|
-
};
|
|
149
|
-
finalizedOrder.orderer = session.currentProvider.uuid;
|
|
150
|
-
|
|
151
|
-
postOrder(prepOrderPostData(finalizedOrder, patient.id, finalizedOrder?.encounterUuid))
|
|
152
|
-
.then(() => {
|
|
153
|
-
clearOrders();
|
|
154
|
-
mutateOrders();
|
|
155
|
-
showSnackbar({
|
|
156
|
-
isLowContrast: false,
|
|
157
|
-
kind: 'success',
|
|
158
|
-
title: t('successSavingDrugOrder', 'Order saved'),
|
|
159
|
-
});
|
|
160
|
-
closeWorkspace({ discardUnsavedChanges: true });
|
|
161
|
-
})
|
|
162
|
-
.catch((error) => {
|
|
163
|
-
showSnackbar({
|
|
164
|
-
isLowContrast: false,
|
|
165
|
-
kind: 'error',
|
|
166
|
-
title: t('errorSavingDrugOrder', 'Error saving order'),
|
|
167
|
-
subtitle: error,
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
},
|
|
171
|
-
[clearOrders, closeWorkspace, initialOrder, mutateOrders, patient.id, session.currentProvider.uuid, t],
|
|
139
|
+
[orders, setOrders, session?.currentProvider?.uuid, closeWorkspaceWithSavedChanges, initialOrder],
|
|
172
140
|
);
|
|
173
141
|
|
|
174
142
|
const cancelOrder = useCallback(() => {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
143
|
+
setOrders(orders.filter((order) => order.concept.uuid !== defaultValues.concept.conceptUuid));
|
|
144
|
+
closeWorkspace({
|
|
145
|
+
onWorkspaceClose: () => launchWorkspace('order-basket'),
|
|
146
|
+
closeWorkspaceGroup: false,
|
|
179
147
|
});
|
|
180
148
|
}, [closeWorkspace, orders, setOrders, defaultValues]);
|
|
181
149
|
|
|
182
|
-
const closeModifyOrderWorkspace = useCallback(() => {
|
|
183
|
-
clearOrders();
|
|
184
|
-
closeWorkspace();
|
|
185
|
-
}, [clearOrders, closeWorkspace]);
|
|
186
|
-
|
|
187
150
|
const onError = (errors: FieldErrors<OrderBasketItem>) => {
|
|
188
151
|
if (errors) {
|
|
189
152
|
setShowErrorNotification(true);
|
|
@@ -201,24 +164,20 @@ export function OrderForm({
|
|
|
201
164
|
};
|
|
202
165
|
|
|
203
166
|
useEffect(() => {
|
|
204
|
-
|
|
205
|
-
}, [isDirty,
|
|
167
|
+
promptBeforeClosing(() => isDirty);
|
|
168
|
+
}, [isDirty, promptBeforeClosing]);
|
|
206
169
|
|
|
207
170
|
const responsiveSize = isTablet ? 'lg' : 'sm';
|
|
208
171
|
|
|
209
172
|
return (
|
|
210
173
|
<>
|
|
211
|
-
<Form
|
|
212
|
-
className={styles.orderForm}
|
|
213
|
-
onSubmit={handleSubmit(initialOrder?.action == 'REVISE' ? submitDrugOrderToServer : saveOrderToBasket, onError)}
|
|
214
|
-
id="drugOrderForm"
|
|
215
|
-
>
|
|
174
|
+
<Form className={styles.orderForm} onSubmit={handleSubmit(handleFormSubmission, onError)} id="drugOrderForm">
|
|
216
175
|
<div className={styles.form}>
|
|
217
176
|
<ExtensionSlot name="top-of-lab-order-form-slot" state={{ order: initialOrder }} />
|
|
218
177
|
<Grid className={styles.gridRow}>
|
|
219
178
|
<Column lg={16} md={8} sm={4}>
|
|
220
179
|
<InputWrapper>
|
|
221
|
-
<
|
|
180
|
+
<span className={styles.testTypeLabel}>{t('testType', 'Test type')}</span>
|
|
222
181
|
<p className={styles.testType}>{initialOrder?.concept?.display}</p>
|
|
223
182
|
</InputWrapper>
|
|
224
183
|
</Column>
|
|
@@ -335,12 +294,7 @@ export function OrderForm({
|
|
|
335
294
|
<ButtonSet
|
|
336
295
|
className={classNames(styles.buttonSet, isTablet ? styles.tabletButtonSet : styles.desktopButtonSet)}
|
|
337
296
|
>
|
|
338
|
-
<Button
|
|
339
|
-
className={styles.button}
|
|
340
|
-
kind="secondary"
|
|
341
|
-
onClick={initialOrder?.action == 'REVISE' ? closeModifyOrderWorkspace : cancelOrder}
|
|
342
|
-
size="xl"
|
|
343
|
-
>
|
|
297
|
+
<Button className={styles.button} kind="secondary" onClick={cancelOrder} size="xl">
|
|
344
298
|
{t('discard', 'Discard')}
|
|
345
299
|
</Button>
|
|
346
300
|
<Button className={styles.button} kind="primary" size="xl" type="submit">
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import React, { type ComponentProps, useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { Button, Tile } from '@carbon/react';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
AddIcon,
|
|
6
|
+
ChevronDownIcon,
|
|
7
|
+
ChevronUpIcon,
|
|
8
|
+
type DefaultWorkspaceProps,
|
|
9
|
+
MaybeIcon,
|
|
10
|
+
useLayoutType,
|
|
11
|
+
launchWorkspace,
|
|
12
|
+
} from '@openmrs/esm-framework';
|
|
5
13
|
import { useTranslation } from 'react-i18next';
|
|
6
14
|
import { type OrderBasketItem, useOrderBasket, useOrderType } from '@openmrs/esm-patient-common-lib';
|
|
7
15
|
import { type OrderTypeDefinition } from '../../config-schema';
|
|
@@ -10,24 +18,11 @@ import OrderBasketItemTile from './order-basket-item-tile.component';
|
|
|
10
18
|
import styles from './general-order-panel.scss';
|
|
11
19
|
|
|
12
20
|
interface GeneralOrderTypeProps extends OrderTypeDefinition {
|
|
21
|
+
closeWorkspace: DefaultWorkspaceProps['closeWorkspace'];
|
|
13
22
|
patient: fhir.Patient;
|
|
14
|
-
orderTypeUuid: string;
|
|
15
|
-
launchGeneralOrderForm(orderTypeUuid: string, order?: OrderBasketItem): void;
|
|
16
23
|
}
|
|
17
24
|
|
|
18
|
-
|
|
19
|
-
* The extension is slotted into order-basket-slot in the main Order Basket workspace by default.
|
|
20
|
-
* It renders the "Add +" button for general orders, and lists pending general orders in the order basket.
|
|
21
|
-
*
|
|
22
|
-
* Designs: https://app.zeplin.io/project/60d59321e8100b0324762e05/screen/62c6bb9500e7671a618efa56
|
|
23
|
-
*/
|
|
24
|
-
const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
25
|
-
patient,
|
|
26
|
-
orderTypeUuid,
|
|
27
|
-
label,
|
|
28
|
-
icon,
|
|
29
|
-
launchGeneralOrderForm,
|
|
30
|
-
}) => {
|
|
25
|
+
const GeneralOrderType: React.FC<GeneralOrderTypeProps> = ({ patient, orderTypeUuid, closeWorkspace, label, icon }) => {
|
|
31
26
|
const { t } = useTranslation();
|
|
32
27
|
const isTablet = useLayoutType() === 'tablet';
|
|
33
28
|
const { orderType, isLoadingOrderType } = useOrderType(orderTypeUuid);
|
|
@@ -70,6 +65,29 @@ const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
|
70
65
|
};
|
|
71
66
|
}, [orders]);
|
|
72
67
|
|
|
68
|
+
const openConceptSearch = () => {
|
|
69
|
+
closeWorkspace({
|
|
70
|
+
ignoreChanges: true,
|
|
71
|
+
onWorkspaceClose: () =>
|
|
72
|
+
launchWorkspace('orderable-concept-workspace', {
|
|
73
|
+
orderTypeUuid,
|
|
74
|
+
}),
|
|
75
|
+
closeWorkspaceGroup: false,
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const openOrderForm = (order: OrderBasketItem) => {
|
|
80
|
+
closeWorkspace({
|
|
81
|
+
ignoreChanges: true,
|
|
82
|
+
onWorkspaceClose: () =>
|
|
83
|
+
launchWorkspace('orderable-concept-workspace', {
|
|
84
|
+
order,
|
|
85
|
+
orderTypeUuid,
|
|
86
|
+
}),
|
|
87
|
+
closeWorkspaceGroup: false,
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
|
|
73
91
|
const removeOrder = useCallback(
|
|
74
92
|
(order: OrderBasketItem) => {
|
|
75
93
|
const newOrders = [...orders];
|
|
@@ -102,7 +120,7 @@ const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
|
102
120
|
kind="ghost"
|
|
103
121
|
renderIcon={(props: ComponentProps<typeof AddIcon>) => <AddIcon size={16} {...props} />}
|
|
104
122
|
iconDescription={t('addMedication', 'Add medication')}
|
|
105
|
-
onClick={
|
|
123
|
+
onClick={openConceptSearch}
|
|
106
124
|
size={isTablet ? 'md' : 'sm'}
|
|
107
125
|
>
|
|
108
126
|
{t('add', 'Add')}
|
|
@@ -130,7 +148,7 @@ const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
|
130
148
|
<OrderBasketItemTile
|
|
131
149
|
key={`incomplete-${order.action}-${order.concept?.uuid}-${index}`}
|
|
132
150
|
orderBasketItem={order}
|
|
133
|
-
onItemClick={() =>
|
|
151
|
+
onItemClick={() => openOrderForm(order)}
|
|
134
152
|
onRemoveClick={() => removeOrder(order)}
|
|
135
153
|
/>
|
|
136
154
|
))}
|
|
@@ -142,7 +160,7 @@ const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
|
142
160
|
<OrderBasketItemTile
|
|
143
161
|
key={`new-${order.action}-${order.concept?.uuid}-${index}`}
|
|
144
162
|
orderBasketItem={order}
|
|
145
|
-
onItemClick={() =>
|
|
163
|
+
onItemClick={() => openOrderForm(order)}
|
|
146
164
|
onRemoveClick={() => removeOrder(order)}
|
|
147
165
|
/>
|
|
148
166
|
))}
|
|
@@ -155,7 +173,7 @@ const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
|
155
173
|
<OrderBasketItemTile
|
|
156
174
|
key={`renewed-${item.action}-${item.concept?.uuid}-${index}`}
|
|
157
175
|
orderBasketItem={item}
|
|
158
|
-
onItemClick={() =>
|
|
176
|
+
onItemClick={() => openOrderForm(item)}
|
|
159
177
|
onRemoveClick={() => removeOrder(item)}
|
|
160
178
|
/>
|
|
161
179
|
))}
|
|
@@ -168,7 +186,7 @@ const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
|
168
186
|
<OrderBasketItemTile
|
|
169
187
|
key={`revised-${item.action}-${item.concept?.uuid}-${index}`}
|
|
170
188
|
orderBasketItem={item}
|
|
171
|
-
onItemClick={() =>
|
|
189
|
+
onItemClick={() => openOrderForm(item)}
|
|
172
190
|
onRemoveClick={() => removeOrder(item)}
|
|
173
191
|
/>
|
|
174
192
|
))}
|
|
@@ -181,7 +199,7 @@ const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
|
181
199
|
<OrderBasketItemTile
|
|
182
200
|
key={`discontinued-${item.action}-${item.concept?.uuid}-${index}`}
|
|
183
201
|
orderBasketItem={item}
|
|
184
|
-
onItemClick={() =>
|
|
202
|
+
onItemClick={() => openOrderForm(item)}
|
|
185
203
|
onRemoveClick={() => removeOrder(item)}
|
|
186
204
|
/>
|
|
187
205
|
))}
|
|
@@ -193,4 +211,4 @@ const GeneralOrderPanel: React.FC<GeneralOrderTypeProps> = ({
|
|
|
193
211
|
);
|
|
194
212
|
};
|
|
195
213
|
|
|
196
|
-
export default
|
|
214
|
+
export default GeneralOrderType;
|