@openmrs/esm-patient-orders-app 11.3.1-pre.9452 → 11.3.1-pre.9455

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 +71 -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,40 @@ import {
31
32
  useConfig,
32
33
  ExtensionSlot,
33
34
  OpenmrsDatePicker,
34
- launchWorkspace,
35
+ type Workspace2DefinitionProps,
36
+ showSnackbar,
37
+ useAbortController,
35
38
  } from '@openmrs/esm-framework';
36
39
  import { ordersEqual, prepOrderPostData } from '../resources';
37
40
  import { type ConfigObject } from '../../../config-schema';
38
41
  import styles from './general-order-form.scss';
39
42
 
40
- export interface OrderFormProps extends DefaultPatientWorkspaceProps {
43
+ export interface OrderFormProps {
41
44
  initialOrder: OrderBasketItem;
42
45
  orderTypeUuid: string;
43
- orderableConceptSets: Array<string>;
46
+ closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
47
+ setHasUnsavedChanges: (hasUnsavedChanges: boolean) => void;
48
+ patient: fhir.Patient;
44
49
  }
45
50
 
46
51
  // Designs:
47
52
  // https://app.zeplin.io/project/60d5947dd636aebbd63dce4c/screen/640b06c440ee3f7af8747620
48
53
  // https://app.zeplin.io/project/60d5947dd636aebbd63dce4c/screen/640b06d286e0aa7b0316db4a
49
54
  export function OrderForm({
50
- initialOrder,
51
- closeWorkspace,
52
- closeWorkspaceWithSavedChanges,
53
- promptBeforeClosing,
54
55
  patient,
56
+ initialOrder,
55
57
  orderTypeUuid,
58
+ closeWorkspace,
59
+ setHasUnsavedChanges,
56
60
  }: OrderFormProps) {
57
61
  const { t } = useTranslation();
58
62
  const isTablet = useLayoutType() === 'tablet';
59
63
  const session = useSession();
60
- const isEditing = useMemo(() => initialOrder && initialOrder.action === 'REVISE', [initialOrder]);
61
- const { orders, setOrders } = useOrderBasket<OrderBasketItem>(patient, orderTypeUuid, prepOrderPostData);
64
+ const { orders, setOrders, clearOrders } = useOrderBasket<OrderBasketItem>(patient, orderTypeUuid, prepOrderPostData);
62
65
  const [showErrorNotification, setShowErrorNotification] = useState(false);
63
66
  const { orderType } = useOrderType(orderTypeUuid);
64
67
  const config = useConfig<ConfigObject>();
68
+ const { mutate: mutateOrders } = useMutatePatientOrders(patient.id);
65
69
 
66
70
  const OrderFormSchema = useMemo(
67
71
  () =>
@@ -108,7 +112,7 @@ export function OrderForm({
108
112
  return menu?.item?.value?.toLowerCase().includes(menu?.inputValue?.toLowerCase());
109
113
  }, []);
110
114
 
111
- const handleFormSubmission = useCallback(
115
+ const saveOrderToBasket = useCallback(
112
116
  (data: OrderBasketItem) => {
113
117
  const finalizedOrder: OrderBasketItem = {
114
118
  ...initialOrder,
@@ -131,22 +135,55 @@ export function OrderForm({
131
135
 
132
136
  setOrders(newOrders);
133
137
 
134
- closeWorkspaceWithSavedChanges({
135
- onWorkspaceClose: () => launchWorkspace('order-basket'),
136
- closeWorkspaceGroup: false,
137
- });
138
+ closeWorkspace({ discardUnsavedChanges: true });
138
139
  },
139
- [orders, setOrders, session?.currentProvider?.uuid, closeWorkspaceWithSavedChanges, initialOrder],
140
+ [orders, setOrders, session?.currentProvider?.uuid, initialOrder, closeWorkspace],
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],
140
172
  );
141
173
 
142
174
  const cancelOrder = useCallback(() => {
143
- setOrders(orders.filter((order) => order.concept.uuid !== defaultValues.concept.conceptUuid));
144
- closeWorkspace({
145
- onWorkspaceClose: () => launchWorkspace('order-basket'),
146
- closeWorkspaceGroup: false,
175
+ closeWorkspace().then((didClose: boolean) => {
176
+ if (didClose) {
177
+ setOrders(orders.filter((order) => order.concept.uuid !== defaultValues.concept.conceptUuid));
178
+ }
147
179
  });
148
180
  }, [closeWorkspace, orders, setOrders, defaultValues]);
149
181
 
182
+ const closeModifyOrderWorkspace = useCallback(() => {
183
+ clearOrders();
184
+ closeWorkspace();
185
+ }, [clearOrders, closeWorkspace]);
186
+
150
187
  const onError = (errors: FieldErrors<OrderBasketItem>) => {
151
188
  if (errors) {
152
189
  setShowErrorNotification(true);
@@ -164,20 +201,24 @@ export function OrderForm({
164
201
  };
165
202
 
166
203
  useEffect(() => {
167
- promptBeforeClosing(() => isDirty);
168
- }, [isDirty, promptBeforeClosing]);
204
+ setHasUnsavedChanges(isDirty);
205
+ }, [isDirty, setHasUnsavedChanges]);
169
206
 
170
207
  const responsiveSize = isTablet ? 'lg' : 'sm';
171
208
 
172
209
  return (
173
210
  <>
174
- <Form className={styles.orderForm} onSubmit={handleSubmit(handleFormSubmission, onError)} id="drugOrderForm">
211
+ <Form
212
+ className={styles.orderForm}
213
+ onSubmit={handleSubmit(initialOrder?.action == 'REVISE' ? submitDrugOrderToServer : saveOrderToBasket, onError)}
214
+ id="drugOrderForm"
215
+ >
175
216
  <div className={styles.form}>
176
217
  <ExtensionSlot name="top-of-lab-order-form-slot" state={{ order: initialOrder }} />
177
218
  <Grid className={styles.gridRow}>
178
219
  <Column lg={16} md={8} sm={4}>
179
220
  <InputWrapper>
180
- <span className={styles.testTypeLabel}>{t('testType', 'Test type')}</span>
221
+ <label className={styles.testTypeLabel}>{t('testType', 'Test type')}</label>
181
222
  <p className={styles.testType}>{initialOrder?.concept?.display}</p>
182
223
  </InputWrapper>
183
224
  </Column>
@@ -294,7 +335,12 @@ export function OrderForm({
294
335
  <ButtonSet
295
336
  className={classNames(styles.buttonSet, isTablet ? styles.tabletButtonSet : styles.desktopButtonSet)}
296
337
  >
297
- <Button className={styles.button} kind="secondary" onClick={cancelOrder} size="xl">
338
+ <Button
339
+ className={styles.button}
340
+ kind="secondary"
341
+ onClick={initialOrder?.action == 'REVISE' ? closeModifyOrderWorkspace : cancelOrder}
342
+ size="xl"
343
+ >
298
344
  {t('discard', 'Discard')}
299
345
  </Button>
300
346
  <Button className={styles.button} kind="primary" size="xl" type="submit">