@openmrs/esm-patient-tests-app 11.3.1-pre.9447 → 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 (47) hide show
  1. package/.turbo/turbo-build.log +11 -11
  2. package/dist/{1935.js → 1176.js} +1 -1
  3. package/dist/1176.js.map +1 -0
  4. package/dist/1477.js +1 -1
  5. package/dist/1477.js.map +1 -1
  6. package/dist/1638.js +1 -1
  7. package/dist/1638.js.map +1 -1
  8. package/dist/4300.js +1 -1
  9. package/dist/629.js +1 -0
  10. package/dist/629.js.map +1 -0
  11. package/dist/671.js +1 -0
  12. package/dist/671.js.map +1 -0
  13. package/dist/7202.js +1 -1
  14. package/dist/7202.js.map +1 -1
  15. package/dist/790.js +1 -1
  16. package/dist/790.js.map +1 -1
  17. package/dist/9838.js +1 -0
  18. package/dist/9838.js.map +1 -0
  19. package/dist/main.js +1 -1
  20. package/dist/main.js.map +1 -1
  21. package/dist/openmrs-esm-patient-tests-app.js +1 -1
  22. package/dist/openmrs-esm-patient-tests-app.js.buildmanifest.json +109 -85
  23. package/dist/openmrs-esm-patient-tests-app.js.map +1 -1
  24. package/dist/routes.json +1 -1
  25. package/package.json +2 -2
  26. package/src/edit-test-results/modal/edit-lab-results.modal.tsx +4 -3
  27. package/src/index.ts +5 -1
  28. package/src/routes.json +2 -3
  29. package/src/test-orders/add-test-order/add-test-order.component.tsx +125 -0
  30. package/src/test-orders/add-test-order/add-test-order.test.tsx +22 -45
  31. package/src/test-orders/add-test-order/add-test-order.workspace.tsx +24 -152
  32. package/src/test-orders/add-test-order/exported-add-test-order.workspace.tsx +30 -0
  33. package/src/test-orders/add-test-order/test-order-form.component.tsx +68 -60
  34. package/src/test-orders/add-test-order/test-order.ts +3 -3
  35. package/src/test-orders/add-test-order/test-type-search.component.tsx +28 -60
  36. package/src/test-orders/api.ts +6 -2
  37. package/src/test-orders/lab-order-basket-panel/lab-order-basket-item-tile.component.tsx +1 -1
  38. package/src/test-orders/lab-order-basket-panel/lab-order-basket-panel.extension.tsx +26 -84
  39. package/src/test-orders/lab-order-basket-panel/lab-order-basket-panel.test.tsx +10 -12
  40. package/src/test-results/tree-view/tree-view.component.tsx +1 -1
  41. package/src/types.ts +0 -9
  42. package/translations/en.json +2 -4
  43. package/dist/1935.js.map +0 -1
  44. package/dist/34.js +0 -1
  45. package/dist/34.js.map +0 -1
  46. package/dist/6113.js +0 -1
  47. package/dist/6113.js.map +0 -1
@@ -19,35 +19,35 @@ import { zodResolver } from '@hookform/resolvers/zod';
19
19
  import { z } from 'zod';
20
20
  import { useTranslation } from 'react-i18next';
21
21
  import {
22
- type DefaultPatientWorkspaceProps,
23
- type Order,
24
22
  type OrderUrgency,
25
23
  priorityOptions,
26
24
  useOrderBasket,
27
25
  useOrderType,
26
+ type TestOrderBasketItem,
27
+ postOrder,
28
+ useMutatePatientOrders,
29
+ showOrderSuccessToast,
28
30
  } from '@openmrs/esm-patient-common-lib';
29
31
  import {
30
32
  ExtensionSlot,
31
- launchWorkspace,
32
33
  OpenmrsDatePicker,
34
+ showSnackbar,
33
35
  useConfig,
34
36
  useLayoutType,
35
37
  useSession,
38
+ type Workspace2DefinitionProps,
36
39
  } from '@openmrs/esm-framework';
37
40
  import { prepTestOrderPostData, useOrderReasons } from '../api';
38
41
  import { ordersEqual } from './test-order';
39
42
  import { type ConfigObject } from '../../config-schema';
40
- import { type TestOrderBasketItem } from '../../types';
41
- import { WORKSPACES } from '../lab-order-basket-panel/lab-order-basket-panel.extension';
42
43
  import styles from './test-order-form.scss';
43
44
 
44
- export interface LabOrderFormProps extends DefaultPatientWorkspaceProps {
45
+ export interface LabOrderFormProps {
46
+ closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
45
47
  initialOrder: TestOrderBasketItem;
46
48
  orderTypeUuid: string;
47
49
  orderableConceptSets: Array<string>;
48
- prevWorkSpace: string;
49
- isWorkSpaceType: (value: string) => boolean;
50
- prevOrder: Order;
50
+ setHasUnsavedChanges: (hasUnsavedChanges: boolean) => void;
51
51
  patient: fhir.Patient;
52
52
  }
53
53
 
@@ -57,25 +57,22 @@ export interface LabOrderFormProps extends DefaultPatientWorkspaceProps {
57
57
  export function LabOrderForm({
58
58
  initialOrder,
59
59
  closeWorkspace,
60
- closeWorkspaceWithSavedChanges,
61
- promptBeforeClosing,
62
60
  orderTypeUuid,
63
- orderableConceptSets,
64
- prevWorkSpace,
65
- isWorkSpaceType,
66
- prevOrder,
67
- patientUuid,
61
+ setHasUnsavedChanges,
68
62
  patient,
69
63
  }: LabOrderFormProps) {
70
64
  const { t } = useTranslation();
71
65
  const isTablet = useLayoutType() === 'tablet';
72
66
  const session = useSession();
73
- const isEditing = useMemo(() => initialOrder && initialOrder.action === 'REVISE', [initialOrder]);
74
- const { orders, setOrders } = useOrderBasket<TestOrderBasketItem>(patient, orderTypeUuid, prepTestOrderPostData);
67
+ const { orders, setOrders, clearOrders } = useOrderBasket<TestOrderBasketItem>(
68
+ patient,
69
+ orderTypeUuid,
70
+ prepTestOrderPostData,
71
+ );
75
72
  const [showErrorNotification, setShowErrorNotification] = useState(false);
76
73
  const config = useConfig<ConfigObject>();
77
- const { orderType, isLoadingOrderType } = useOrderType(orderTypeUuid);
78
-
74
+ const { orderType } = useOrderType(orderTypeUuid);
75
+ const { mutate: mutateOrders } = useMutatePatientOrders(patient.id);
79
76
  const orderReasonRequired = useMemo(
80
77
  () =>
81
78
  (config.labTestsWithOrderReasons?.find((c) => c.labTestUuid === initialOrder?.testType?.conceptUuid) || {})
@@ -147,7 +144,7 @@ export function LabOrderForm({
147
144
  return itemDisplay?.includes(inputValue);
148
145
  }, []);
149
146
 
150
- const handleFormSubmission = useCallback(
147
+ const saveLabOrderToBasket = useCallback(
151
148
  (data: TestOrderBasketItem) => {
152
149
  const finalizedOrder: TestOrderBasketItem = {
153
150
  ...initialOrder,
@@ -170,40 +167,46 @@ export function LabOrderForm({
170
167
 
171
168
  setOrders(newOrders);
172
169
 
173
- closeWorkspaceWithSavedChanges({
174
- onWorkspaceClose: () =>
175
- typeof isWorkSpaceType === 'function' &&
176
- isWorkSpaceType(prevWorkSpace) &&
177
- prevWorkSpace === WORKSPACES.TEST_RESULTS_FORM
178
- ? launchWorkspace(prevWorkSpace, { order: prevOrder })
179
- : launchWorkspace(WORKSPACES.ORDER_BASKET),
180
- closeWorkspaceGroup: false,
181
- });
170
+ closeWorkspace({ discardUnsavedChanges: true });
182
171
  },
183
- [
184
- orders,
185
- setOrders,
186
- session?.currentProvider?.uuid,
187
- closeWorkspaceWithSavedChanges,
188
- initialOrder,
189
- isWorkSpaceType,
190
- prevOrder,
191
- prevWorkSpace,
192
- ],
172
+ [orders, setOrders, session?.currentProvider?.uuid, closeWorkspace, initialOrder],
173
+ );
174
+
175
+ const submitLabOrderToServer = useCallback(
176
+ (data: TestOrderBasketItem) => {
177
+ const finalizedOrder: TestOrderBasketItem = {
178
+ ...initialOrder,
179
+ ...data,
180
+ };
181
+ finalizedOrder.orderer = session.currentProvider.uuid;
182
+ postOrder(prepTestOrderPostData(finalizedOrder, patient.id, finalizedOrder?.encounterUuid))
183
+ .then(() => {
184
+ clearOrders();
185
+ mutateOrders();
186
+ showOrderSuccessToast(t, [finalizedOrder]);
187
+ closeWorkspace({ discardUnsavedChanges: true });
188
+ })
189
+ .catch((error) => {
190
+ showSnackbar({
191
+ isLowContrast: false,
192
+ kind: 'error',
193
+ title: t('errorSavingLabOrder', 'Error saving lab order'),
194
+ subtitle: error.message,
195
+ });
196
+ });
197
+ },
198
+ [clearOrders, closeWorkspace, initialOrder, mutateOrders, patient.id, session.currentProvider.uuid, t],
193
199
  );
194
200
 
195
201
  const cancelOrder = useCallback(() => {
196
202
  setOrders(orders.filter((order) => order.testType.conceptUuid !== defaultValues.testType.conceptUuid));
197
- closeWorkspace({
198
- onWorkspaceClose: () =>
199
- typeof isWorkSpaceType === 'function' &&
200
- isWorkSpaceType(prevWorkSpace) &&
201
- prevWorkSpace === WORKSPACES.TEST_RESULTS_FORM
202
- ? launchWorkspace(prevWorkSpace, { order: prevOrder })
203
- : launchWorkspace(WORKSPACES.ORDER_BASKET),
204
- closeWorkspaceGroup: false,
205
- });
206
- }, [closeWorkspace, orders, setOrders, defaultValues, isWorkSpaceType, prevOrder, prevWorkSpace]);
203
+ closeWorkspace();
204
+ }, [closeWorkspace, orders, setOrders, defaultValues]);
205
+
206
+ const closeModifyOrderWorkspace = useCallback(() => {
207
+ clearOrders();
208
+ closeWorkspace();
209
+ }, [clearOrders, closeWorkspace]);
207
210
 
208
211
  const onError = (errors: FieldErrors<TestOrderBasketItem>) => {
209
212
  if (errors) {
@@ -225,19 +228,23 @@ export function LabOrderForm({
225
228
  );
226
229
 
227
230
  useEffect(() => {
228
- promptBeforeClosing(() => isDirty);
229
- }, [isDirty, promptBeforeClosing]);
231
+ setHasUnsavedChanges(isDirty);
232
+ }, [isDirty, setHasUnsavedChanges]);
230
233
 
231
234
  const responsiveSize = isTablet ? 'lg' : 'sm';
232
235
 
233
236
  return (
234
- <Form className={styles.orderForm} onSubmit={handleSubmit(handleFormSubmission, onError)} id="drugOrderForm">
237
+ <Form
238
+ className={styles.orderForm}
239
+ onSubmit={handleSubmit(initialOrder?.action == 'REVISE' ? submitLabOrderToServer : saveLabOrderToBasket, onError)}
240
+ id="drugOrderForm"
241
+ >
235
242
  <div className={styles.form}>
236
243
  <ExtensionSlot name="top-of-lab-order-form-slot" state={{ order: initialOrder }} />
237
244
  <Grid className={styles.gridRow}>
238
245
  <Column lg={16} md={8} sm={4}>
239
246
  <InputWrapper>
240
- <span className={styles.testTypeLabel}>{t('testType', 'Test type')}</span>
247
+ <label className={styles.testTypeLabel}>{t('testType', 'Test type')}</label>
241
248
  <p className={styles.testType}>{initialOrder?.testType?.label}</p>
242
249
  </InputWrapper>
243
250
  </Column>
@@ -381,15 +388,16 @@ export function LabOrderForm({
381
388
  <ButtonSet
382
389
  className={classNames(styles.buttonSet, isTablet ? styles.tabletButtonSet : styles.desktopButtonSet)}
383
390
  >
384
- <Button className={styles.button} kind="secondary" onClick={cancelOrder} size="xl">
391
+ <Button
392
+ className={styles.button}
393
+ kind="secondary"
394
+ onClick={initialOrder?.action == 'REVISE' ? closeModifyOrderWorkspace : cancelOrder}
395
+ size="xl"
396
+ >
385
397
  {t('discard', 'Discard')}
386
398
  </Button>
387
399
  <Button className={styles.button} kind="primary" size="xl" type="submit">
388
- {typeof isWorkSpaceType === 'function' &&
389
- isWorkSpaceType(prevWorkSpace) &&
390
- prevWorkSpace === WORKSPACES.TEST_RESULTS_FORM
391
- ? t('saveTest', 'Save test')
392
- : t('saveOrder', 'Save order')}
400
+ {t('saveOrder', 'Save order')}
393
401
  </Button>
394
402
  </ButtonSet>
395
403
  </div>
@@ -1,16 +1,16 @@
1
- import { priorityOptions, type OrderUrgency } from '@openmrs/esm-patient-common-lib';
1
+ import { priorityOptions, type OrderUrgency, type TestOrderBasketItem } from '@openmrs/esm-patient-common-lib';
2
2
  import { type TestType } from './useTestTypes';
3
- import type { TestOrderBasketItem } from '../../types';
4
3
 
5
4
  type LabOrderRequest = Pick<TestOrderBasketItem, 'action' | 'testType'>;
6
5
 
7
- export function createEmptyLabOrder(testType: TestType, orderer: string): TestOrderBasketItem {
6
+ export function createEmptyLabOrder(testType: TestType, orderer: string, visit): TestOrderBasketItem {
8
7
  return {
9
8
  action: 'NEW',
10
9
  urgency: priorityOptions[0].value as OrderUrgency,
11
10
  display: testType.label,
12
11
  testType,
13
12
  orderer,
13
+ visit,
14
14
  };
15
15
  }
16
16
 
@@ -5,34 +5,30 @@ import { Button, ButtonSkeleton, Search, SkeletonText, Tile } from '@carbon/reac
5
5
  import { ShoppingCartArrowUp } from '@carbon/react/icons';
6
6
  import {
7
7
  ArrowRightIcon,
8
- closeWorkspace,
9
- launchWorkspace,
10
8
  ResponsiveWrapper,
11
9
  ShoppingCartArrowDownIcon,
12
10
  useDebounce,
13
11
  useLayoutType,
14
12
  useSession,
13
+ type Visit,
14
+ type Workspace2DefinitionProps,
15
15
  } from '@openmrs/esm-framework';
16
- import { useOrderBasket, type Order } from '@openmrs/esm-patient-common-lib';
17
- import type { TestOrderBasketItem } from '../../types';
16
+ import { useOrderBasket, type TestOrderBasketItem } from '@openmrs/esm-patient-common-lib';
18
17
  import { prepTestOrderPostData } from '../api';
19
18
  import { createEmptyLabOrder } from './test-order';
20
19
  import { useTestTypes, type TestType } from './useTestTypes';
21
- import { WORKSPACES } from '../lab-order-basket-panel/lab-order-basket-panel.extension';
22
20
  import styles from './test-type-search.scss';
23
21
 
24
22
  export interface TestTypeSearchProps {
25
23
  openLabForm: (searchResult: TestOrderBasketItem) => void;
26
24
  orderTypeUuid: string;
27
25
  orderableConceptSets: Array<string>;
28
- prevWorkSpace: string;
29
- isWorkSpaceType: (value: string) => boolean;
30
- prevOrder: Order;
26
+ closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
31
27
  patient: fhir.Patient;
28
+ visit: Visit;
32
29
  }
33
30
 
34
31
  interface TestTypeSearchResultsProps extends TestTypeSearchProps {
35
- cancelOrder: () => void;
36
32
  searchTerm: string;
37
33
  focusAndClearSearchInput: () => void;
38
34
  patient: fhir.Patient;
@@ -42,20 +38,18 @@ interface TestTypeSearchResultItemProps {
42
38
  orderTypeUuid: string;
43
39
  testType: TestType;
44
40
  openOrderForm: (searchResult: TestOrderBasketItem) => void;
45
- prevWorkSpace: string;
46
- isWorkSpaceType: (value: string) => boolean;
47
- prevOrder: Order;
48
41
  patient: fhir.Patient;
42
+ visit: Visit;
43
+ closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
49
44
  }
50
45
 
51
46
  export function TestTypeSearch({
47
+ patient,
48
+ visit,
52
49
  openLabForm,
53
50
  orderTypeUuid,
54
51
  orderableConceptSets,
55
- prevWorkSpace,
56
- isWorkSpaceType,
57
- prevOrder,
58
- patient,
52
+ closeWorkspace,
59
53
  }: TestTypeSearchProps) {
60
54
  const { t } = useTranslation();
61
55
  const [searchTerm, setSearchTerm] = useState('');
@@ -67,18 +61,6 @@ export function TestTypeSearch({
67
61
  searchInputRef.current?.focus();
68
62
  }, [setSearchTerm]);
69
63
 
70
- const cancelOrder = useCallback(() => {
71
- closeWorkspace('add-lab-order', {
72
- ignoreChanges: true,
73
- onWorkspaceClose: () =>
74
- typeof isWorkSpaceType === 'function' &&
75
- isWorkSpaceType(prevWorkSpace) &&
76
- prevWorkSpace === WORKSPACES.TEST_RESULTS_FORM
77
- ? launchWorkspace(prevWorkSpace, { order: prevOrder })
78
- : launchWorkspace(WORKSPACES.ORDER_BASKET),
79
- });
80
- }, [isWorkSpaceType, prevOrder, prevWorkSpace]);
81
-
82
64
  const handleSearchTermChange = useCallback(
83
65
  (event: React.ChangeEvent<HTMLInputElement>) => {
84
66
  setSearchTerm(event.target.value ?? '');
@@ -100,32 +82,28 @@ export function TestTypeSearch({
100
82
  />
101
83
  </ResponsiveWrapper>
102
84
  <TestTypeSearchResults
103
- cancelOrder={cancelOrder}
85
+ closeWorkspace={closeWorkspace}
104
86
  orderTypeUuid={orderTypeUuid}
105
87
  orderableConceptSets={orderableConceptSets}
106
88
  focusAndClearSearchInput={focusAndClearSearchInput}
107
89
  openLabForm={openLabForm}
108
90
  searchTerm={debouncedSearchTerm}
109
- prevWorkSpace={prevWorkSpace}
110
- isWorkSpaceType={isWorkSpaceType}
111
- prevOrder={prevOrder}
112
91
  patient={patient}
92
+ visit={visit}
113
93
  />
114
94
  </>
115
95
  );
116
96
  }
117
97
 
118
98
  function TestTypeSearchResults({
119
- cancelOrder,
99
+ closeWorkspace,
120
100
  searchTerm,
121
101
  orderTypeUuid,
122
102
  orderableConceptSets,
123
103
  openLabForm,
124
104
  focusAndClearSearchInput,
125
- prevWorkSpace,
126
- isWorkSpaceType,
127
- prevOrder,
128
105
  patient,
106
+ visit,
129
107
  }: TestTypeSearchResultsProps) {
130
108
  const { t } = useTranslation();
131
109
  const isTablet = useLayoutType() === 'tablet';
@@ -176,10 +154,9 @@ function TestTypeSearchResults({
176
154
  orderTypeUuid={orderTypeUuid}
177
155
  openOrderForm={openLabForm}
178
156
  testType={testType}
179
- prevWorkSpace={prevWorkSpace}
180
- isWorkSpaceType={isWorkSpaceType}
181
- prevOrder={prevOrder}
157
+ closeWorkspace={closeWorkspace}
182
158
  patient={patient}
159
+ visit={visit}
183
160
  />
184
161
  ))}
185
162
  </div>
@@ -187,12 +164,12 @@ function TestTypeSearchResults({
187
164
  {isTablet && (
188
165
  <div className={styles.separatorContainer}>
189
166
  <p className={styles.separator}>{t('or', 'or')}</p>
190
- <Button iconDescription="Return to order basket" kind="ghost" onClick={cancelOrder}>
191
- {typeof isWorkSpaceType === 'function' &&
192
- isWorkSpaceType(prevWorkSpace) &&
193
- prevWorkSpace === WORKSPACES.TEST_RESULTS_FORM
194
- ? t('backToTestResults', 'Back to test Results')
195
- : t('backToOrderBasket', 'Back to order basket')}
167
+ <Button
168
+ iconDescription="Return to order basket"
169
+ kind="ghost"
170
+ onClick={() => closeWorkspace({ discardUnsavedChanges: true })}
171
+ >
172
+ {t('back', 'Back')}
196
173
  </Button>
197
174
  </div>
198
175
  )}
@@ -224,10 +201,9 @@ const TestTypeSearchResultItem: React.FC<TestTypeSearchResultItemProps> = ({
224
201
  testType,
225
202
  openOrderForm,
226
203
  orderTypeUuid,
227
- prevWorkSpace,
228
- isWorkSpaceType,
229
- prevOrder,
204
+ closeWorkspace,
230
205
  patient,
206
+ visit,
231
207
  }) => {
232
208
  const { t } = useTranslation();
233
209
  const isTablet = useLayoutType() === 'tablet';
@@ -241,25 +217,17 @@ const TestTypeSearchResultItem: React.FC<TestTypeSearchResultItemProps> = ({
241
217
 
242
218
  const createLabOrder = useCallback(
243
219
  (orderableConcept: TestType) => {
244
- return createEmptyLabOrder(orderableConcept, session.currentProvider?.uuid);
220
+ return createEmptyLabOrder(orderableConcept, session.currentProvider?.uuid, visit);
245
221
  },
246
- [session.currentProvider.uuid],
222
+ [session.currentProvider.uuid, visit],
247
223
  );
248
224
 
249
225
  const addToBasket = useCallback(() => {
250
226
  const labOrder = createLabOrder(testType);
251
227
  labOrder.isOrderIncomplete = true;
252
228
  setOrders([...orders, labOrder]);
253
- closeWorkspace('add-lab-order', {
254
- ignoreChanges: true,
255
- onWorkspaceClose: () =>
256
- typeof isWorkSpaceType === 'function' &&
257
- isWorkSpaceType(prevWorkSpace) &&
258
- prevWorkSpace === WORKSPACES.TEST_RESULTS_FORM
259
- ? launchWorkspace(prevWorkSpace, { order: prevOrder })
260
- : launchWorkspace(WORKSPACES.ORDER_BASKET),
261
- });
262
- }, [orders, setOrders, createLabOrder, testType, isWorkSpaceType, prevOrder, prevWorkSpace]);
229
+ closeWorkspace({ discardUnsavedChanges: true });
230
+ }, [orders, setOrders, createLabOrder, testType, closeWorkspace]);
263
231
 
264
232
  const removeFromBasket = useCallback(() => {
265
233
  setOrders(orders.filter((order) => order.testType.conceptUuid !== testType.conceptUuid));
@@ -2,7 +2,12 @@ import { useCallback, useMemo } from 'react';
2
2
  import { chunk } from 'lodash-es';
3
3
  import useSWR, { useSWRConfig } from 'swr';
4
4
  import useSWRImmutable from 'swr/immutable';
5
- import type { OrderPost, PatientOrderFetchResponse, TestOrderPost } from '@openmrs/esm-patient-common-lib';
5
+ import type {
6
+ OrderPost,
7
+ PatientOrderFetchResponse,
8
+ TestOrderBasketItem,
9
+ TestOrderPost,
10
+ } from '@openmrs/esm-patient-common-lib';
6
11
  import {
7
12
  type FetchResponse,
8
13
  openmrsFetch,
@@ -12,7 +17,6 @@ import {
12
17
  useConfig,
13
18
  } from '@openmrs/esm-framework';
14
19
  import { type ConfigObject } from '../config-schema';
15
- import type { TestOrderBasketItem } from '../types';
16
20
 
17
21
  export const careSettingUuid = '6f0c9a92-6f24-11e3-af88-005056821db0';
18
22
 
@@ -3,7 +3,7 @@ import classNames from 'classnames';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { ClickableTile, IconButton, Tile } from '@carbon/react';
5
5
  import { ExtensionSlot, TrashCanIcon, useLayoutType, WarningIcon } from '@openmrs/esm-framework';
6
- import type { TestOrderBasketItem } from '../../types';
6
+ import type { TestOrderBasketItem } from '@openmrs/esm-patient-common-lib';
7
7
  import styles from './lab-order-basket-item-tile.scss';
8
8
 
9
9
  export interface OrderBasketItemTileProps {
@@ -2,38 +2,26 @@ import React, { type ComponentProps, useCallback, useEffect, useMemo, useState }
2
2
  import classNames from 'classnames';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { Button, Tile } from '@carbon/react';
5
+ import { AddIcon, ChevronDownIcon, ChevronUpIcon, useLayoutType, useConfig, MaybeIcon } from '@openmrs/esm-framework';
5
6
  import {
6
- AddIcon,
7
- closeWorkspace,
8
- ChevronDownIcon,
9
- ChevronUpIcon,
10
- useLayoutType,
11
- useConfig,
12
- MaybeIcon,
13
- launchWorkspace,
14
- useWorkspaces,
15
- type Visit,
16
- } from '@openmrs/esm-framework';
17
- import { type OrderBasketItem, useOrderBasket, useOrderType } from '@openmrs/esm-patient-common-lib';
7
+ type TestOrderBasketItem,
8
+ useOrderBasket,
9
+ useOrderType,
10
+ type OrderBasketExtensionProps,
11
+ } from '@openmrs/esm-patient-common-lib';
18
12
  import type { ConfigObject } from '../../config-schema';
19
- import type { TestOrderBasketItem } from '../../types';
20
13
  import { LabOrderBasketItemTile } from './lab-order-basket-item-tile.component';
21
14
  import { prepTestOrderPostData } from '../api';
22
15
  import LabIcon from './lab-icon.component';
23
16
  import styles from './lab-order-basket-panel.scss';
24
17
 
25
- interface OrderBasketSlotProps {
26
- patientUuid: string;
27
- patient: fhir.Patient;
28
- visitContext: Visit;
29
- mutateVisitContext: () => void;
30
- }
31
-
32
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 lab orders, and lists pending lab orders in the order basket.
21
+ *
33
22
  * Designs: https://app.zeplin.io/project/60d59321e8100b0324762e05/screen/648c44d9d4052c613e7f23da
34
- * Slotted into order-basket-slot by default
35
23
  */
36
- const LabOrderBasketPanelExtension: React.FC<OrderBasketSlotProps> = ({ patient }) => {
24
+ export function LabOrderBasketPanelExtension({ patient, launchLabOrderForm }: OrderBasketExtensionProps) {
37
25
  const { orders, additionalTestOrderTypes } = useConfig<ConfigObject>();
38
26
  const { t } = useTranslation();
39
27
  const allOrderTypes: ConfigObject['additionalTestOrderTypes'] = [
@@ -49,35 +37,30 @@ const LabOrderBasketPanelExtension: React.FC<OrderBasketSlotProps> = ({ patient
49
37
  return (
50
38
  <>
51
39
  {allOrderTypes.map((orderTypeConfig) => (
52
- <LabOrderBasketPanel patient={patient} key={orderTypeConfig.orderTypeUuid} {...orderTypeConfig} />
40
+ <LabOrderBasketPanel
41
+ key={orderTypeConfig.orderTypeUuid}
42
+ patient={patient}
43
+ {...orderTypeConfig}
44
+ launchLabOrderForm={launchLabOrderForm}
45
+ />
53
46
  ))}
54
47
  </>
55
48
  );
56
- };
57
-
58
- export const WORKSPACES = {
59
- TEST_RESULTS_FORM: 'test-results-form-workspace',
60
- ORDER_BASKET: 'order-basket',
61
- };
49
+ }
62
50
 
63
51
  type OrderTypeConfig = ConfigObject['additionalTestOrderTypes'][0];
64
52
 
65
53
  interface LabOrderBasketPanelProps extends OrderTypeConfig {
66
54
  patient: fhir.Patient;
55
+ launchLabOrderForm(orderTypeUuid: string, order?: TestOrderBasketItem): void;
67
56
  }
68
57
 
69
- function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient }: LabOrderBasketPanelProps) {
58
+ function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient, launchLabOrderForm }: LabOrderBasketPanelProps) {
70
59
  const { t } = useTranslation();
71
- type WorkSpaceType = (typeof WORKSPACES)[keyof typeof WORKSPACES];
72
60
  const isTablet = useLayoutType() === 'tablet';
73
61
  const responsiveSize = isTablet ? 'md' : 'sm';
74
62
  const isDefaultLabOrder = icon === 'omrs-icon-lab-order';
75
63
  const { orderType, isLoadingOrderType } = useOrderType(orderTypeUuid);
76
- const { workspaces = [{ name: WORKSPACES.ORDER_BASKET, additionalProps: {} }] } = useWorkspaces();
77
- const [prevWorkSpace, setPrevWorkSpace] = useState(workspaces[0]?.name);
78
- const [prevOrder, setPrevOrder] = useState(
79
- workspaces[0]?.name === WORKSPACES.TEST_RESULTS_FORM ? workspaces[0].additionalProps['order'] : null,
80
- );
81
64
  const { orders, setOrders } = useOrderBasket<TestOrderBasketItem>(patient, orderTypeUuid, prepTestOrderPostData);
82
65
  const [isExpanded, setIsExpanded] = useState(orders.length > 0);
83
66
  const {
@@ -115,41 +98,6 @@ function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient }: LabOrderBa
115
98
  discontinuedOrderBasketItems,
116
99
  };
117
100
  }, [orders]);
118
- const isWorkSpaceType = useCallback((value: string): value is WorkSpaceType => {
119
- return Object.values(WORKSPACES).includes(value as WorkSpaceType);
120
- }, []);
121
-
122
- const openNewLabForm = useCallback(() => {
123
- closeWorkspace(isWorkSpaceType(prevWorkSpace) ? prevWorkSpace : WORKSPACES.ORDER_BASKET, {
124
- ignoreChanges: true,
125
- onWorkspaceClose: () =>
126
- launchWorkspace('add-lab-order', {
127
- orderTypeUuid: orderTypeUuid,
128
- prevWorkSpace: prevWorkSpace,
129
- isWorkSpaceType: isWorkSpaceType,
130
- prevOrder: prevOrder,
131
- }),
132
- closeWorkspaceGroup: false,
133
- });
134
- }, [orderTypeUuid, isWorkSpaceType, prevOrder, prevWorkSpace]);
135
-
136
- const openEditLabForm = useCallback(
137
- (order: OrderBasketItem) => {
138
- closeWorkspace(isWorkSpaceType(prevWorkSpace) ? prevWorkSpace : WORKSPACES.ORDER_BASKET, {
139
- ignoreChanges: true,
140
- onWorkspaceClose: () =>
141
- launchWorkspace('add-lab-order', {
142
- order,
143
- orderTypeUuid: orderTypeUuid,
144
- prevWorkSpace: prevWorkSpace,
145
- isWorkSpaceType: isWorkSpaceType,
146
- prevOrder: prevOrder,
147
- }),
148
- closeWorkspaceGroup: false,
149
- });
150
- },
151
- [orderTypeUuid, isWorkSpaceType, prevOrder, prevWorkSpace],
152
- );
153
101
 
154
102
  const removeLabOrder = useCallback(
155
103
  (order: TestOrderBasketItem) => {
@@ -181,20 +129,14 @@ function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient }: LabOrderBa
181
129
  ) : (
182
130
  <MaybeIcon icon={icon ? icon : 'omrs-icon-generic-order-type'} size={isTablet ? 40 : 24} />
183
131
  )}
184
- <h4 className={styles.heading}>{`${
185
- isWorkSpaceType(prevWorkSpace) && prevWorkSpace === WORKSPACES.ORDER_BASKET
186
- ? label
187
- ? t(label)
188
- : orderType?.display
189
- : t('tests', 'Tests')
190
- } (${orders.length})`}</h4>
132
+ <h4 className={styles.heading}>{`${label ? t(label) : orderType?.display} (${orders.length})`}</h4>
191
133
  </div>
192
134
  <div className={styles.buttonContainer}>
193
135
  <Button
194
136
  className={styles.addButton}
195
137
  iconDescription="Add lab order"
196
138
  kind="ghost"
197
- onClick={openNewLabForm}
139
+ onClick={() => launchLabOrderForm(orderTypeUuid)}
198
140
  renderIcon={(props: ComponentProps<typeof AddIcon>) => <AddIcon size={16} {...props} />}
199
141
  size={responsiveSize}
200
142
  >
@@ -225,7 +167,7 @@ function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient }: LabOrderBa
225
167
  {incompleteOrderBasketItems.map((order) => (
226
168
  <LabOrderBasketItemTile
227
169
  key={order.uuid}
228
- onItemClick={() => openEditLabForm(order)}
170
+ onItemClick={() => launchLabOrderForm(orderTypeUuid, order)}
229
171
  onRemoveClick={() => removeLabOrder(order)}
230
172
  orderBasketItem={order}
231
173
  />
@@ -237,7 +179,7 @@ function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient }: LabOrderBa
237
179
  {newOrderBasketItems.map((order) => (
238
180
  <LabOrderBasketItemTile
239
181
  key={order.uuid}
240
- onItemClick={() => openEditLabForm(order)}
182
+ onItemClick={() => launchLabOrderForm(orderTypeUuid, order)}
241
183
  onRemoveClick={() => removeLabOrder(order)}
242
184
  orderBasketItem={order}
243
185
  />
@@ -250,7 +192,7 @@ function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient }: LabOrderBa
250
192
  {renewedOrderBasketItems.map((order) => (
251
193
  <LabOrderBasketItemTile
252
194
  key={order.uuid}
253
- onItemClick={() => openEditLabForm(order)}
195
+ onItemClick={() => launchLabOrderForm(orderTypeUuid, order)}
254
196
  onRemoveClick={() => removeLabOrder(order)}
255
197
  orderBasketItem={order}
256
198
  />
@@ -263,7 +205,7 @@ function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient }: LabOrderBa
263
205
  {revisedOrderBasketItems.map((order) => (
264
206
  <LabOrderBasketItemTile
265
207
  key={order.uuid}
266
- onItemClick={() => openEditLabForm(order)}
208
+ onItemClick={() => launchLabOrderForm(orderTypeUuid, order)}
267
209
  onRemoveClick={() => removeLabOrder(order)}
268
210
  orderBasketItem={order}
269
211
  />
@@ -276,7 +218,7 @@ function LabOrderBasketPanel({ orderTypeUuid, label, icon, patient }: LabOrderBa
276
218
  {discontinuedOrderBasketItems.map((order) => (
277
219
  <LabOrderBasketItemTile
278
220
  key={order.uuid}
279
- onItemClick={() => openEditLabForm(order)}
221
+ onItemClick={() => launchLabOrderForm(orderTypeUuid, order)}
280
222
  onRemoveClick={() => removeLabOrder(order)}
281
223
  orderBasketItem={order}
282
224
  />