@openmrs/esm-patient-orders-app 11.3.1-patch.9310 → 11.3.1-patch.9508

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