@thrustdevs/esm-procedure-orders-app 1.0.2-pre.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +41 -0
- package/README.md +7 -0
- package/dist/122.js +1 -0
- package/dist/122.js.map +1 -0
- package/dist/144.js +2 -0
- package/dist/144.js.LICENSE.txt +19 -0
- package/dist/144.js.map +1 -0
- package/dist/182.js +1 -0
- package/dist/182.js.map +1 -0
- package/dist/205.js +1 -0
- package/dist/205.js.map +1 -0
- package/dist/216.js +2 -0
- package/dist/216.js.LICENSE.txt +9 -0
- package/dist/216.js.map +1 -0
- package/dist/290.js +2 -0
- package/dist/290.js.LICENSE.txt +5 -0
- package/dist/290.js.map +1 -0
- package/dist/300.js +1 -0
- package/dist/341.js +2 -0
- package/dist/341.js.LICENSE.txt +29 -0
- package/dist/341.js.map +1 -0
- package/dist/41.js +2 -0
- package/dist/41.js.LICENSE.txt +9 -0
- package/dist/41.js.map +1 -0
- package/dist/470.js +1 -0
- package/dist/470.js.map +1 -0
- package/dist/495.js +1 -0
- package/dist/495.js.map +1 -0
- package/dist/506.js +2 -0
- package/dist/506.js.LICENSE.txt +39 -0
- package/dist/506.js.map +1 -0
- package/dist/537.js +1 -0
- package/dist/537.js.map +1 -0
- package/dist/647.js +2 -0
- package/dist/647.js.LICENSE.txt +5 -0
- package/dist/647.js.map +1 -0
- package/dist/7.js +1 -0
- package/dist/7.js.map +1 -0
- package/dist/719.js +2 -0
- package/dist/719.js.LICENSE.txt +5 -0
- package/dist/719.js.map +1 -0
- package/dist/720.js +1 -0
- package/dist/720.js.map +1 -0
- package/dist/876.js +1 -0
- package/dist/876.js.map +1 -0
- package/dist/883.js +1 -0
- package/dist/883.js.map +1 -0
- package/dist/89.js +1 -0
- package/dist/89.js.map +1 -0
- package/dist/892.js +1 -0
- package/dist/892.js.map +1 -0
- package/dist/895.js +1 -0
- package/dist/895.js.map +1 -0
- package/dist/913.js +2 -0
- package/dist/913.js.LICENSE.txt +32 -0
- package/dist/913.js.map +1 -0
- package/dist/924.js +1 -0
- package/dist/924.js.map +1 -0
- package/dist/943.js +1 -0
- package/dist/943.js.map +1 -0
- package/dist/99.js +2 -0
- package/dist/99.js.LICENSE.txt +5 -0
- package/dist/99.js.map +1 -0
- package/dist/kenyaemr-esm-procedure-orders-app.js +1 -0
- package/dist/kenyaemr-esm-procedure-orders-app.js.buildmanifest.json +786 -0
- package/dist/kenyaemr-esm-procedure-orders-app.js.map +1 -0
- package/dist/main.js +2 -0
- package/dist/main.js.LICENSE.txt +35 -0
- package/dist/main.js.map +1 -0
- package/dist/routes.json +1 -0
- package/jest.config.js +8 -0
- package/package.json +55 -0
- package/src/completed-list/completed-list.component.tsx +40 -0
- package/src/completed-list/completed-list.resource.ts +0 -0
- package/src/completed-list/completed-list.scss +223 -0
- package/src/components/create-dashboard-link.component.tsx +35 -0
- package/src/components/overlay/hook.ts +47 -0
- package/src/components/overlay/overlay.component.tsx +42 -0
- package/src/components/overlay/overlay.scss +92 -0
- package/src/config-schema.ts +78 -0
- package/src/constants.ts +5 -0
- package/src/declarations.d.ts +6 -0
- package/src/empty-state/empty-state-component.tsx +21 -0
- package/src/empty-state/empty-state.scss +23 -0
- package/src/form/post-procedures/post-procedure-form.component.tsx +468 -0
- package/src/form/post-procedures/post-procedure-form.scss +189 -0
- package/src/form/post-procedures/post-procedure.resource.tsx +71 -0
- package/src/form/procedures-orders/add-procedures-order/add-procedures-order.scss +44 -0
- package/src/form/procedures-orders/add-procedures-order/add-procedures-order.workspace.tsx +93 -0
- package/src/form/procedures-orders/add-procedures-order/procedures-order-form.component.tsx +476 -0
- package/src/form/procedures-orders/add-procedures-order/procedures-order-form.scss +80 -0
- package/src/form/procedures-orders/add-procedures-order/procedures-order.ts +17 -0
- package/src/form/procedures-orders/add-procedures-order/procedures-type-search.scss +115 -0
- package/src/form/procedures-orders/add-procedures-order/procedures-type-search.tsx +236 -0
- package/src/form/procedures-orders/add-procedures-order/useProceduresTypes.ts +93 -0
- package/src/form/procedures-orders/api.ts +282 -0
- package/src/form/procedures-orders/order-config.ts +48 -0
- package/src/form/procedures-orders/procedures-order-basket-panel/procedures-icon.component.tsx +39 -0
- package/src/form/procedures-orders/procedures-order-basket-panel/procedures-order-basket-item-tile.component.tsx +100 -0
- package/src/form/procedures-orders/procedures-order-basket-panel/procedures-order-basket-item-tile.scss +72 -0
- package/src/form/procedures-orders/procedures-order-basket-panel/procedures-order-basket-panel.extension.tsx +190 -0
- package/src/form/procedures-orders/procedures-order-basket-panel/procedures-order-basket-panel.scss +74 -0
- package/src/form/procedures-orders/procedures-order-basket-panel/procedures-order-basket.scss +55 -0
- package/src/header/procedure-header.component.tsx +32 -0
- package/src/header/procedure-header.scss +70 -0
- package/src/header/procedure-illustration.component.tsx +52 -0
- package/src/hooks/useOrdersWorklist.ts +70 -0
- package/src/hooks/useSearchGroupedResults.ts +22 -0
- package/src/hooks/useSearchResults.ts +39 -0
- package/src/index.ts +59 -0
- package/src/left-panel-link.tsx +40 -0
- package/src/not-done-list/not-done-list.component.tsx +44 -0
- package/src/not-done-list/not-done.scss +207 -0
- package/src/patient-chart/patient-procedure-order-results-table.resource.ts +43 -0
- package/src/patient-chart/patient-procedure-order-results.component.tsx +12 -0
- package/src/patient-chart/patient-procedure-order-results.resource.ts +485 -0
- package/src/patient-chart/patient-procedure-results.component.tsx +30 -0
- package/src/patient-chart/procedure-active-order/procedure-active-order-results.component.tsx +390 -0
- package/src/patient-chart/procedure-active-order/procedure-active-order-results.scss +78 -0
- package/src/patient-chart/procedure-order-referals/procedure-order-referals.component.tsx +394 -0
- package/src/patient-chart/procedure-order-referals/procedure-order-referals.resource.tsx +0 -0
- package/src/patient-chart/procedure-order-referals/procedure-order-referals.scss +78 -0
- package/src/patient-chart/procedure-past-test/laboratory-past-test-order-results.component.tsx +366 -0
- package/src/patient-chart/procedure-past-test/laboratory-past-test-order-results.scss +74 -0
- package/src/patient-chart/procedure-tabs/laboratory-order-tabs.component.tsx +44 -0
- package/src/patient-chart/procedure-tabs/laboratory-order-tabs.scss +7 -0
- package/src/patient-chart/procedure-workspaces/laboratory-referral.workspace.component.tsx +11 -0
- package/src/patient-chart/procedure-workspaces/laboratory-referral.workspace.scss +0 -0
- package/src/patient-chart/results-summary/print-results-summary.component.tsx +152 -0
- package/src/patient-chart/results-summary/print-results-summary.scss +80 -0
- package/src/patient-chart/results-summary/print-results-table.component.tsx +134 -0
- package/src/patient-chart/results-summary/results-summary.resource.tsx +174 -0
- package/src/patient-chart/results-summary/results-summary.scss +158 -0
- package/src/patient-chart/results-summary/send-email-dialog.component.tsx +59 -0
- package/src/patient-chart/results-summary/test-children-results.component.tsx +177 -0
- package/src/patient-chart/results-summary/test-print-results-table.component.tsx +105 -0
- package/src/patient-chart/results-summary/test-results-table.component.tsx +103 -0
- package/src/print/print-procedure-results.component.tsx +49 -0
- package/src/print/print-procedure.component.tsx +105 -0
- package/src/print/print-procedure.scss +98 -0
- package/src/procedure-tabs/completed-tab.component.tsx +12 -0
- package/src/procedure-tabs/not-done-tab.component.tsx +12 -0
- package/src/procedure-tabs/referred-tab.component.tsx +12 -0
- package/src/procedure-tabs/work-list-tab.component.tsx +13 -0
- package/src/procedure.component.tsx +24 -0
- package/src/procedures-ordered/_pick-procedure-request-menu.component.tsx +33 -0
- package/src/procedures-ordered/pick-procedure-order/add-to-worklist-dialog.component.tsx +105 -0
- package/src/procedures-ordered/pick-procedure-order/add-to-worklist-dialog.resource.ts +106 -0
- package/src/procedures-ordered/pick-procedure-order/add-to-worklist-dialog.scss +38 -0
- package/src/procedures-ordered/pick-procedure-request-menu.component.tsx +32 -0
- package/src/procedures-ordered/procedure-dialogs/add-to-worklist-dialog.component.tsx +300 -0
- package/src/procedures-ordered/procedure-dialogs/add-to-worklist-dialog.resource.ts +153 -0
- package/src/procedures-ordered/procedure-dialogs/add-to-worklist-dialog.scss +38 -0
- package/src/procedures-ordered/procedure-instructions/instructions.scss +24 -0
- package/src/procedures-ordered/procedure-instructions/procedure-instructions-menu.component.tsx +32 -0
- package/src/procedures-ordered/procedure-instructions/procedure-instructions.component.tsx +78 -0
- package/src/procedures-ordered/procedure-instructions/procedure-instructions.scss +24 -0
- package/src/procedures-ordered/procedure-queue.scss +211 -0
- package/src/procedures-ordered/procedure-tabs.component.tsx +104 -0
- package/src/procedures-ordered/procedure-tests/procedure-tests.component.tsx +83 -0
- package/src/procedures-ordered/procedure-tests/procedure-tests.resource.ts +14 -0
- package/src/procedures-ordered/procedure-tests/procedure-tests.scss +12 -0
- package/src/procedures-ordered/procedures-ordered-list.component.tsx +38 -0
- package/src/procedures-ordered/reject-order-dialog/reject-order-dialog.scss +14 -0
- package/src/procedures-ordered/reject-order-dialog/reject-procedure-order-dialog.component.tsx +98 -0
- package/src/procedures-ordered/reject-reason/procedure-reject-reason-menu.component.tsx +32 -0
- package/src/procedures-ordered/reject-reason/procedure-reject-reason.component.tsx +40 -0
- package/src/procedures-ordered/transition-patient-new-queue/transition-latest-queue-entry-button.component.tsx +42 -0
- package/src/procedures-ordered/transition-patient-new-queue/transition-latest-queue-entry-button.scss +14 -0
- package/src/procedures-ordered/transition-patient-new-queue/transition-latest-queue-entry-button.test.tsx +67 -0
- package/src/referred-procedures/referred-procedures.component.tsx +37 -0
- package/src/results/result-form-field.component.tsx +141 -0
- package/src/results/result-form.component.tsx +120 -0
- package/src/results/result-form.resource.ts +361 -0
- package/src/results/result-form.scss +22 -0
- package/src/root.component.tsx +16 -0
- package/src/routes.json +152 -0
- package/src/setup-tests.ts +7 -0
- package/src/shared/ui/common/action-button/action-button.component.tsx +68 -0
- package/src/shared/ui/common/action-button/action-button.scss +12 -0
- package/src/shared/ui/common/action-button/order-action-extension.component.tsx +21 -0
- package/src/shared/ui/common/grouped-orders-table.component.tsx +176 -0
- package/src/shared/ui/common/grouped-orders-table.scss +30 -0
- package/src/shared/ui/common/grouped-procedure-types.ts +47 -0
- package/src/shared/ui/common/list-order-details.component.tsx +171 -0
- package/src/shared/ui/common/list-order-details.resource.ts +41 -0
- package/src/shared/ui/common/list-order-details.scss +118 -0
- package/src/shared/ui/common/orders-date-range-picker.scss +15 -0
- package/src/shared/ui/common/orders-date-range-picker.tsx +38 -0
- package/src/summary-tiles/procedure-summary-tiles.component.tsx +36 -0
- package/src/summary-tiles/procedure-summary-tiles.scss +11 -0
- package/src/summary-tiles/procedure-summary.resource.tsx +79 -0
- package/src/summary-tiles/summary-tile.component.tsx +41 -0
- package/src/summary-tiles/summary-tile.scss +53 -0
- package/src/types/index.ts +661 -0
- package/src/types/patient-queue.ts +77 -0
- package/src/ui-components/overflow-menu.component.tsx +74 -0
- package/src/ui-components/overflow-menu.scss +39 -0
- package/src/utils/functions.ts +236 -0
- package/src/utils/orders-table/orders-data-table.component.tsx +129 -0
- package/src/utils/orders-table/orders-data-table.scss +50 -0
- package/src/work-list/work-list.component.tsx +38 -0
- package/src/work-list/work-list.resource.ts +26 -0
- package/src/work-list/work-list.scss +207 -0
- package/translations/en.json +141 -0
- package/tsconfig.json +5 -0
- package/webpack.config.js +1 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import useSWR, { mutate } from 'swr';
|
|
2
|
+
import { type FetchResponse, openmrsFetch, useConfig, restBaseUrl, showSnackbar } from '@openmrs/esm-framework';
|
|
3
|
+
import { type ConfigObject } from '../../config-schema';
|
|
4
|
+
import { useCallback, useMemo } from 'react';
|
|
5
|
+
import type { OrderPost, PatientOrderFetchResponse } from '@openmrs/esm-patient-common-lib';
|
|
6
|
+
import useSWRImmutable from 'swr/immutable';
|
|
7
|
+
import { type ProcedureOrderBasketItem } from '../../types';
|
|
8
|
+
|
|
9
|
+
export interface ProcedureOrderPost extends OrderPost {
|
|
10
|
+
scheduledDate?: string;
|
|
11
|
+
commentToFulfiller?: string;
|
|
12
|
+
specimenSource?: string;
|
|
13
|
+
specimenType?: string;
|
|
14
|
+
numberOfRepeats?: string;
|
|
15
|
+
}
|
|
16
|
+
export const careSettingUuid = '6f0c9a92-6f24-11e3-af88-005056821db0';
|
|
17
|
+
/**
|
|
18
|
+
* SWR-based data fetcher for patient orders.
|
|
19
|
+
*
|
|
20
|
+
* @param patientUuid The UUID of the patient whose orders should be fetched.
|
|
21
|
+
* @param status Allows fetching either all orders or only active orders.
|
|
22
|
+
*/
|
|
23
|
+
export function usePatientLabOrders(patientUuid: string, status: 'ACTIVE' | 'any') {
|
|
24
|
+
const { labOrderTypeUuid: labOrderTypeUUID } = (useConfig() as ConfigObject).orders;
|
|
25
|
+
const ordersUrl = `${restBaseUrl}/order?patient=${patientUuid}&careSetting=${careSettingUuid}&status=${status}&orderType=${labOrderTypeUUID}`;
|
|
26
|
+
|
|
27
|
+
const { data, error, isLoading, isValidating } = useSWR<FetchResponse<PatientOrderFetchResponse>, Error>(
|
|
28
|
+
patientUuid ? ordersUrl : null,
|
|
29
|
+
openmrsFetch,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const mutateOrders = useCallback(
|
|
33
|
+
() => mutate((key) => typeof key === 'string' && key.startsWith(`${restBaseUrl}/order?patient=${patientUuid}`)),
|
|
34
|
+
[patientUuid],
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const labOrders = useMemo(
|
|
38
|
+
() =>
|
|
39
|
+
data?.data?.results
|
|
40
|
+
? data.data.results?.sort((order1, order2) => (order2.dateActivated > order1.dateActivated ? 1 : -1))
|
|
41
|
+
: null,
|
|
42
|
+
[data],
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
data: data ? labOrders : null,
|
|
47
|
+
error,
|
|
48
|
+
isLoading,
|
|
49
|
+
isValidating,
|
|
50
|
+
mutate: mutateOrders,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function useOrderReasons(conceptUuids: Array<string>) {
|
|
55
|
+
const shouldFetch = conceptUuids && conceptUuids.length > 0;
|
|
56
|
+
const url = shouldFetch ? getConceptReferenceUrls(conceptUuids) : null;
|
|
57
|
+
const { data, error, isLoading } = useSWRImmutable<FetchResponse<ConceptResponse>, Error>(
|
|
58
|
+
shouldFetch ? `${restBaseUrl}/${url[0]}` : null,
|
|
59
|
+
openmrsFetch,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const ob = data?.data;
|
|
63
|
+
const orderReasons = ob
|
|
64
|
+
? Object.entries(ob).map(([key, value]) => ({
|
|
65
|
+
uuid: value.uuid,
|
|
66
|
+
display: value.display,
|
|
67
|
+
}))
|
|
68
|
+
: [];
|
|
69
|
+
|
|
70
|
+
if (error) {
|
|
71
|
+
showSnackbar({
|
|
72
|
+
title: error.name,
|
|
73
|
+
subtitle: error.message,
|
|
74
|
+
kind: 'error',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return { orderReasons: orderReasons, isLoading };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function prepProceduresOrderPostData(
|
|
82
|
+
order: ProcedureOrderBasketItem,
|
|
83
|
+
patientUuid: string,
|
|
84
|
+
encounterUuid: string,
|
|
85
|
+
): ProcedureOrderPost {
|
|
86
|
+
let payload = {};
|
|
87
|
+
if (order.action === 'NEW' || order.action === 'RENEW') {
|
|
88
|
+
payload = {
|
|
89
|
+
action: 'NEW',
|
|
90
|
+
type: 'procedureorder',
|
|
91
|
+
patient: patientUuid,
|
|
92
|
+
careSetting: careSettingUuid,
|
|
93
|
+
orderer: order.orderer,
|
|
94
|
+
encounter: encounterUuid,
|
|
95
|
+
concept: order.testType.conceptUuid,
|
|
96
|
+
frequency: order.frequency,
|
|
97
|
+
numberOfRepeats: order.numberOfRepeats,
|
|
98
|
+
urgency: order.urgency,
|
|
99
|
+
commentToFulfiller: order.commentsToFulfiller,
|
|
100
|
+
instructions: order.instructions,
|
|
101
|
+
orderReason: order.orderReason,
|
|
102
|
+
orderReasonNonCoded: order.orderReasonNonCoded,
|
|
103
|
+
bodySite: order.bodySite,
|
|
104
|
+
};
|
|
105
|
+
if (order.urgency === 'ON_SCHEDULED_DATE') {
|
|
106
|
+
payload['scheduledDate'] =
|
|
107
|
+
order.scheduleDate instanceof Date ? order.scheduleDate.toISOString() : order.scheduleDate;
|
|
108
|
+
}
|
|
109
|
+
return payload;
|
|
110
|
+
} else if (order.action === 'REVISE') {
|
|
111
|
+
payload = {
|
|
112
|
+
action: 'REVISE',
|
|
113
|
+
type: 'procedureorder',
|
|
114
|
+
patient: patientUuid,
|
|
115
|
+
careSetting: order.careSetting,
|
|
116
|
+
orderer: order.orderer,
|
|
117
|
+
encounter: encounterUuid,
|
|
118
|
+
concept: order.testType.conceptUuid,
|
|
119
|
+
specimenSource: order.specimenSource,
|
|
120
|
+
specimenType: order.specimenType,
|
|
121
|
+
frequency: order.frequency,
|
|
122
|
+
numberOfRepeats: order.numberOfRepeats,
|
|
123
|
+
urgency: order.urgency,
|
|
124
|
+
commentToFulfiller: order.commentsToFulfiller,
|
|
125
|
+
instructions: order.instructions,
|
|
126
|
+
orderReason: order.orderReason,
|
|
127
|
+
orderReasonNonCoded: order.orderReasonNonCoded,
|
|
128
|
+
previousOrder: order.previousOrder,
|
|
129
|
+
};
|
|
130
|
+
if (order.urgency === 'ON_SCHEDULED_DATE') {
|
|
131
|
+
payload['scheduledDate'] =
|
|
132
|
+
order.scheduleDate instanceof Date ? order.scheduleDate.toISOString() : order.scheduleDate;
|
|
133
|
+
}
|
|
134
|
+
return payload;
|
|
135
|
+
} else if (order.action === 'DISCONTINUE') {
|
|
136
|
+
payload = {
|
|
137
|
+
action: 'DISCONTINUE',
|
|
138
|
+
type: 'procedureorder',
|
|
139
|
+
patient: patientUuid,
|
|
140
|
+
careSetting: order.careSetting,
|
|
141
|
+
orderer: order.orderer,
|
|
142
|
+
encounter: encounterUuid,
|
|
143
|
+
concept: order.testType.conceptUuid,
|
|
144
|
+
specimenSource: order.specimenSource,
|
|
145
|
+
specimenType: order.specimenType,
|
|
146
|
+
frequency: order.frequency,
|
|
147
|
+
urgency: order.urgency,
|
|
148
|
+
numberOfRepeats: order.numberOfRepeats,
|
|
149
|
+
commentToFulfiller: order.commentsToFulfiller,
|
|
150
|
+
orderReason: order.orderReason,
|
|
151
|
+
orderReasonNonCoded: order.orderReasonNonCoded,
|
|
152
|
+
previousOrder: order.previousOrder,
|
|
153
|
+
};
|
|
154
|
+
if (order.urgency === 'ON_SCHEDULED_DATE') {
|
|
155
|
+
payload['scheduledDate'] =
|
|
156
|
+
order.scheduleDate instanceof Date ? order.scheduleDate.toISOString() : order.scheduleDate;
|
|
157
|
+
}
|
|
158
|
+
return payload;
|
|
159
|
+
} else {
|
|
160
|
+
throw new Error(`Unknown order action: ${order.action}.`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const chunkSize = 10;
|
|
164
|
+
export function getConceptReferenceUrls(conceptUuids: Array<string>) {
|
|
165
|
+
const accumulator = [];
|
|
166
|
+
for (let i = 0; i < conceptUuids.length; i += chunkSize) {
|
|
167
|
+
accumulator.push(conceptUuids.slice(i, i + chunkSize));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return accumulator.map((partition) => `conceptreferences?references=${partition.join(',')}&v=custom:(uuid,display)`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export type PostDataPrepLabOrderFunction = (
|
|
174
|
+
order: ProcedureOrderBasketItem,
|
|
175
|
+
patientUuid: string,
|
|
176
|
+
encounterUuid: string,
|
|
177
|
+
) => OrderPost;
|
|
178
|
+
|
|
179
|
+
export interface ConceptAnswers {
|
|
180
|
+
display: string;
|
|
181
|
+
uuid: string;
|
|
182
|
+
}
|
|
183
|
+
export interface ConceptResponse {
|
|
184
|
+
uuid: string;
|
|
185
|
+
display: string;
|
|
186
|
+
datatype: {
|
|
187
|
+
uuid: string;
|
|
188
|
+
display: string;
|
|
189
|
+
};
|
|
190
|
+
answers: Array<ConceptAnswers>;
|
|
191
|
+
setMembers: Array<ConceptAnswers>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface OpenmrsObject {
|
|
195
|
+
uuid: string;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export type BaseOpenmrsObject = OpenmrsObject;
|
|
199
|
+
|
|
200
|
+
export interface SessionPriviledge {
|
|
201
|
+
uuid: string;
|
|
202
|
+
name: string;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface Person {
|
|
206
|
+
uuid: string;
|
|
207
|
+
display: string;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export interface Role {
|
|
211
|
+
role: string;
|
|
212
|
+
display: string;
|
|
213
|
+
}
|
|
214
|
+
export interface User {
|
|
215
|
+
uuid: string;
|
|
216
|
+
display: string;
|
|
217
|
+
givenName: string;
|
|
218
|
+
familyName: string;
|
|
219
|
+
firstName: string;
|
|
220
|
+
lastName: string;
|
|
221
|
+
person?: Person;
|
|
222
|
+
roles?: Role[];
|
|
223
|
+
privileges: SessionPriviledge[];
|
|
224
|
+
}
|
|
225
|
+
export interface Auditable extends OpenmrsObject {
|
|
226
|
+
creator: User;
|
|
227
|
+
dateCreated: Date;
|
|
228
|
+
changedBy: User;
|
|
229
|
+
dateChanged: Date;
|
|
230
|
+
}
|
|
231
|
+
export interface Retireable extends OpenmrsObject {
|
|
232
|
+
retired: boolean;
|
|
233
|
+
dateRetired: Date;
|
|
234
|
+
retiredBy: User;
|
|
235
|
+
retireReason: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface ConceptName extends BaseOpenmrsObject {
|
|
239
|
+
conceptNameId: number;
|
|
240
|
+
concept: Concept;
|
|
241
|
+
name: string;
|
|
242
|
+
localePreferred: boolean;
|
|
243
|
+
short: boolean;
|
|
244
|
+
preferred: boolean;
|
|
245
|
+
indexTerm: boolean;
|
|
246
|
+
synonym: boolean;
|
|
247
|
+
fullySpecifiedName: boolean;
|
|
248
|
+
}
|
|
249
|
+
export interface Concept extends BaseOpenmrsObject, Auditable, Retireable {
|
|
250
|
+
conceptId: number;
|
|
251
|
+
display: string;
|
|
252
|
+
set: boolean;
|
|
253
|
+
version: string;
|
|
254
|
+
names: ConceptName[];
|
|
255
|
+
name: ConceptName;
|
|
256
|
+
numeric: boolean;
|
|
257
|
+
complex: boolean;
|
|
258
|
+
shortNames: ConceptName[];
|
|
259
|
+
indexTerms: ConceptName[];
|
|
260
|
+
synonyms: ConceptName[];
|
|
261
|
+
setMembers: Concept[];
|
|
262
|
+
possibleValues: Concept[];
|
|
263
|
+
preferredName: ConceptName;
|
|
264
|
+
shortName: ConceptName;
|
|
265
|
+
fullySpecifiedName: ConceptName;
|
|
266
|
+
answers: Concept[];
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function useConceptById(id: string) {
|
|
270
|
+
const apiUrl = `ws/rest/v1/concept/${id}`;
|
|
271
|
+
const { data, error, isLoading } = useSWR<
|
|
272
|
+
{
|
|
273
|
+
data: Concept;
|
|
274
|
+
},
|
|
275
|
+
Error
|
|
276
|
+
>(apiUrl, openmrsFetch);
|
|
277
|
+
return {
|
|
278
|
+
items: data?.data || <Concept>{},
|
|
279
|
+
isLoading,
|
|
280
|
+
isError: error,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import useSWRImmutable from 'swr/immutable';
|
|
4
|
+
import { type DurationUnit, type OrderFrequency } from '../../types';
|
|
5
|
+
|
|
6
|
+
export interface CommonConfigProps {
|
|
7
|
+
uuid: string;
|
|
8
|
+
display: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface OrderConfig {
|
|
12
|
+
durationUnits: Array<CommonConfigProps>;
|
|
13
|
+
orderFrequencies: Array<CommonConfigProps>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function useOrderConfig(): {
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
error: Error;
|
|
19
|
+
orderConfigObject: {
|
|
20
|
+
durationUnits: Array<DurationUnit>;
|
|
21
|
+
orderFrequencies: Array<OrderFrequency>;
|
|
22
|
+
};
|
|
23
|
+
} {
|
|
24
|
+
const { data, error, isLoading, isValidating } = useSWRImmutable<{ data: OrderConfig }, Error>(
|
|
25
|
+
`${restBaseUrl}/orderentryconfig`,
|
|
26
|
+
openmrsFetch,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const results = useMemo(
|
|
30
|
+
() => ({
|
|
31
|
+
orderConfigObject: {
|
|
32
|
+
durationUnits: data?.data?.durationUnits?.map(({ uuid, display }) => ({
|
|
33
|
+
valueCoded: uuid,
|
|
34
|
+
value: display,
|
|
35
|
+
})),
|
|
36
|
+
orderFrequencies: data?.data?.orderFrequencies?.map(({ uuid, display }) => ({
|
|
37
|
+
valueCoded: uuid,
|
|
38
|
+
value: display,
|
|
39
|
+
})),
|
|
40
|
+
},
|
|
41
|
+
isLoading,
|
|
42
|
+
error,
|
|
43
|
+
}),
|
|
44
|
+
[data, error, isLoading],
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return results;
|
|
48
|
+
}
|
package/src/form/procedures-orders/procedures-order-basket-panel/procedures-icon.component.tsx
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ProcedureIconProps {
|
|
4
|
+
isTablet: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export default function ProcedureIcon({ isTablet }: ProcedureIconProps) {
|
|
8
|
+
const size = isTablet ? 40 : 24;
|
|
9
|
+
return (
|
|
10
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
11
|
+
<g clip-path="url(#clip0_319_602)">
|
|
12
|
+
<mask id="mask0_319_602" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
|
|
13
|
+
<path d="M24 0H0V24H24V0Z" fill="white" />
|
|
14
|
+
</mask>
|
|
15
|
+
<g mask="url(#mask0_319_602)">
|
|
16
|
+
<path d="M24 0H0V24H24V0Z" fill="#FFE9BD" />
|
|
17
|
+
<g clip-path="url(#clip1_319_602)">
|
|
18
|
+
<path
|
|
19
|
+
d="M17.6122 8.1377C17.279 7.81933 16.8358 7.64167 16.375 7.64167C15.9141 7.64167 15.4709 7.81933 15.1377 8.1377L5.15015 18.125H9.1951C9.48249 18.1257 9.76718 18.0695 10.0327 17.9595C10.2982 17.8495 10.5393 17.6879 10.7419 17.4841L17.6122 10.6123C17.7748 10.4498 17.9037 10.2569 17.9917 10.0446C18.0797 9.83235 18.125 9.6048 18.125 9.37499C18.125 9.14519 18.0797 8.91763 17.9917 8.70533C17.9037 8.49303 17.7748 8.30015 17.6122 8.1377ZM10.3781 14.1344L11.2907 13.2218L12.5285 14.4597L11.616 15.3724L10.3781 14.1344ZM10.1231 16.8655C10.0015 16.9877 9.85685 17.0846 9.69757 17.1506C9.53829 17.2166 9.36751 17.2504 9.1951 17.25H7.26244L9.75938 14.7531L10.9975 15.9912L10.1231 16.8655ZM16.9934 9.99366L13.1469 13.841L11.9091 12.6032L15.7561 8.75632C15.9228 8.59715 16.1443 8.50833 16.3748 8.50833C16.6052 8.50833 16.8268 8.59715 16.9934 8.75632C17.0747 8.83756 17.1392 8.934 17.1832 9.04016C17.2271 9.14631 17.2498 9.26009 17.2498 9.37499C17.2498 9.48989 17.2271 9.60367 17.1832 9.70982C17.1392 9.81598 17.0747 9.91242 16.9934 9.99366Z"
|
|
20
|
+
fill="#D99000"
|
|
21
|
+
/>
|
|
22
|
+
<path
|
|
23
|
+
d="M11.5625 5.87499C11.2919 5.87581 11.0282 5.96036 10.8077 6.11703C10.5871 6.2737 10.4205 6.49481 10.3306 6.74999H8.41928C8.34588 6.54115 8.22073 6.35433 8.05552 6.20699C7.89031 6.05966 7.69044 5.95662 7.47459 5.90751C7.25875 5.85839 7.03397 5.86481 6.82128 5.92616C6.60859 5.98751 6.41492 6.10179 6.25839 6.25831C6.10186 6.41484 5.98757 6.6085 5.92621 6.82118C5.86485 7.03387 5.85842 7.25865 5.90752 7.4745C5.95662 7.69035 6.05965 7.89022 6.20698 8.05544C6.3543 8.22065 6.54112 8.34582 6.74995 8.41923V10.3305C6.45805 10.4337 6.21202 10.6368 6.05536 10.9039C5.89871 11.1709 5.8415 11.4848 5.89385 11.7899C5.94621 12.0951 6.10476 12.3719 6.34148 12.5715C6.57819 12.771 6.87784 12.8805 7.18745 12.8805C7.49707 12.8805 7.79671 12.771 8.03343 12.5715C8.27015 12.3719 8.42869 12.0951 8.48105 11.7899C8.53341 11.4848 8.4762 11.1709 8.31954 10.9039C8.16288 10.6368 7.91686 10.4337 7.62495 10.3305V8.41945C7.80796 8.35418 7.97417 8.24904 8.11155 8.11164C8.24893 7.97424 8.35404 7.80801 8.41928 7.62499H10.3305C10.4112 7.85121 10.5524 8.05092 10.7388 8.20229C10.9253 8.35367 11.1497 8.45089 11.3877 8.48334C11.6256 8.51578 11.8679 8.4822 12.0881 8.38627C12.3082 8.29033 12.4978 8.13572 12.636 7.93935C12.7743 7.74297 12.8559 7.51238 12.8719 7.27276C12.888 7.03314 12.8379 6.79372 12.7271 6.58066C12.6163 6.3676 12.449 6.18909 12.2436 6.06464C12.0383 5.94018 11.8026 5.87458 11.5625 5.87499ZM7.18745 12C7.10092 12 7.01634 11.9743 6.94439 11.9263C6.87244 11.8782 6.81637 11.8099 6.78326 11.7299C6.75014 11.65 6.74148 11.562 6.75836 11.4771C6.77524 11.3923 6.81691 11.3143 6.87809 11.2531C6.93928 11.1919 7.01723 11.1503 7.1021 11.1334C7.18697 11.1165 7.27493 11.1252 7.35488 11.1583C7.43482 11.1914 7.50315 11.2475 7.55122 11.3194C7.59929 11.3914 7.62495 11.476 7.62495 11.5625C7.62486 11.6785 7.57874 11.7897 7.49671 11.8717C7.41468 11.9538 7.30346 11.9999 7.18745 12ZM7.18745 7.62499C7.10092 7.62499 7.01634 7.59933 6.94439 7.55126C6.87244 7.50319 6.81637 7.43486 6.78326 7.35491C6.75014 7.27497 6.74148 7.18701 6.75836 7.10214C6.77524 7.01727 6.81691 6.93932 6.87809 6.87813C6.93928 6.81695 7.01723 6.77528 7.1021 6.7584C7.18697 6.74152 7.27493 6.75018 7.35488 6.78329C7.43482 6.81641 7.50315 6.87248 7.55122 6.94443C7.59929 7.01638 7.62495 7.10096 7.62495 7.18749C7.62486 7.30349 7.57874 7.41472 7.49671 7.49675C7.41468 7.57877 7.30346 7.6249 7.18745 7.62499ZM11.5625 7.62499C11.4759 7.62499 11.3913 7.59933 11.3194 7.55126C11.2474 7.50319 11.1914 7.43486 11.1583 7.35491C11.1251 7.27497 11.1165 7.18701 11.1334 7.10214C11.1502 7.01727 11.1919 6.93932 11.2531 6.87813C11.3143 6.81695 11.3922 6.77528 11.4771 6.7584C11.562 6.74152 11.6499 6.75018 11.7299 6.78329C11.8098 6.81641 11.8781 6.87248 11.9262 6.94443C11.9743 7.01638 12 7.10096 12 7.18749C11.9999 7.30349 11.9537 7.41472 11.8717 7.49675C11.7897 7.57877 11.6785 7.6249 11.5625 7.62499Z"
|
|
24
|
+
fill="#D99000"
|
|
25
|
+
/>
|
|
26
|
+
</g>
|
|
27
|
+
</g>
|
|
28
|
+
</g>
|
|
29
|
+
<defs>
|
|
30
|
+
<clipPath id="clip0_319_602">
|
|
31
|
+
<rect width="24" height="24" fill="white" />
|
|
32
|
+
</clipPath>
|
|
33
|
+
<clipPath id="clip1_319_602">
|
|
34
|
+
<rect width="14" height="14" fill="white" transform="translate(5 5)" />
|
|
35
|
+
</clipPath>
|
|
36
|
+
</defs>
|
|
37
|
+
</svg>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Button, ClickableTile, Tile } from '@carbon/react';
|
|
5
|
+
import { TrashCan, Warning } from '@carbon/react/icons';
|
|
6
|
+
import { useLayoutType } from '@openmrs/esm-framework';
|
|
7
|
+
import styles from './procedures-order-basket-item-tile.scss';
|
|
8
|
+
import { type ProcedureOrderBasketItem } from '../../../types';
|
|
9
|
+
|
|
10
|
+
export interface OrderBasketItemTileProps {
|
|
11
|
+
orderBasketItem: ProcedureOrderBasketItem;
|
|
12
|
+
onItemClick: () => void;
|
|
13
|
+
onRemoveClick: () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function ProceduresOrderBasketItemTile({
|
|
17
|
+
orderBasketItem,
|
|
18
|
+
onItemClick,
|
|
19
|
+
onRemoveClick,
|
|
20
|
+
}: OrderBasketItemTileProps) {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
const isTablet = useLayoutType() === 'tablet';
|
|
23
|
+
|
|
24
|
+
// This here is really dirty, but required.
|
|
25
|
+
// If the ref's value is false, we won't react to the ClickableTile's handleClick function.
|
|
26
|
+
// Why is this necessary?
|
|
27
|
+
// The "Remove" button is nested inside the ClickableTile. If the button's clicked, the tile also raises the
|
|
28
|
+
// handleClick event later. Not sure if this is a bug, but this shouldn't be possible in our flows.
|
|
29
|
+
// Hence, we manually prevent the handleClick callback from being invoked as soon as the button is pressed once.
|
|
30
|
+
const shouldOnClickBeCalled = useRef(true);
|
|
31
|
+
|
|
32
|
+
const labTile = (
|
|
33
|
+
<div className={styles.orderBasketItemTile}>
|
|
34
|
+
<div className={styles.clipTextWithEllipsis}>
|
|
35
|
+
<OrderActionLabel orderBasketItem={orderBasketItem} />
|
|
36
|
+
<br />
|
|
37
|
+
<span className={styles.name}>{orderBasketItem.testType?.label}</span>
|
|
38
|
+
<span className={styles.label01}>
|
|
39
|
+
{!!orderBasketItem.orderError && (
|
|
40
|
+
<>
|
|
41
|
+
<br />
|
|
42
|
+
<span className={styles.orderErrorText}>
|
|
43
|
+
<Warning size={16} /> <span className={styles.label01}>{t('error', 'Error').toUpperCase()}</span>{' '}
|
|
44
|
+
|
|
45
|
+
{orderBasketItem.orderError.responseBody?.error?.message ?? orderBasketItem.orderError.message}
|
|
46
|
+
</span>
|
|
47
|
+
</>
|
|
48
|
+
)}
|
|
49
|
+
</span>
|
|
50
|
+
</div>
|
|
51
|
+
<Button
|
|
52
|
+
className={styles.removeButton}
|
|
53
|
+
kind="ghost"
|
|
54
|
+
hasIconOnly={true}
|
|
55
|
+
renderIcon={(props) => <TrashCan size={16} {...props} />}
|
|
56
|
+
iconDescription={t('removeFromBasket', 'Remove from basket')}
|
|
57
|
+
onClick={() => {
|
|
58
|
+
shouldOnClickBeCalled.current = false;
|
|
59
|
+
onRemoveClick();
|
|
60
|
+
}}
|
|
61
|
+
tooltipPosition="left"
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
return orderBasketItem.action === 'DISCONTINUE' ? (
|
|
67
|
+
<Tile>{labTile}</Tile>
|
|
68
|
+
) : (
|
|
69
|
+
<ClickableTile
|
|
70
|
+
role="listitem"
|
|
71
|
+
className={classNames({
|
|
72
|
+
[styles.clickableTileTablet]: isTablet,
|
|
73
|
+
[styles.clickableTileDesktop]: !isTablet,
|
|
74
|
+
})}
|
|
75
|
+
onClick={() => shouldOnClickBeCalled.current && onItemClick()}>
|
|
76
|
+
{labTile}
|
|
77
|
+
</ClickableTile>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function OrderActionLabel({ orderBasketItem }: { orderBasketItem: ProcedureOrderBasketItem }) {
|
|
82
|
+
const { t } = useTranslation();
|
|
83
|
+
|
|
84
|
+
if (orderBasketItem.isOrderIncomplete) {
|
|
85
|
+
return <span className={styles.orderActionIncompleteLabel}>{t('orderActionIncomplete', 'Incomplete')}</span>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
switch (orderBasketItem.action) {
|
|
89
|
+
case 'NEW':
|
|
90
|
+
return <span className={styles.orderActionNewLabel}>{t('orderActionNew', 'New')}</span>;
|
|
91
|
+
case 'RENEW':
|
|
92
|
+
return <span className={styles.orderActionRenewLabel}>{t('orderActionRenew', 'Renew')}</span>;
|
|
93
|
+
case 'REVISE':
|
|
94
|
+
return <span className={styles.orderActionRevisedLabel}>{t('orderActionRevise', 'Modify')}</span>;
|
|
95
|
+
case 'DISCONTINUE':
|
|
96
|
+
return <span className={styles.orderActionDiscontinueLabel}>{t('orderActionDiscontinue', 'Discontinue')}</span>;
|
|
97
|
+
default:
|
|
98
|
+
return <></>;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
@use '@carbon/styles/scss/spacing';
|
|
2
|
+
@use '@carbon/styles/scss/type';
|
|
3
|
+
@use '@openmrs/esm-styleguide/src/vars' as vars;
|
|
4
|
+
|
|
5
|
+
.clickableTileDesktop {
|
|
6
|
+
padding: 0.5rem 0.75rem;
|
|
7
|
+
border-bottom: 1px solid vars.$ui-03;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.clickableTileTablet {
|
|
11
|
+
padding: 0.75rem 1rem;
|
|
12
|
+
background-color: vars.$ui-02;
|
|
13
|
+
border-bottom: 1px solid vars.$ui-03;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.orderBasketItemTile {
|
|
17
|
+
display: flex;
|
|
18
|
+
justify-content: space-between;
|
|
19
|
+
align-items: baseline;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.label {
|
|
23
|
+
display: inline-block;
|
|
24
|
+
@include type.type-style('label-01');
|
|
25
|
+
margin-bottom: 0.5rem;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.orderActionNewLabel {
|
|
29
|
+
@extend .label;
|
|
30
|
+
color: black;
|
|
31
|
+
background-color: #c4f4cc;
|
|
32
|
+
padding: 0 0.25rem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.orderActionIncompleteLabel {
|
|
36
|
+
@extend .label;
|
|
37
|
+
color: white;
|
|
38
|
+
background-color: vars.$danger;
|
|
39
|
+
padding: 0 0.25rem;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.orderActionRenewLabel {
|
|
43
|
+
@extend .label;
|
|
44
|
+
color: vars.$support-02;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.orderActionRevisedLabel {
|
|
48
|
+
@extend .label;
|
|
49
|
+
color: #943d00;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.orderActionDiscontinueLabel {
|
|
53
|
+
@extend .label;
|
|
54
|
+
color: vars.$danger;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.orderErrorText {
|
|
58
|
+
color: vars.$danger;
|
|
59
|
+
display: flex;
|
|
60
|
+
align-items: center;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.name {
|
|
64
|
+
@include type.type-style('heading-compact-01');
|
|
65
|
+
color: black;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.removeButton {
|
|
69
|
+
svg {
|
|
70
|
+
fill: vars.$danger !important;
|
|
71
|
+
}
|
|
72
|
+
}
|