@openmrs/esm-patient-orders-app 11.3.1-pre.9452 → 11.3.1-pre.9458
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 +14 -14
- package/dist/1253.js +1 -0
- package/dist/1253.js.map +1 -0
- package/dist/375.js +1 -0
- package/dist/375.js.map +1 -0
- package/dist/4300.js +1 -1
- package/dist/4341.js +1 -0
- package/dist/4341.js.map +1 -0
- package/dist/4558.js +1 -0
- package/dist/4558.js.map +1 -0
- package/dist/5937.js +1 -0
- package/dist/5937.js.map +1 -0
- package/dist/6473.js +1 -0
- package/dist/6473.js.map +1 -0
- package/dist/6483.js +1 -0
- package/dist/6483.js.map +1 -0
- package/dist/8376.js +1 -0
- package/dist/8376.js.map +1 -0
- package/dist/8389.js +1 -0
- package/dist/8389.js.map +1 -0
- package/dist/8416.js +1 -0
- package/dist/8416.js.map +1 -0
- package/dist/8894.js +1 -0
- package/dist/8894.js.map +1 -0
- 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 +230 -107
- 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 +0 -25
- package/src/components/order-details-table.component.tsx +53 -40
- package/src/index.ts +19 -11
- package/src/lab-results/{lab-results-form.component.tsx → exported-lab-results-form.workspace.tsx} +105 -108
- package/src/lab-results/lab-results-form.test.tsx +24 -38
- package/src/lab-results/lab-results-form.workspace.tsx +26 -0
- package/src/order-basket/exported-order-basket.workspace.tsx +59 -0
- package/src/order-basket/general-order-type/{orderable-concept-search/orderable-concept-search.workspace.tsx → add-general-order/add-general-order.component.tsx} +78 -83
- package/src/order-basket/general-order-type/add-general-order/add-general-order.workspace.tsx +38 -0
- package/src/order-basket/general-order-type/add-general-order/exported-add-general-order.workspace.tsx +35 -0
- package/src/order-basket/general-order-type/{orderable-concept-search → add-general-order}/search-results.component.tsx +15 -14
- package/src/order-basket/general-order-type/general-order-form/general-order-form.component.tsx +70 -25
- package/src/order-basket/general-order-type/{general-order-type.component.tsx → general-order-panel.component.tsx} +23 -41
- package/src/order-basket/general-order-type/resources.ts +3 -2
- package/src/order-basket/order-basket.component.tsx +213 -0
- package/src/order-basket/order-basket.workspace.tsx +42 -252
- package/src/order-basket-action-button/order-basket-action-button.component.tsx +35 -0
- package/src/order-basket-action-button/order-basket-action-button.test.tsx +27 -36
- package/src/routes.json +17 -25
- package/src/utils/index.ts +15 -3
- package/translations/en.json +4 -20
- package/dist/1571.js +0 -1
- package/dist/1571.js.map +0 -1
- package/dist/2717.js +0 -1
- package/dist/2717.js.map +0 -1
- package/dist/4937.js +0 -1
- package/dist/4937.js.map +0 -1
- package/dist/8625.js +0 -1
- package/dist/8625.js.map +0 -1
- package/dist/8803.js +0 -1
- package/dist/8803.js.map +0 -1
- package/dist/8960.js +0 -1
- package/dist/8960.js.map +0 -1
- package/src/order-basket-action-button/order-basket-action-button.extension.tsx +0 -31
- package/src/order-cancellation-form/cancel-order-form.component.tsx +0 -180
- package/src/order-cancellation-form/cancel-order-form.scss +0 -87
- package/src/order-cancellation-form/cancel-order.resource.tsx +0 -15
- /package/src/order-basket/general-order-type/{orderable-concept-search → add-general-order}/orderable-concept-search.scss +0 -0
- /package/src/order-basket/general-order-type/{orderable-concept-search → add-general-order}/search-results.scss +0 -0
|
@@ -1,53 +1,40 @@
|
|
|
1
|
-
import React, { type ComponentProps, useCallback,
|
|
1
|
+
import React, { type ComponentProps, useCallback, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { Button, Search } from '@carbon/react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import {
|
|
5
5
|
ArrowLeftIcon,
|
|
6
|
-
launchWorkspace,
|
|
7
6
|
ResponsiveWrapper,
|
|
8
7
|
useConfig,
|
|
9
8
|
useDebounce,
|
|
10
9
|
useLayoutType,
|
|
11
|
-
type
|
|
10
|
+
type Visit,
|
|
11
|
+
Workspace2,
|
|
12
|
+
type Workspace2DefinitionProps,
|
|
12
13
|
} from '@openmrs/esm-framework';
|
|
13
|
-
import {
|
|
14
|
-
type DefaultPatientWorkspaceProps,
|
|
15
|
-
type OrderBasketItem,
|
|
16
|
-
useOrderBasket,
|
|
17
|
-
useOrderType,
|
|
18
|
-
} from '@openmrs/esm-patient-common-lib';
|
|
14
|
+
import { type OrderBasketItem, useOrderBasket, useOrderType } from '@openmrs/esm-patient-common-lib';
|
|
19
15
|
import { OrderForm } from '../general-order-form/general-order-form.component';
|
|
20
16
|
import { prepOrderPostData } from '../resources';
|
|
21
17
|
import { type ConfigObject } from '../../../config-schema';
|
|
22
18
|
import OrderableConceptSearchResults from './search-results.component';
|
|
23
19
|
import styles from './orderable-concept-search.scss';
|
|
24
20
|
|
|
25
|
-
interface
|
|
26
|
-
|
|
21
|
+
interface AddGeneralOrderProps {
|
|
22
|
+
initialOrder: OrderBasketItem;
|
|
27
23
|
orderTypeUuid: string;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
export const careSettingUuid = '6f0c9a92-6f24-11e3-af88-005056821db0';
|
|
33
|
-
|
|
34
|
-
type DrugsOrOrders = Pick<OrderBasketItem, 'action' | 'concept'>;
|
|
35
|
-
|
|
36
|
-
export function ordersEqual(order1: DrugsOrOrders, order2: DrugsOrOrders) {
|
|
37
|
-
return order1.action === order2.action && order1.concept.uuid === order2.concept.uuid;
|
|
24
|
+
patient: fhir.Patient;
|
|
25
|
+
visitContext: Visit;
|
|
26
|
+
closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
|
|
38
27
|
}
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
/**
|
|
30
|
+
* This workspace displays the drug order form for adding or editing a general order.
|
|
31
|
+
*/
|
|
32
|
+
const AddGeneralOrder: React.FC<AddGeneralOrderProps> = ({
|
|
33
|
+
initialOrder,
|
|
42
34
|
orderTypeUuid,
|
|
43
|
-
closeWorkspace,
|
|
44
|
-
closeWorkspaceWithSavedChanges,
|
|
45
|
-
promptBeforeClosing,
|
|
46
|
-
setTitle,
|
|
47
|
-
patientUuid,
|
|
48
35
|
patient,
|
|
49
36
|
visitContext,
|
|
50
|
-
|
|
37
|
+
closeWorkspace,
|
|
51
38
|
}) => {
|
|
52
39
|
const { t } = useTranslation();
|
|
53
40
|
const isTablet = useLayoutType() === 'tablet';
|
|
@@ -55,16 +42,23 @@ const OrderableConceptSearchWorkspace: React.FC<OrderableConceptSearchWorkspaceP
|
|
|
55
42
|
const { orderTypes } = useConfig<ConfigObject>();
|
|
56
43
|
const [currentOrder, setCurrentOrder] = useState(initialOrder);
|
|
57
44
|
const { orderType } = useOrderType(orderTypeUuid);
|
|
45
|
+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
|
58
46
|
|
|
59
|
-
|
|
47
|
+
const title = useMemo(() => {
|
|
60
48
|
if (orderType) {
|
|
61
|
-
|
|
62
|
-
t(`
|
|
49
|
+
if (initialOrder?.action == 'REVISE') {
|
|
50
|
+
return t(`editOrderableForOrderType`, 'Edit {{orderTypeDisplay}}', {
|
|
63
51
|
orderTypeDisplay: orderType.display.toLocaleLowerCase(),
|
|
64
|
-
})
|
|
65
|
-
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
return t(`addOrderableForOrderType`, 'Add {{orderTypeDisplay}}', {
|
|
55
|
+
orderTypeDisplay: orderType.display.toLocaleLowerCase(),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
return '';
|
|
66
60
|
}
|
|
67
|
-
}, [orderType, t,
|
|
61
|
+
}, [orderType, t, initialOrder?.action]);
|
|
68
62
|
|
|
69
63
|
const orderableConceptSets = useMemo(
|
|
70
64
|
() => orderTypes.find((orderType) => orderType.orderTypeUuid === orderTypeUuid).orderableConceptSets,
|
|
@@ -72,10 +66,7 @@ const OrderableConceptSearchWorkspace: React.FC<OrderableConceptSearchWorkspaceP
|
|
|
72
66
|
);
|
|
73
67
|
|
|
74
68
|
const cancelDrugOrder = useCallback(() => {
|
|
75
|
-
closeWorkspace(
|
|
76
|
-
onWorkspaceClose: () => launchWorkspace('order-basket'),
|
|
77
|
-
closeWorkspaceGroup: false,
|
|
78
|
-
});
|
|
69
|
+
closeWorkspace();
|
|
79
70
|
}, [closeWorkspace]);
|
|
80
71
|
|
|
81
72
|
const openOrderForm = useCallback(
|
|
@@ -91,53 +82,51 @@ const OrderableConceptSearchWorkspace: React.FC<OrderableConceptSearchWorkspaceP
|
|
|
91
82
|
);
|
|
92
83
|
|
|
93
84
|
return (
|
|
94
|
-
<
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
/>
|
|
130
|
-
)}
|
|
131
|
-
</div>
|
|
85
|
+
<Workspace2 title={title} hasUnsavedChanges={hasUnsavedChanges}>
|
|
86
|
+
<div className={styles.workspaceWrapper}>
|
|
87
|
+
{!isTablet && (
|
|
88
|
+
<div className={styles.backButton}>
|
|
89
|
+
<Button
|
|
90
|
+
iconDescription="Return to order basket"
|
|
91
|
+
kind="ghost"
|
|
92
|
+
onClick={cancelDrugOrder}
|
|
93
|
+
renderIcon={(props: ComponentProps<typeof ArrowLeftIcon>) => <ArrowLeftIcon size={24} {...props} />}
|
|
94
|
+
size="sm"
|
|
95
|
+
>
|
|
96
|
+
<span>{t('backToOrderBasket', 'Back to order basket')}</span>
|
|
97
|
+
</Button>
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
|
+
{currentOrder ? (
|
|
101
|
+
<OrderForm
|
|
102
|
+
initialOrder={currentOrder}
|
|
103
|
+
closeWorkspace={closeWorkspace}
|
|
104
|
+
setHasUnsavedChanges={setHasUnsavedChanges}
|
|
105
|
+
orderTypeUuid={orderTypeUuid}
|
|
106
|
+
patient={patient}
|
|
107
|
+
/>
|
|
108
|
+
) : (
|
|
109
|
+
<ConceptSearch
|
|
110
|
+
openOrderForm={openOrderForm}
|
|
111
|
+
closeWorkspace={closeWorkspace}
|
|
112
|
+
orderableConceptSets={orderableConceptSets}
|
|
113
|
+
orderTypeUuid={orderTypeUuid}
|
|
114
|
+
patient={patient}
|
|
115
|
+
visit={visitContext}
|
|
116
|
+
/>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
</Workspace2>
|
|
132
120
|
);
|
|
133
121
|
};
|
|
134
122
|
|
|
135
123
|
interface ConceptSearchProps {
|
|
136
|
-
closeWorkspace:
|
|
124
|
+
closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
|
|
137
125
|
openOrderForm: (search: OrderBasketItem) => void;
|
|
138
126
|
orderTypeUuid: string;
|
|
139
127
|
orderableConceptSets: Array<string>;
|
|
140
128
|
patient: fhir.Patient;
|
|
129
|
+
visit: Visit;
|
|
141
130
|
}
|
|
142
131
|
|
|
143
132
|
function ConceptSearch({
|
|
@@ -146,6 +135,7 @@ function ConceptSearch({
|
|
|
146
135
|
openOrderForm,
|
|
147
136
|
orderableConceptSets,
|
|
148
137
|
patient,
|
|
138
|
+
visit,
|
|
149
139
|
}: ConceptSearchProps) {
|
|
150
140
|
const { t } = useTranslation();
|
|
151
141
|
const { orderType } = useOrderType(orderTypeUuid);
|
|
@@ -155,9 +145,7 @@ function ConceptSearch({
|
|
|
155
145
|
const searchInputRef = useRef(null);
|
|
156
146
|
|
|
157
147
|
const cancelDrugOrder = useCallback(() => {
|
|
158
|
-
closeWorkspace(
|
|
159
|
-
onWorkspaceClose: () => launchWorkspace('order-basket'),
|
|
160
|
-
});
|
|
148
|
+
closeWorkspace();
|
|
161
149
|
}, [closeWorkspace]);
|
|
162
150
|
|
|
163
151
|
const focusAndClearSearchInput = () => {
|
|
@@ -191,11 +179,12 @@ function ConceptSearch({
|
|
|
191
179
|
searchTerm={debouncedSearchTerm}
|
|
192
180
|
openOrderForm={openOrderForm}
|
|
193
181
|
focusAndClearSearchInput={focusAndClearSearchInput}
|
|
194
|
-
closeWorkspace={closeWorkspace}
|
|
195
182
|
orderTypeUuid={orderTypeUuid}
|
|
196
183
|
cancelOrder={() => {}}
|
|
197
184
|
orderableConceptSets={orderableConceptSets}
|
|
185
|
+
closeWorkspace={closeWorkspace}
|
|
198
186
|
patient={patient}
|
|
187
|
+
visit={visit}
|
|
199
188
|
/>
|
|
200
189
|
{isTablet && (
|
|
201
190
|
<div className={styles.separatorContainer}>
|
|
@@ -209,4 +198,10 @@ function ConceptSearch({
|
|
|
209
198
|
);
|
|
210
199
|
}
|
|
211
200
|
|
|
212
|
-
|
|
201
|
+
type DrugsOrOrders = Pick<OrderBasketItem, 'action' | 'concept'>;
|
|
202
|
+
|
|
203
|
+
function ordersEqual(order1: DrugsOrOrders, order2: DrugsOrOrders) {
|
|
204
|
+
return order1.action === order2.action && order1.concept.uuid === order2.concept.uuid;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export default AddGeneralOrder;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
type OrderBasketItem,
|
|
4
|
+
type OrderBasketWindowProps,
|
|
5
|
+
type PatientWorkspace2DefinitionProps,
|
|
6
|
+
} from '@openmrs/esm-patient-common-lib';
|
|
7
|
+
import AddGeneralOrder from './add-general-order.component';
|
|
8
|
+
|
|
9
|
+
interface OrderableConceptSearchWorkspaceProps {
|
|
10
|
+
order: OrderBasketItem;
|
|
11
|
+
orderTypeUuid: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* This workspace displays the order form for adding or editing a general order.
|
|
16
|
+
*
|
|
17
|
+
* This workspace must only be used within the patient chart.
|
|
18
|
+
* @see exported-add-general-order.workspace.tsx
|
|
19
|
+
*/
|
|
20
|
+
const AddGeneralOrderWorkspace: React.FC<
|
|
21
|
+
PatientWorkspace2DefinitionProps<OrderableConceptSearchWorkspaceProps, OrderBasketWindowProps>
|
|
22
|
+
> = ({
|
|
23
|
+
workspaceProps: { order: initialOrder, orderTypeUuid },
|
|
24
|
+
groupProps: { patient, visitContext, mutateVisitContext },
|
|
25
|
+
closeWorkspace,
|
|
26
|
+
}) => {
|
|
27
|
+
return (
|
|
28
|
+
<AddGeneralOrder
|
|
29
|
+
initialOrder={initialOrder}
|
|
30
|
+
orderTypeUuid={orderTypeUuid}
|
|
31
|
+
patient={patient}
|
|
32
|
+
visitContext={visitContext}
|
|
33
|
+
closeWorkspace={closeWorkspace}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default AddGeneralOrderWorkspace;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type Workspace2DefinitionProps } from '@openmrs/esm-framework';
|
|
3
|
+
import { type ExportedOrderBasketWindowProps, type OrderBasketItem } from '@openmrs/esm-patient-common-lib';
|
|
4
|
+
import AddGeneralOrder from './add-general-order.component';
|
|
5
|
+
|
|
6
|
+
interface OrderableConceptSearchWorkspaceProps {
|
|
7
|
+
order: OrderBasketItem;
|
|
8
|
+
orderTypeUuid: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This workspace displays the drug order form for adding or editing a general order.
|
|
13
|
+
*
|
|
14
|
+
* This workspace is meant for use outside the patient chart.
|
|
15
|
+
* @see exported-add-general-order.workspace.tsx
|
|
16
|
+
*/
|
|
17
|
+
const ExportedAddGeneralOrderWorkspace: React.FC<
|
|
18
|
+
Workspace2DefinitionProps<OrderableConceptSearchWorkspaceProps, ExportedOrderBasketWindowProps, {}>
|
|
19
|
+
> = ({
|
|
20
|
+
workspaceProps: { order: initialOrder, orderTypeUuid },
|
|
21
|
+
windowProps: { patient, visitContext },
|
|
22
|
+
closeWorkspace,
|
|
23
|
+
}) => {
|
|
24
|
+
return (
|
|
25
|
+
<AddGeneralOrder
|
|
26
|
+
initialOrder={initialOrder}
|
|
27
|
+
orderTypeUuid={orderTypeUuid}
|
|
28
|
+
patient={patient}
|
|
29
|
+
visitContext={visitContext}
|
|
30
|
+
closeWorkspace={closeWorkspace}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default ExportedAddGeneralOrderWorkspace;
|
|
@@ -4,12 +4,12 @@ import { ShoppingCartArrowUp } from '@carbon/react/icons';
|
|
|
4
4
|
import { Tile, Button, SkeletonText, ButtonSkeleton } from '@carbon/react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import {
|
|
7
|
+
type Workspace2DefinitionProps,
|
|
7
8
|
ArrowRightIcon,
|
|
8
|
-
type DefaultWorkspaceProps,
|
|
9
9
|
ShoppingCartArrowDownIcon,
|
|
10
10
|
useLayoutType,
|
|
11
11
|
useSession,
|
|
12
|
-
|
|
12
|
+
type Visit,
|
|
13
13
|
} from '@openmrs/esm-framework';
|
|
14
14
|
import {
|
|
15
15
|
useOrderBasket,
|
|
@@ -27,8 +27,9 @@ interface OrderableConceptSearchResultsProps {
|
|
|
27
27
|
cancelOrder: () => void;
|
|
28
28
|
orderableConceptSets: Array<string>;
|
|
29
29
|
orderTypeUuid: string;
|
|
30
|
-
closeWorkspace:
|
|
30
|
+
closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
|
|
31
31
|
patient: fhir.Patient;
|
|
32
|
+
visit: Visit;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
const OrderableConceptSearchResults: React.FC<OrderableConceptSearchResultsProps> = ({
|
|
@@ -40,6 +41,7 @@ const OrderableConceptSearchResults: React.FC<OrderableConceptSearchResultsProps
|
|
|
40
41
|
orderTypeUuid,
|
|
41
42
|
closeWorkspace,
|
|
42
43
|
patient,
|
|
44
|
+
visit,
|
|
43
45
|
}) => {
|
|
44
46
|
const { t } = useTranslation();
|
|
45
47
|
const isTablet = useLayoutType() === 'tablet';
|
|
@@ -92,6 +94,7 @@ const OrderableConceptSearchResults: React.FC<OrderableConceptSearchResultsProps
|
|
|
92
94
|
orderTypeUuid={orderTypeUuid}
|
|
93
95
|
closeWorkspace={closeWorkspace}
|
|
94
96
|
patient={patient}
|
|
97
|
+
visit={visit}
|
|
95
98
|
/>
|
|
96
99
|
))}
|
|
97
100
|
</div>
|
|
@@ -156,8 +159,9 @@ interface TestTypeSearchResultItemProps {
|
|
|
156
159
|
concept: OrderableConcept;
|
|
157
160
|
openOrderForm: (searchResult: OrderBasketItem) => void;
|
|
158
161
|
orderTypeUuid: string;
|
|
159
|
-
closeWorkspace:
|
|
162
|
+
closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
|
|
160
163
|
patient: fhir.Patient;
|
|
164
|
+
visit: Visit;
|
|
161
165
|
}
|
|
162
166
|
|
|
163
167
|
const TestTypeSearchResultItem: React.FC<TestTypeSearchResultItemProps> = ({
|
|
@@ -166,6 +170,7 @@ const TestTypeSearchResultItem: React.FC<TestTypeSearchResultItemProps> = ({
|
|
|
166
170
|
orderTypeUuid,
|
|
167
171
|
closeWorkspace,
|
|
168
172
|
patient,
|
|
173
|
+
visit,
|
|
169
174
|
}) => {
|
|
170
175
|
const { t } = useTranslation();
|
|
171
176
|
const isTablet = useLayoutType() === 'tablet';
|
|
@@ -178,22 +183,18 @@ const TestTypeSearchResultItem: React.FC<TestTypeSearchResultItemProps> = ({
|
|
|
178
183
|
);
|
|
179
184
|
|
|
180
185
|
const createOrderBasketItem = useCallback(
|
|
181
|
-
(testType: OrderableConcept) => {
|
|
182
|
-
return createEmptyOrder(testType, session.currentProvider?.uuid);
|
|
186
|
+
(testType: OrderableConcept, visit: Visit) => {
|
|
187
|
+
return createEmptyOrder(testType, session.currentProvider?.uuid, visit);
|
|
183
188
|
},
|
|
184
189
|
[session.currentProvider.uuid],
|
|
185
190
|
);
|
|
186
191
|
|
|
187
192
|
const addToBasket = useCallback(() => {
|
|
188
|
-
const orderBasketItem = createOrderBasketItem(concept);
|
|
193
|
+
const orderBasketItem = createOrderBasketItem(concept, visit);
|
|
189
194
|
orderBasketItem.isOrderIncomplete = true;
|
|
190
195
|
setOrders([...orders, orderBasketItem]);
|
|
191
|
-
closeWorkspace({
|
|
192
|
-
|
|
193
|
-
onWorkspaceClose: () => launchWorkspace('order-basket'),
|
|
194
|
-
closeWorkspaceGroup: false,
|
|
195
|
-
});
|
|
196
|
-
}, [orders, setOrders, createOrderBasketItem, concept, closeWorkspace]);
|
|
196
|
+
closeWorkspace({ discardUnsavedChanges: true });
|
|
197
|
+
}, [orders, setOrders, createOrderBasketItem, concept, closeWorkspace, visit]);
|
|
197
198
|
|
|
198
199
|
const removeFromBasket = useCallback(() => {
|
|
199
200
|
setOrders(orders.filter((order) => order?.concept?.uuid !== concept?.uuid));
|
|
@@ -232,7 +233,7 @@ const TestTypeSearchResultItem: React.FC<TestTypeSearchResultItemProps> = ({
|
|
|
232
233
|
<Button
|
|
233
234
|
kind="ghost"
|
|
234
235
|
renderIcon={(props: ComponentProps<typeof ArrowRightIcon>) => <ArrowRightIcon size={16} {...props} />}
|
|
235
|
-
onClick={() => openOrderForm(createOrderBasketItem(concept))}
|
|
236
|
+
onClick={() => openOrderForm(createOrderBasketItem(concept, visit))}
|
|
236
237
|
>
|
|
237
238
|
{t('goToDrugOrderForm', 'Order form')}
|
|
238
239
|
</Button>
|
package/src/order-basket/general-order-type/general-order-form/general-order-form.component.tsx
CHANGED
|
@@ -19,11 +19,12 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
19
19
|
import { z } from 'zod';
|
|
20
20
|
import {
|
|
21
21
|
priorityOptions,
|
|
22
|
-
type DefaultPatientWorkspaceProps,
|
|
23
22
|
type OrderBasketItem,
|
|
24
23
|
type OrderUrgency,
|
|
25
24
|
useOrderBasket,
|
|
26
25
|
useOrderType,
|
|
26
|
+
postOrder,
|
|
27
|
+
useMutatePatientOrders,
|
|
27
28
|
} from '@openmrs/esm-patient-common-lib';
|
|
28
29
|
import {
|
|
29
30
|
useLayoutType,
|
|
@@ -31,37 +32,39 @@ import {
|
|
|
31
32
|
useConfig,
|
|
32
33
|
ExtensionSlot,
|
|
33
34
|
OpenmrsDatePicker,
|
|
34
|
-
|
|
35
|
+
type Workspace2DefinitionProps,
|
|
36
|
+
showSnackbar,
|
|
35
37
|
} from '@openmrs/esm-framework';
|
|
36
38
|
import { ordersEqual, prepOrderPostData } from '../resources';
|
|
37
39
|
import { type ConfigObject } from '../../../config-schema';
|
|
38
40
|
import styles from './general-order-form.scss';
|
|
39
41
|
|
|
40
|
-
export interface OrderFormProps
|
|
42
|
+
export interface OrderFormProps {
|
|
41
43
|
initialOrder: OrderBasketItem;
|
|
42
44
|
orderTypeUuid: string;
|
|
43
|
-
|
|
45
|
+
closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
|
|
46
|
+
setHasUnsavedChanges: (hasUnsavedChanges: boolean) => void;
|
|
47
|
+
patient: fhir.Patient;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
// Designs:
|
|
47
51
|
// https://app.zeplin.io/project/60d5947dd636aebbd63dce4c/screen/640b06c440ee3f7af8747620
|
|
48
52
|
// https://app.zeplin.io/project/60d5947dd636aebbd63dce4c/screen/640b06d286e0aa7b0316db4a
|
|
49
53
|
export function OrderForm({
|
|
50
|
-
initialOrder,
|
|
51
|
-
closeWorkspace,
|
|
52
|
-
closeWorkspaceWithSavedChanges,
|
|
53
|
-
promptBeforeClosing,
|
|
54
54
|
patient,
|
|
55
|
+
initialOrder,
|
|
55
56
|
orderTypeUuid,
|
|
57
|
+
closeWorkspace,
|
|
58
|
+
setHasUnsavedChanges,
|
|
56
59
|
}: OrderFormProps) {
|
|
57
60
|
const { t } = useTranslation();
|
|
58
61
|
const isTablet = useLayoutType() === 'tablet';
|
|
59
62
|
const session = useSession();
|
|
60
|
-
const
|
|
61
|
-
const { orders, setOrders } = useOrderBasket<OrderBasketItem>(patient, orderTypeUuid, prepOrderPostData);
|
|
63
|
+
const { orders, setOrders, clearOrders } = useOrderBasket<OrderBasketItem>(patient, orderTypeUuid, prepOrderPostData);
|
|
62
64
|
const [showErrorNotification, setShowErrorNotification] = useState(false);
|
|
63
65
|
const { orderType } = useOrderType(orderTypeUuid);
|
|
64
66
|
const config = useConfig<ConfigObject>();
|
|
67
|
+
const { mutate: mutateOrders } = useMutatePatientOrders(patient.id);
|
|
65
68
|
|
|
66
69
|
const OrderFormSchema = useMemo(
|
|
67
70
|
() =>
|
|
@@ -108,7 +111,7 @@ export function OrderForm({
|
|
|
108
111
|
return menu?.item?.value?.toLowerCase().includes(menu?.inputValue?.toLowerCase());
|
|
109
112
|
}, []);
|
|
110
113
|
|
|
111
|
-
const
|
|
114
|
+
const saveOrderToBasket = useCallback(
|
|
112
115
|
(data: OrderBasketItem) => {
|
|
113
116
|
const finalizedOrder: OrderBasketItem = {
|
|
114
117
|
...initialOrder,
|
|
@@ -131,22 +134,55 @@ export function OrderForm({
|
|
|
131
134
|
|
|
132
135
|
setOrders(newOrders);
|
|
133
136
|
|
|
134
|
-
|
|
135
|
-
onWorkspaceClose: () => launchWorkspace('order-basket'),
|
|
136
|
-
closeWorkspaceGroup: false,
|
|
137
|
-
});
|
|
137
|
+
closeWorkspace({ discardUnsavedChanges: true });
|
|
138
138
|
},
|
|
139
|
-
[orders, setOrders, session?.currentProvider?.uuid,
|
|
139
|
+
[orders, setOrders, session?.currentProvider?.uuid, initialOrder, closeWorkspace],
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const submitDrugOrderToServer = useCallback(
|
|
143
|
+
(data: OrderBasketItem) => {
|
|
144
|
+
const finalizedOrder: OrderBasketItem = {
|
|
145
|
+
...initialOrder,
|
|
146
|
+
...data,
|
|
147
|
+
};
|
|
148
|
+
finalizedOrder.orderer = session.currentProvider.uuid;
|
|
149
|
+
|
|
150
|
+
postOrder(prepOrderPostData(finalizedOrder, patient.id, finalizedOrder?.encounterUuid))
|
|
151
|
+
.then(() => {
|
|
152
|
+
clearOrders();
|
|
153
|
+
mutateOrders();
|
|
154
|
+
showSnackbar({
|
|
155
|
+
isLowContrast: false,
|
|
156
|
+
kind: 'success',
|
|
157
|
+
title: t('successSavingDrugOrder', 'Order saved'),
|
|
158
|
+
});
|
|
159
|
+
closeWorkspace({ discardUnsavedChanges: true });
|
|
160
|
+
})
|
|
161
|
+
.catch((error) => {
|
|
162
|
+
showSnackbar({
|
|
163
|
+
isLowContrast: false,
|
|
164
|
+
kind: 'error',
|
|
165
|
+
title: t('errorSavingDrugOrder', 'Error saving order'),
|
|
166
|
+
subtitle: error,
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
[clearOrders, closeWorkspace, initialOrder, mutateOrders, patient.id, session.currentProvider.uuid, t],
|
|
140
171
|
);
|
|
141
172
|
|
|
142
173
|
const cancelOrder = useCallback(() => {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
174
|
+
closeWorkspace().then((didClose: boolean) => {
|
|
175
|
+
if (didClose) {
|
|
176
|
+
setOrders(orders.filter((order) => order.concept.uuid !== defaultValues.concept.conceptUuid));
|
|
177
|
+
}
|
|
147
178
|
});
|
|
148
179
|
}, [closeWorkspace, orders, setOrders, defaultValues]);
|
|
149
180
|
|
|
181
|
+
const closeModifyOrderWorkspace = useCallback(() => {
|
|
182
|
+
clearOrders();
|
|
183
|
+
closeWorkspace();
|
|
184
|
+
}, [clearOrders, closeWorkspace]);
|
|
185
|
+
|
|
150
186
|
const onError = (errors: FieldErrors<OrderBasketItem>) => {
|
|
151
187
|
if (errors) {
|
|
152
188
|
setShowErrorNotification(true);
|
|
@@ -164,20 +200,24 @@ export function OrderForm({
|
|
|
164
200
|
};
|
|
165
201
|
|
|
166
202
|
useEffect(() => {
|
|
167
|
-
|
|
168
|
-
}, [isDirty,
|
|
203
|
+
setHasUnsavedChanges(isDirty);
|
|
204
|
+
}, [isDirty, setHasUnsavedChanges]);
|
|
169
205
|
|
|
170
206
|
const responsiveSize = isTablet ? 'lg' : 'sm';
|
|
171
207
|
|
|
172
208
|
return (
|
|
173
209
|
<>
|
|
174
|
-
<Form
|
|
210
|
+
<Form
|
|
211
|
+
className={styles.orderForm}
|
|
212
|
+
onSubmit={handleSubmit(initialOrder?.action == 'REVISE' ? submitDrugOrderToServer : saveOrderToBasket, onError)}
|
|
213
|
+
id="drugOrderForm"
|
|
214
|
+
>
|
|
175
215
|
<div className={styles.form}>
|
|
176
216
|
<ExtensionSlot name="top-of-lab-order-form-slot" state={{ order: initialOrder }} />
|
|
177
217
|
<Grid className={styles.gridRow}>
|
|
178
218
|
<Column lg={16} md={8} sm={4}>
|
|
179
219
|
<InputWrapper>
|
|
180
|
-
<
|
|
220
|
+
<label className={styles.testTypeLabel}>{t('testType', 'Test type')}</label>
|
|
181
221
|
<p className={styles.testType}>{initialOrder?.concept?.display}</p>
|
|
182
222
|
</InputWrapper>
|
|
183
223
|
</Column>
|
|
@@ -294,7 +334,12 @@ export function OrderForm({
|
|
|
294
334
|
<ButtonSet
|
|
295
335
|
className={classNames(styles.buttonSet, isTablet ? styles.tabletButtonSet : styles.desktopButtonSet)}
|
|
296
336
|
>
|
|
297
|
-
<Button
|
|
337
|
+
<Button
|
|
338
|
+
className={styles.button}
|
|
339
|
+
kind="secondary"
|
|
340
|
+
onClick={initialOrder?.action == 'REVISE' ? closeModifyOrderWorkspace : cancelOrder}
|
|
341
|
+
size="xl"
|
|
342
|
+
>
|
|
298
343
|
{t('discard', 'Discard')}
|
|
299
344
|
</Button>
|
|
300
345
|
<Button className={styles.button} kind="primary" size="xl" type="submit">
|