@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.
Files changed (70) hide show
  1. package/.turbo/turbo-build.log +14 -14
  2. package/dist/1253.js +1 -0
  3. package/dist/1253.js.map +1 -0
  4. package/dist/375.js +1 -0
  5. package/dist/375.js.map +1 -0
  6. package/dist/4300.js +1 -1
  7. package/dist/4341.js +1 -0
  8. package/dist/4341.js.map +1 -0
  9. package/dist/4558.js +1 -0
  10. package/dist/4558.js.map +1 -0
  11. package/dist/5937.js +1 -0
  12. package/dist/5937.js.map +1 -0
  13. package/dist/6473.js +1 -0
  14. package/dist/6473.js.map +1 -0
  15. package/dist/6483.js +1 -0
  16. package/dist/6483.js.map +1 -0
  17. package/dist/8376.js +1 -0
  18. package/dist/8376.js.map +1 -0
  19. package/dist/8389.js +1 -0
  20. package/dist/8389.js.map +1 -0
  21. package/dist/8416.js +1 -0
  22. package/dist/8416.js.map +1 -0
  23. package/dist/8894.js +1 -0
  24. package/dist/8894.js.map +1 -0
  25. package/dist/main.js +1 -1
  26. package/dist/main.js.map +1 -1
  27. package/dist/openmrs-esm-patient-orders-app.js +1 -1
  28. package/dist/openmrs-esm-patient-orders-app.js.buildmanifest.json +230 -107
  29. package/dist/openmrs-esm-patient-orders-app.js.map +1 -1
  30. package/dist/routes.json +1 -1
  31. package/package.json +2 -2
  32. package/src/api/api.ts +0 -25
  33. package/src/components/order-details-table.component.tsx +53 -40
  34. package/src/index.ts +19 -11
  35. package/src/lab-results/{lab-results-form.component.tsx → exported-lab-results-form.workspace.tsx} +105 -108
  36. package/src/lab-results/lab-results-form.test.tsx +24 -38
  37. package/src/lab-results/lab-results-form.workspace.tsx +26 -0
  38. package/src/order-basket/exported-order-basket.workspace.tsx +59 -0
  39. 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
  40. package/src/order-basket/general-order-type/add-general-order/add-general-order.workspace.tsx +38 -0
  41. package/src/order-basket/general-order-type/add-general-order/exported-add-general-order.workspace.tsx +35 -0
  42. package/src/order-basket/general-order-type/{orderable-concept-search → add-general-order}/search-results.component.tsx +15 -14
  43. package/src/order-basket/general-order-type/general-order-form/general-order-form.component.tsx +70 -25
  44. package/src/order-basket/general-order-type/{general-order-type.component.tsx → general-order-panel.component.tsx} +23 -41
  45. package/src/order-basket/general-order-type/resources.ts +3 -2
  46. package/src/order-basket/order-basket.component.tsx +213 -0
  47. package/src/order-basket/order-basket.workspace.tsx +42 -252
  48. package/src/order-basket-action-button/order-basket-action-button.component.tsx +35 -0
  49. package/src/order-basket-action-button/order-basket-action-button.test.tsx +27 -36
  50. package/src/routes.json +17 -25
  51. package/src/utils/index.ts +15 -3
  52. package/translations/en.json +4 -20
  53. package/dist/1571.js +0 -1
  54. package/dist/1571.js.map +0 -1
  55. package/dist/2717.js +0 -1
  56. package/dist/2717.js.map +0 -1
  57. package/dist/4937.js +0 -1
  58. package/dist/4937.js.map +0 -1
  59. package/dist/8625.js +0 -1
  60. package/dist/8625.js.map +0 -1
  61. package/dist/8803.js +0 -1
  62. package/dist/8803.js.map +0 -1
  63. package/dist/8960.js +0 -1
  64. package/dist/8960.js.map +0 -1
  65. package/src/order-basket-action-button/order-basket-action-button.extension.tsx +0 -31
  66. package/src/order-cancellation-form/cancel-order-form.component.tsx +0 -180
  67. package/src/order-cancellation-form/cancel-order-form.scss +0 -87
  68. package/src/order-cancellation-form/cancel-order.resource.tsx +0 -15
  69. /package/src/order-basket/general-order-type/{orderable-concept-search → add-general-order}/orderable-concept-search.scss +0 -0
  70. /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, useEffect, useMemo, useRef, useState } from 'react';
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 DefaultWorkspaceProps,
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 OrderableConceptSearchWorkspaceProps extends DefaultPatientWorkspaceProps {
26
- order: OrderBasketItem;
21
+ interface AddGeneralOrderProps {
22
+ initialOrder: OrderBasketItem;
27
23
  orderTypeUuid: string;
28
- orderableConceptClasses: Array<string>;
29
- orderableConceptSets: Array<string>;
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
- const OrderableConceptSearchWorkspace: React.FC<OrderableConceptSearchWorkspaceProps> = ({
41
- order: initialOrder,
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
- mutateVisitContext,
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
- useEffect(() => {
47
+ const title = useMemo(() => {
60
48
  if (orderType) {
61
- setTitle(
62
- t(`addOrderableForOrderType`, 'Add {{orderTypeDisplay}}', {
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, setTitle]);
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
- <div className={styles.workspaceWrapper}>
95
- {!isTablet && (
96
- <div className={styles.backButton}>
97
- <Button
98
- iconDescription="Return to order basket"
99
- kind="ghost"
100
- onClick={cancelDrugOrder}
101
- renderIcon={(props: ComponentProps<typeof ArrowLeftIcon>) => <ArrowLeftIcon size={24} {...props} />}
102
- size="sm"
103
- >
104
- <span>{t('backToOrderBasket', 'Back to order basket')}</span>
105
- </Button>
106
- </div>
107
- )}
108
- {currentOrder ? (
109
- <OrderForm
110
- initialOrder={currentOrder}
111
- closeWorkspace={closeWorkspace}
112
- closeWorkspaceWithSavedChanges={closeWorkspaceWithSavedChanges}
113
- promptBeforeClosing={promptBeforeClosing}
114
- orderTypeUuid={orderTypeUuid}
115
- orderableConceptSets={orderableConceptSets}
116
- patientUuid={patientUuid}
117
- patient={patient}
118
- visitContext={visitContext}
119
- mutateVisitContext={mutateVisitContext}
120
- setTitle={() => {}}
121
- />
122
- ) : (
123
- <ConceptSearch
124
- openOrderForm={openOrderForm}
125
- closeWorkspace={closeWorkspace}
126
- orderableConceptSets={orderableConceptSets}
127
- orderTypeUuid={orderTypeUuid}
128
- patient={patient}
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: DefaultWorkspaceProps['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
- export default OrderableConceptSearchWorkspace;
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
- launchWorkspace,
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: DefaultWorkspaceProps['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: DefaultWorkspaceProps['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
- ignoreChanges: true,
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>
@@ -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
- launchWorkspace,
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 extends DefaultPatientWorkspaceProps {
42
+ export interface OrderFormProps {
41
43
  initialOrder: OrderBasketItem;
42
44
  orderTypeUuid: string;
43
- orderableConceptSets: Array<string>;
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 isEditing = useMemo(() => initialOrder && initialOrder.action === 'REVISE', [initialOrder]);
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 handleFormSubmission = useCallback(
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
- closeWorkspaceWithSavedChanges({
135
- onWorkspaceClose: () => launchWorkspace('order-basket'),
136
- closeWorkspaceGroup: false,
137
- });
137
+ closeWorkspace({ discardUnsavedChanges: true });
138
138
  },
139
- [orders, setOrders, session?.currentProvider?.uuid, closeWorkspaceWithSavedChanges, initialOrder],
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
- setOrders(orders.filter((order) => order.concept.uuid !== defaultValues.concept.conceptUuid));
144
- closeWorkspace({
145
- onWorkspaceClose: () => launchWorkspace('order-basket'),
146
- closeWorkspaceGroup: false,
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
- promptBeforeClosing(() => isDirty);
168
- }, [isDirty, promptBeforeClosing]);
203
+ setHasUnsavedChanges(isDirty);
204
+ }, [isDirty, setHasUnsavedChanges]);
169
205
 
170
206
  const responsiveSize = isTablet ? 'lg' : 'sm';
171
207
 
172
208
  return (
173
209
  <>
174
- <Form className={styles.orderForm} onSubmit={handleSubmit(handleFormSubmission, onError)} id="drugOrderForm">
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
- <span className={styles.testTypeLabel}>{t('testType', 'Test type')}</span>
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 className={styles.button} kind="secondary" onClick={cancelOrder} size="xl">
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">