@kenyaemr/esm-service-queues-app 8.1.1-pre.129 → 8.1.2-pre.152

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 (256) hide show
  1. package/.turbo/turbo-build.log +26 -26
  2. package/dist/1006.js +1 -0
  3. package/dist/1006.js.map +1 -0
  4. package/dist/1060.js +1 -0
  5. package/dist/1060.js.map +1 -0
  6. package/dist/130.js +1 -1
  7. package/dist/130.js.map +1 -1
  8. package/dist/1325.js +1 -0
  9. package/dist/1325.js.map +1 -0
  10. package/dist/1644.js +1 -0
  11. package/dist/1727.js +1 -0
  12. package/dist/1727.js.map +1 -0
  13. package/dist/1800.js +1 -0
  14. package/dist/1800.js.map +1 -0
  15. package/dist/236.js +1 -1
  16. package/dist/2757.js +1 -0
  17. package/dist/{282.js → 2760.js} +1 -1
  18. package/dist/2760.js.map +1 -0
  19. package/dist/2784.js +2 -0
  20. package/dist/2784.js.map +1 -0
  21. package/dist/3199.js +1 -0
  22. package/dist/3199.js.map +1 -0
  23. package/dist/3372.js +2 -0
  24. package/dist/3372.js.map +1 -0
  25. package/dist/3574.js +1 -0
  26. package/dist/3604.js +1 -0
  27. package/dist/3604.js.map +1 -0
  28. package/dist/3652.js +1 -0
  29. package/dist/3760.js +1 -0
  30. package/dist/3760.js.map +1 -0
  31. package/dist/3818.js +1 -0
  32. package/dist/3818.js.map +1 -0
  33. package/dist/3828.js +1 -0
  34. package/dist/3828.js.map +1 -0
  35. package/dist/4272.js +1 -0
  36. package/dist/4378.js +1 -0
  37. package/dist/443.js +1 -0
  38. package/dist/443.js.map +1 -0
  39. package/dist/4460.js +1 -0
  40. package/dist/4705.js +1 -0
  41. package/dist/4911.js +1 -0
  42. package/dist/4911.js.map +1 -0
  43. package/dist/5236.js +1 -0
  44. package/dist/5236.js.map +1 -0
  45. package/dist/5240.js +1 -0
  46. package/dist/5282.js +1 -0
  47. package/dist/5282.js.map +1 -0
  48. package/dist/5336.js +1 -0
  49. package/dist/539.js +1 -0
  50. package/dist/5673.js +1 -0
  51. package/dist/5711.js +1 -0
  52. package/dist/5737.js +1 -0
  53. package/dist/5833.js +1 -0
  54. package/dist/6566.js +1 -0
  55. package/dist/6578.js +2 -0
  56. package/dist/{660.js.LICENSE.txt → 6578.js.LICENSE.txt} +5 -0
  57. package/dist/6578.js.map +1 -0
  58. package/dist/6591.js +2 -0
  59. package/dist/6591.js.map +1 -0
  60. package/dist/6670.js +1 -0
  61. package/dist/6670.js.map +1 -0
  62. package/dist/6727.js +1 -0
  63. package/dist/744.js +1 -0
  64. package/dist/752.js +1 -1
  65. package/dist/752.js.map +1 -1
  66. package/dist/7807.js +1 -0
  67. package/dist/8271.js +1 -0
  68. package/dist/8319.js +1 -0
  69. package/dist/8788.js +1 -0
  70. package/dist/899.js +1 -0
  71. package/dist/9261.js +1 -0
  72. package/dist/9392.js +1 -0
  73. package/dist/9392.js.map +1 -0
  74. package/dist/9993.js +1 -0
  75. package/dist/9993.js.map +1 -0
  76. package/dist/kenyaemr-esm-service-queues-app.js +1 -1
  77. package/dist/kenyaemr-esm-service-queues-app.js.buildmanifest.json +541 -234
  78. package/dist/kenyaemr-esm-service-queues-app.js.map +1 -1
  79. package/dist/main.js +1 -1
  80. package/dist/main.js.LICENSE.txt +5 -0
  81. package/dist/main.js.map +1 -1
  82. package/dist/routes.json +1 -1
  83. package/package-lock.json +2 -2
  84. package/package.json +8 -5
  85. package/src/active-visits/active-visits-table.resource.ts +0 -62
  86. package/src/active-visits/change-status-dialog.component.tsx +10 -3
  87. package/src/active-visits/change-status-dialog.scss +29 -1
  88. package/src/active-visits/change-status-dialog.test.tsx +11 -3
  89. package/src/add-provider-queue-room/add-provider-queue-room.component.tsx +53 -54
  90. package/src/add-provider-queue-room/add-provider-queue-room.scss +28 -0
  91. package/src/add-provider-queue-room/add-provider-queue-room.test.tsx +1 -1
  92. package/src/clear-queue-entries-dialog/clear-queue-entries-dialog.component.tsx +1 -0
  93. package/src/clear-queue-entries-dialog/clear-queue-entries-dialog.scss +29 -0
  94. package/src/clear-queue-entries-dialog/clear-queue-entries-dialog.test.tsx +4 -1
  95. package/src/config-schema.ts +28 -8
  96. package/src/create-queue-entry/create-queue-entry.workspace.tsx +99 -0
  97. package/src/create-queue-entry/existing-visit-form/existing-visit-form.component.tsx +73 -0
  98. package/src/{patient-search/visit-form-queue-fields/visit-form-queue-fields.component.tsx → create-queue-entry/queue-fields/queue-fields.component.tsx} +76 -50
  99. package/src/create-queue-entry/queue-fields/queue-fields.resource.ts +63 -0
  100. package/src/{patient-search/visit-form-queue-fields/visit-form-queue-fields.scss → create-queue-entry/queue-fields/queue-fields.scss} +0 -4
  101. package/src/{patient-search/visit-form-queue-fields/visit-form-queue-fields.test.tsx → create-queue-entry/queue-fields/queue-fields.test.tsx} +37 -17
  102. package/src/create-queue-entry/queue-fields/visit-form-queue-fields.extension.tsx +31 -0
  103. package/src/hooks/useQueueEntries.ts +13 -12
  104. package/src/index.ts +8 -14
  105. package/src/patient-info/patient-info.component.tsx +10 -8
  106. package/src/patient-queue-header/patient-queue-header.component.tsx +18 -13
  107. package/src/patient-queue-metrics/metrics-header.component.tsx +4 -4
  108. package/src/queue-entry-table-components/queue-priority.component.tsx +16 -11
  109. package/src/queue-entry-table-components/queue-priority.scss +5 -0
  110. package/src/queue-entry-table-components/transition-entry.component.tsx +1 -1
  111. package/src/queue-patient-linelists/queue-linelist-base-table.component.tsx +1 -1
  112. package/src/queue-patient-linelists/queue-linelist-filter.workspace.tsx +13 -12
  113. package/src/queue-patient-linelists/scheduled-appointments-table.component.tsx +1 -1
  114. package/src/queue-rooms/queue-room-form.test.tsx +2 -2
  115. package/src/queue-rooms/queue-room-form.workspace.tsx +1 -1
  116. package/src/queue-screen/queue-screen.test.tsx +11 -4
  117. package/src/queue-services/queue-service-form.test.tsx +76 -16
  118. package/src/queue-services/queue-service-form.workspace.tsx +131 -131
  119. package/src/queue-services/queue-service.resource.ts +7 -2
  120. package/src/queue-table/cells/columns.resource.ts +10 -7
  121. package/src/queue-table/cells/queue-table-visit-attribute-queue-number-cell.component.tsx +1 -0
  122. package/src/queue-table/default-queue-table.component.tsx +12 -13
  123. package/src/queue-table/default-queue-table.test.tsx +3 -3
  124. package/src/queue-table/queue-entry-actions/queue-entry-actions-modal.scss +28 -0
  125. package/src/queue-table/queue-entry-actions/queue-entry-actions.modal.tsx +8 -2
  126. package/src/queue-table/queue-entry-actions/queue-entry-confirm-action.modal.tsx +2 -1
  127. package/src/queue-table/queue-entry-actions/queue-entry-confirm-action.scss +29 -0
  128. package/src/queue-table/queue-table.component.tsx +1 -1
  129. package/src/queue-table/queue-table.scss +12 -2
  130. package/src/queue-table/queue-table.test.tsx +10 -1
  131. package/src/remove-queue-entry-dialog/remove-queue-entry.component.tsx +16 -4
  132. package/src/remove-queue-entry-dialog/remove-queue-entry.scss +29 -0
  133. package/src/routes.json +4 -8
  134. package/src/transition-latest-queue-entry/transition-latest-queue-entry.resource.ts +2 -10
  135. package/src/transition-queue-entry/transition-queue-entry-dialog.component.tsx +41 -32
  136. package/src/transition-queue-entry/transition-queue-entry-dialog.scss +28 -0
  137. package/src/types/index.ts +0 -8
  138. package/src/views/queue-tables-for-all-statuses.component.tsx +12 -15
  139. package/translations/am.json +5 -78
  140. package/translations/ar.json +5 -78
  141. package/translations/de.json +235 -0
  142. package/translations/en.json +9 -86
  143. package/translations/es.json +3 -76
  144. package/translations/fr.json +5 -78
  145. package/translations/he.json +5 -78
  146. package/translations/hi.json +235 -0
  147. package/translations/hi_IN.json +235 -0
  148. package/translations/id.json +235 -0
  149. package/translations/it.json +235 -0
  150. package/translations/km.json +5 -78
  151. package/translations/ne.json +235 -0
  152. package/translations/pt.json +235 -0
  153. package/translations/pt_BR.json +235 -0
  154. package/translations/qu.json +235 -0
  155. package/translations/si.json +235 -0
  156. package/translations/sw.json +235 -0
  157. package/translations/sw_KE.json +235 -0
  158. package/translations/tr.json +235 -0
  159. package/translations/tr_TR.json +235 -0
  160. package/translations/uk.json +235 -0
  161. package/translations/vi.json +235 -0
  162. package/translations/zh.json +6 -79
  163. package/translations/zh_CN.json +5 -78
  164. package/dist/169.js +0 -1
  165. package/dist/169.js.map +0 -1
  166. package/dist/199.js +0 -1
  167. package/dist/199.js.map +0 -1
  168. package/dist/236.js.map +0 -1
  169. package/dist/271.js +0 -1
  170. package/dist/282.js.map +0 -1
  171. package/dist/319.js +0 -1
  172. package/dist/325.js +0 -1
  173. package/dist/325.js.map +0 -1
  174. package/dist/366.js +0 -1
  175. package/dist/366.js.map +0 -1
  176. package/dist/372.js +0 -2
  177. package/dist/372.js.map +0 -1
  178. package/dist/392.js +0 -1
  179. package/dist/392.js.map +0 -1
  180. package/dist/460.js +0 -1
  181. package/dist/501.js +0 -1
  182. package/dist/501.js.map +0 -1
  183. package/dist/574.js +0 -1
  184. package/dist/591.js +0 -2
  185. package/dist/591.js.map +0 -1
  186. package/dist/6.js +0 -1
  187. package/dist/6.js.map +0 -1
  188. package/dist/60.js +0 -1
  189. package/dist/60.js.map +0 -1
  190. package/dist/604.js +0 -1
  191. package/dist/604.js.map +0 -1
  192. package/dist/644.js +0 -1
  193. package/dist/660.js +0 -2
  194. package/dist/660.js.map +0 -1
  195. package/dist/670.js +0 -1
  196. package/dist/670.js.map +0 -1
  197. package/dist/727.js +0 -1
  198. package/dist/727.js.map +0 -1
  199. package/dist/748.js +0 -1
  200. package/dist/748.js.map +0 -1
  201. package/dist/757.js +0 -1
  202. package/dist/760.js +0 -1
  203. package/dist/760.js.map +0 -1
  204. package/dist/784.js +0 -2
  205. package/dist/784.js.map +0 -1
  206. package/dist/788.js +0 -1
  207. package/dist/800.js +0 -1
  208. package/dist/800.js.map +0 -1
  209. package/dist/807.js +0 -1
  210. package/dist/818.js +0 -1
  211. package/dist/818.js.map +0 -1
  212. package/dist/828.js +0 -1
  213. package/dist/828.js.map +0 -1
  214. package/dist/833.js +0 -1
  215. package/dist/911.js +0 -1
  216. package/dist/911.js.map +0 -1
  217. package/dist/940.js +0 -1
  218. package/dist/940.js.map +0 -1
  219. package/src/add-patient-toqueue/add-patient-toqueue-dialog.component.tsx +0 -228
  220. package/src/add-patient-toqueue/add-patient-toqueue-dialog.scss +0 -32
  221. package/src/patient-search/advanced-search.component.tsx +0 -191
  222. package/src/patient-search/advanced-search.scss +0 -154
  223. package/src/patient-search/advanced-search.test.tsx +0 -26
  224. package/src/patient-search/basic-search.component.tsx +0 -112
  225. package/src/patient-search/basic-search.scss +0 -139
  226. package/src/patient-search/basic-search.test.tsx +0 -18
  227. package/src/patient-search/empty-data-illustration.component.tsx +0 -41
  228. package/src/patient-search/hooks/useActivePatientEnrollment.tsx +0 -29
  229. package/src/patient-search/hooks/useDefaultLocation.ts +0 -14
  230. package/src/patient-search/hooks/usePatients.tsx +0 -25
  231. package/src/patient-search/hooks/useRecommendedVisitTypes.tsx +0 -35
  232. package/src/patient-search/hooks/useScheduledVisits.ts +0 -52
  233. package/src/patient-search/patient-scheduled-visits.component.tsx +0 -315
  234. package/src/patient-search/patient-scheduled-visits.scss +0 -131
  235. package/src/patient-search/patient-scheduled-visits.test.tsx +0 -39
  236. package/src/patient-search/patient-search.workspace.tsx +0 -135
  237. package/src/patient-search/search-illustration.component.tsx +0 -27
  238. package/src/patient-search/search-results.component.tsx +0 -75
  239. package/src/patient-search/search-results.scss +0 -80
  240. package/src/patient-search/search-results.test.tsx +0 -69
  241. package/src/patient-search/search.resource.ts +0 -10
  242. package/src/patient-search/visit-form/existing-visit-form.component.tsx +0 -112
  243. package/src/patient-search/visit-form/queue.resource.ts +0 -64
  244. package/src/patient-search/visit-form/visit-form.component.tsx +0 -337
  245. package/src/patient-search/visit-form/visit-type-selector.component.tsx +0 -153
  246. package/src/patient-search/visit-form/visit-type-selector.scss +0 -100
  247. package/src/patient-search/visit-form/visit-type-selector.test.tsx +0 -84
  248. package/src/visits-missing-inqueue/visits-missing-inqueue.component.tsx +0 -277
  249. package/src/visits-missing-inqueue/visits-missing-inqueue.resource.ts +0 -93
  250. package/src/visits-missing-inqueue/visits-missing-inqueue.scss +0 -111
  251. /package/dist/{784.js.LICENSE.txt → 2784.js.LICENSE.txt} +0 -0
  252. /package/dist/{372.js.LICENSE.txt → 3372.js.LICENSE.txt} +0 -0
  253. /package/dist/{591.js.LICENSE.txt → 6591.js.LICENSE.txt} +0 -0
  254. /package/src/{patient-search/patient-search.scss → create-queue-entry/create-queue-entry.scss} +0 -0
  255. /package/src/{patient-search/visit-form/visit-form.scss → create-queue-entry/existing-visit-form/existing-visit-form.scss} +0 -0
  256. /package/src/{patient-search → create-queue-entry}/hooks/useQueueLocations.tsx +0 -0
@@ -1,315 +0,0 @@
1
- import React, { useCallback, useEffect, useState } from 'react';
2
- import dayjs from 'dayjs';
3
- import head from 'lodash-es/head';
4
- import { useTranslation } from 'react-i18next';
5
- import {
6
- Button,
7
- ButtonSet,
8
- ContentSwitcher,
9
- DataTableSkeleton,
10
- InlineLoading,
11
- InlineNotification,
12
- RadioTile,
13
- Switch,
14
- TileGroup,
15
- } from '@carbon/react';
16
- import {
17
- formatDatetime,
18
- type NewVisitPayload,
19
- parseDate,
20
- saveVisit,
21
- showSnackbar,
22
- toDateObjectStrict,
23
- toOmrsIsoString,
24
- useConfig,
25
- useLayoutType,
26
- useLocations,
27
- useSession,
28
- useVisit,
29
- useVisitTypes,
30
- } from '@openmrs/esm-framework';
31
- import { type Appointment, SearchTypes } from '../types';
32
- import { postQueueEntry } from './visit-form/queue.resource';
33
- import { convertTime12to24 } from '../helpers/time-helpers';
34
- import { useQueueLocations } from './hooks/useQueueLocations';
35
- import { useQueues } from '../hooks/useQueues';
36
- import { useMutateQueueEntries } from '../hooks/useQueueEntries';
37
- import { type ConfigObject } from '../config-schema';
38
- import styles from './patient-scheduled-visits.scss';
39
-
40
- enum visitType {
41
- RECENT = 'Recent',
42
- FUTURE = 'Future',
43
- }
44
-
45
- const ScheduledVisitsForVisitType: React.FC<{
46
- visits;
47
- visitType;
48
- scheduledVisitHeader;
49
- patientUuid;
50
- closeWorkspace: () => void;
51
- }> = ({ visits, scheduledVisitHeader, patientUuid, closeWorkspace }) => {
52
- const { t } = useTranslation();
53
- const [visitsIndex, setVisitsIndex] = useState(0);
54
- const [hasPriority, setHasPriority] = useState(false);
55
- const [userLocation, setUserLocation] = useState('');
56
- const locations = useLocations();
57
- const session = useSession();
58
- const { queues, isLoading: isLoadingQueues } = useQueues(userLocation);
59
- const { mutateQueueEntries } = useMutateQueueEntries();
60
- const [isSubmitting, setIsSubmitting] = useState(false);
61
- const timeFormat = new Date().getHours() >= 12 ? 'PM' : 'AM';
62
- const visitDate = new Date();
63
- const visitTime = dayjs(new Date()).format('hh:mm');
64
- const [appointment, setAppointment] = useState<Appointment>();
65
- const [patientId, setPatientId] = useState('');
66
- const allVisitTypes = useVisitTypes();
67
- const { currentVisit } = useVisit(patientUuid);
68
- const config = useConfig<ConfigObject>();
69
- const visitQueueNumberAttributeUuid = config.visitQueueNumberAttributeUuid;
70
- const { queueLocations } = useQueueLocations();
71
- const selectedQueueLocation = queueLocations[0]?.id;
72
-
73
- // TODO: This needs fixing, we cannot just take the first queue and assume that is what is wanted
74
- const service = head(queues)?.uuid;
75
- const defaultStatus = config.concepts.defaultStatusConceptUuid;
76
- const priorities = queues.find((q) => q.uuid === service)?.allowedPriorities ?? [];
77
-
78
- useEffect(() => {
79
- if (!userLocation && session?.sessionLocation !== null) {
80
- setUserLocation(session?.sessionLocation?.uuid);
81
- } else if (!userLocation && locations) {
82
- setUserLocation(head(locations)?.uuid);
83
- }
84
- }, [session, locations, userLocation]);
85
-
86
- const handleSubmit = useCallback(
87
- (priority) => {
88
- setIsSubmitting(true);
89
- const [hours, minutes] = convertTime12to24(visitTime, timeFormat);
90
- const visitType = [...allVisitTypes].shift().uuid;
91
-
92
- const payload: NewVisitPayload = {
93
- patient: patientId,
94
- startDatetime: toDateObjectStrict(
95
- toOmrsIsoString(
96
- new Date(dayjs(visitDate).year(), dayjs(visitDate).month(), dayjs(visitDate).date(), hours, minutes),
97
- ),
98
- ),
99
- visitType: visitType,
100
- location: userLocation,
101
- };
102
-
103
- if (currentVisit) {
104
- showSnackbar({
105
- title: t('startVisitError', 'Error starting visit'),
106
- kind: 'error',
107
- isLowContrast: false,
108
- subtitle: t('patientHasActiveVisit', 'The patient already has an active visit'),
109
- });
110
- setIsSubmitting(false);
111
- } else {
112
- const abortController = new AbortController();
113
-
114
- saveVisit(payload, abortController)
115
- .then((response) => {
116
- postQueueEntry(
117
- response.data.uuid,
118
- patientId,
119
- priority,
120
- defaultStatus,
121
- service,
122
- appointment,
123
- selectedQueueLocation,
124
- visitQueueNumberAttributeUuid,
125
- )
126
- .then(() => {
127
- showSnackbar({
128
- kind: 'success',
129
- title: t('startAVisit', 'Start a visit'),
130
- subtitle: t(
131
- 'startVisitQueueSuccessfully',
132
- 'Patient has been added to active visits list and queue.',
133
- `${hours} : ${minutes}`,
134
- ),
135
- });
136
- closeWorkspace();
137
- setIsSubmitting(false);
138
- mutateQueueEntries();
139
- })
140
- .catch((error) => {
141
- showSnackbar({
142
- title: t('queueEntryError', 'Error adding patient to the queue'),
143
- kind: 'error',
144
- isLowContrast: false,
145
- subtitle: error?.message,
146
- });
147
- setIsSubmitting(false);
148
- });
149
- })
150
- .catch((error) => {
151
- showSnackbar({
152
- title: t('startVisitError', 'Error starting visit'),
153
- kind: 'error',
154
- isLowContrast: false,
155
- subtitle: error?.message,
156
- });
157
- setIsSubmitting(false);
158
- });
159
- }
160
- },
161
- [
162
- visitTime,
163
- timeFormat,
164
- allVisitTypes,
165
- patientId,
166
- visitDate,
167
- userLocation,
168
- queues,
169
- config.concepts.defaultStatusConceptUuid,
170
- config.concepts.defaultPriorityConceptUuid,
171
- currentVisit,
172
- t,
173
- priorities,
174
- appointment,
175
- selectedQueueLocation,
176
- visitQueueNumberAttributeUuid,
177
- closeWorkspace,
178
- mutateQueueEntries,
179
- ],
180
- );
181
-
182
- if (visits) {
183
- return (
184
- <div className={styles.row}>
185
- <p className={styles.heading}>{scheduledVisitHeader} </p>
186
- {visits?.length > 0 ? (
187
- <TileGroup name="tile-group" defaultSelected="default-selected">
188
- {visits?.map((visit, ind) => {
189
- return (
190
- <RadioTile
191
- value={visit.uuid}
192
- key={visit.uuid}
193
- className={styles.visitTile}
194
- onClick={(e) => {
195
- setHasPriority(true);
196
- setVisitsIndex(ind);
197
- setPatientId(visit?.patient?.uuid);
198
- setAppointment(visit);
199
- }}>
200
- <div className={styles.helperText}>
201
- <p className={styles.primaryText}>{visit.service?.name}</p>
202
- <p className={styles.secondaryText}>
203
- {' '}
204
- {formatDatetime(parseDate(visit?.startDateTime))} · {visit.location?.name}{' '}
205
- </p>
206
-
207
- {!visit.service ? (
208
- <DataTableSkeleton />
209
- ) : isLoadingQueues ? null : !priorities?.length ? (
210
- <InlineNotification
211
- className={styles.inlineNotification}
212
- kind={'error'}
213
- lowContrast
214
- subtitle={t('configurePriorities', 'Please configure priorities to continue.')}
215
- title={t('noPrioritiesConfigured', 'No priorities configured')}
216
- />
217
- ) : hasPriority && ind == visitsIndex ? (
218
- <ContentSwitcher
219
- size="sm"
220
- selectedIndex={null}
221
- className={styles.prioritySwitcher}
222
- onChange={(e) => {
223
- handleSubmit(e.name);
224
- }}>
225
- {priorities?.length > 0
226
- ? priorities.map(({ uuid, display }) => {
227
- return <Switch name={uuid} text={display} />;
228
- })
229
- : null}
230
- </ContentSwitcher>
231
- ) : null}
232
- {hasPriority && ind == visitsIndex && isSubmitting ? (
233
- <InlineLoading description={t('loading', 'Loading...')} />
234
- ) : null}
235
- </div>
236
- </RadioTile>
237
- );
238
- })}
239
- </TileGroup>
240
- ) : (
241
- <div className={styles.emptyAppointment}>
242
- <p>{t('noAppointmentsFound', 'No appointments found')} </p>
243
- </div>
244
- )}
245
- </div>
246
- );
247
- }
248
- return (
249
- <div className={styles.emptyAppointment}>
250
- <p className={styles.heading}> {scheduledVisitHeader} </p>
251
- </div>
252
- );
253
- };
254
-
255
- interface PatientScheduledVisitsProps {
256
- appointments: { recentVisits: Appointment[]; futureVisits: Appointment[] };
257
- toggleSearchType: (searchMode: SearchTypes) => void;
258
- patientUuid: string;
259
- closeWorkspace: () => void;
260
- }
261
-
262
- const PatientScheduledVisits: React.FC<PatientScheduledVisitsProps> = ({
263
- appointments,
264
- toggleSearchType,
265
- patientUuid,
266
- closeWorkspace,
267
- }) => {
268
- const { t } = useTranslation();
269
- const isTablet = useLayoutType() === 'tablet';
270
-
271
- return (
272
- <div className={styles.container}>
273
- <ScheduledVisitsForVisitType
274
- visitType={visitType.RECENT}
275
- visits={appointments?.recentVisits}
276
- scheduledVisitHeader={t('recentScheduledVisits', '{{count}} visit(s) scheduled for +/- 7 days', {
277
- count: appointments?.recentVisits?.length,
278
- })}
279
- patientUuid={patientUuid}
280
- closeWorkspace={closeWorkspace}
281
- />
282
- <ScheduledVisitsForVisitType
283
- visitType={visitType.FUTURE}
284
- visits={appointments?.futureVisits}
285
- scheduledVisitHeader={t('futureScheduledVisits', '{{count}} visit(s) scheduled for dates in the future', {
286
- count: appointments?.futureVisits?.length,
287
- })}
288
- patientUuid={patientUuid}
289
- closeWorkspace={closeWorkspace}
290
- />
291
-
292
- <div className={styles['text-divider']}>{t('orInProperFormat', 'Or')}</div>
293
-
294
- <div className={styles.buttonContainer}>
295
- <Button
296
- kind="ghost"
297
- iconDescription="Start another visit type"
298
- onClick={() => toggleSearchType(SearchTypes.VISIT_FORM)}>
299
- {t('anotherVisitType', 'Start another visit type')}
300
- </Button>
301
- </div>
302
-
303
- <ButtonSet className={isTablet ? styles.tablet : styles.desktop}>
304
- <Button className={styles.button} kind="secondary" onClick={() => toggleSearchType(SearchTypes.SEARCH_RESULTS)}>
305
- {t('cancel', 'Cancel')}
306
- </Button>
307
- <Button className={styles.button} kind="primary" type="submit">
308
- {t('search', 'Search')}
309
- </Button>
310
- </ButtonSet>
311
- </div>
312
- );
313
- };
314
-
315
- export default PatientScheduledVisits;
@@ -1,131 +0,0 @@
1
- @use '@carbon/layout';
2
- @use '@carbon/type';
3
- @use '@openmrs/esm-styleguide/src/vars' as *;
4
-
5
- .container {
6
- background-color: $ui-background;
7
- display: flex;
8
- flex-direction: column;
9
- justify-content: space-between;
10
- height: 100%;
11
- }
12
-
13
- .grid {
14
- padding: 0;
15
- }
16
-
17
- .visitTile {
18
- margin: layout.$spacing-05 0;
19
-
20
- &:global(.cds--tile--is-selected:focus) {
21
- background-color: $color-blue-10;
22
- color: $color-blue-10;
23
- border: 1px solid $color-blue-60-2;
24
- outline: none;
25
- }
26
-
27
- &:global(.cds--tile--is-selected:hover) {
28
- background-color: $color-blue-10;
29
- color: $color-blue-10;
30
- border: 1px solid $color-blue-60-2;
31
- outline: none;
32
- }
33
-
34
- &:global(.cds--tile--is-selected:hover .cds--tile__checkmark svg) {
35
- fill: $color-blue-60-2;
36
- }
37
- }
38
-
39
- .recentlyScheduledVisitsContainer {
40
- margin-top: layout.$spacing-06;
41
- margin-bottom: layout.$spacing-10;
42
- }
43
-
44
- .row {
45
- margin: 0 layout.$spacing-05 layout.$spacing-05 layout.$spacing-05;
46
- }
47
-
48
- .backButton {
49
- align-items: center;
50
- display: flex;
51
- justify-content: flex-start;
52
- margin: layout.$spacing-03 0;
53
- padding: 0;
54
- @include type.type-style('body-compact-01');
55
-
56
- button {
57
- display: flex;
58
-
59
- svg {
60
- order: 1;
61
- margin-right: layout.$spacing-03;
62
- margin-left: 0 !important;
63
- }
64
-
65
- span {
66
- order: 2;
67
- }
68
- }
69
- }
70
-
71
- .heading {
72
- @include type.type-style('body-02');
73
- color: $text-02;
74
- margin-left: 1.2rem;
75
- }
76
-
77
- .primaryText {
78
- @include type.type-style('heading-compact-02');
79
- }
80
-
81
- .secondaryText {
82
- @include type.type-style('body-01');
83
- color: $text-02;
84
- }
85
-
86
- .button {
87
- height: layout.$spacing-10;
88
- display: flex;
89
- align-content: flex-start;
90
- align-items: baseline;
91
- min-width: 50%;
92
- }
93
-
94
- .text-divider {
95
- display: flex;
96
- align-items: center;
97
- margin: layout.$spacing-08 25%;
98
- @include type.type-style('heading-03');
99
- color: $text-02;
100
- }
101
-
102
- .text-divider::before,
103
- .text-divider::after {
104
- content: '';
105
- height: 1px;
106
- background-color: $text-03;
107
- flex-grow: 1;
108
- }
109
-
110
- .text-divider::before {
111
- margin-right: layout.$spacing-05;
112
- }
113
-
114
- .text-divider::after {
115
- margin-left: layout.$spacing-05;
116
- }
117
-
118
- .buttonContainer {
119
- display: flex;
120
- align-items: center;
121
- justify-content: center;
122
- margin-bottom: layout.$spacing-03;
123
- }
124
-
125
- .prioritySwitcher {
126
- margin: layout.$spacing-03 0 layout.$spacing-03;
127
- }
128
-
129
- .emptyAppointment {
130
- margin: layout.$spacing-05;
131
- }
@@ -1,39 +0,0 @@
1
- import React from 'react';
2
- import { screen } from '@testing-library/react';
3
- import { getDefaultsFromConfigSchema, useConfig, useLocations, useSession } from '@openmrs/esm-framework';
4
- import { renderWithSwr } from 'tools';
5
- import { type ConfigObject, configSchema } from '../config-schema';
6
- import { mockLocations, mockPatient, mockPatientsVisits, mockSession } from '__mocks__';
7
- import PatientScheduledVisits from './patient-scheduled-visits.component';
8
-
9
- const mockUseConfig = jest.mocked(useConfig<ConfigObject>);
10
- const mockToggleSearchType = jest.fn();
11
- const mockUseLocations = useLocations as jest.Mock;
12
- const mockUseSession = jest.mocked(useSession);
13
-
14
- const defaultProps = {
15
- appointments: { recentVisits: mockPatientsVisits.recentVisits, futureVisits: [] },
16
- closePanel: () => false,
17
- closeWorkspace: jest.fn(),
18
- patientUuid: mockPatient.uuid,
19
- toggleSearchType: mockToggleSearchType,
20
- };
21
-
22
- describe('ScheduledVisits', () => {
23
- beforeEach(() => {
24
- mockUseConfig.mockReturnValue({
25
- ...getDefaultsFromConfigSchema(configSchema),
26
- concepts: {},
27
- } as ConfigObject);
28
- mockUseLocations.mockReturnValue(mockLocations.data.results);
29
- mockUseSession.mockReturnValue(mockSession.data);
30
- });
31
-
32
- it('should display recent and future scheduled visits', async () => {
33
- renderWithSwr(<PatientScheduledVisits {...defaultProps} />);
34
-
35
- expect(screen.getByText(/Cardiology Consultation 1/i)).toBeInTheDocument();
36
- expect(screen.getByText(/08-Aug-2022, 02:56 PM · 10 Engineer VCT/i)).toBeInTheDocument();
37
- expect(screen.getByText(/No appointments found/i)).toBeInTheDocument();
38
- });
39
- });
@@ -1,135 +0,0 @@
1
- import React, { useEffect, useState } from 'react';
2
-
3
- import { SearchTypes } from '../types';
4
- import PatientScheduledVisits from './patient-scheduled-visits.component';
5
- import VisitForm from './visit-form/visit-form.component';
6
- import {
7
- type DefaultWorkspaceProps,
8
- ArrowLeftIcon,
9
- ErrorState,
10
- getPatientName,
11
- PatientBannerContactDetails,
12
- PatientBannerPatientInfo,
13
- PatientBannerToggleContactDetailsButton,
14
- PatientPhoto,
15
- usePatient,
16
- useVisit,
17
- } from '@openmrs/esm-framework';
18
- import ExistingVisitFormComponent from './visit-form/existing-visit-form.component';
19
- import styles from './patient-search.scss';
20
- import { Button, DataTableSkeleton } from '@carbon/react';
21
- import { useScheduledVisits } from './hooks/useScheduledVisits';
22
- import isNil from 'lodash-es/isNil';
23
- import { useTranslation } from 'react-i18next';
24
-
25
- interface PatientSearchProps extends DefaultWorkspaceProps {
26
- selectedPatientUuid: string;
27
- currentServiceQueueUuid?: string;
28
- handleBackToSearchList?: () => void;
29
- }
30
-
31
- export const AddPatientToQueueContext = React.createContext({
32
- currentServiceQueueUuid: '',
33
- });
34
-
35
- const PatientSearch: React.FC<PatientSearchProps> = ({
36
- closeWorkspace,
37
- selectedPatientUuid,
38
- currentServiceQueueUuid,
39
- handleBackToSearchList,
40
- }) => {
41
- const { t } = useTranslation();
42
- const { patient } = usePatient(selectedPatientUuid);
43
- const { activeVisit } = useVisit(selectedPatientUuid);
44
- const [searchType, setSearchType] = useState<SearchTypes>(SearchTypes.SCHEDULED_VISITS);
45
- const [showContactDetails, setContactDetails] = useState(false);
46
- const { appointments, isLoading, error } = useScheduledVisits(selectedPatientUuid);
47
-
48
- const hasAppointments = !(isNil(appointments?.futureVisits) && isNil(appointments?.recentVisits));
49
-
50
- const backButtonDescription =
51
- searchType === SearchTypes.VISIT_FORM && hasAppointments
52
- ? t('backToScheduledVisits', 'Back to scheduled visits')
53
- : t('backToSearchResults', 'Back to search results');
54
-
55
- const toggleSearchType = (searchType: SearchTypes) => {
56
- setSearchType(searchType);
57
- };
58
-
59
- const handleBackToAction = () => {
60
- if (searchType === SearchTypes.VISIT_FORM && hasAppointments) {
61
- setSearchType(SearchTypes.SCHEDULED_VISITS);
62
- } else {
63
- setSearchType(SearchTypes.SEARCH_RESULTS);
64
- }
65
- };
66
-
67
- useEffect(() => {
68
- if (searchType === SearchTypes.SCHEDULED_VISITS && appointments && !hasAppointments) {
69
- setSearchType(SearchTypes.VISIT_FORM);
70
- }
71
- }, [hasAppointments, appointments]);
72
-
73
- useEffect(() => {
74
- if (searchType === SearchTypes.SEARCH_RESULTS) {
75
- handleBackToSearchList && handleBackToSearchList();
76
- }
77
- }, [searchType, handleBackToSearchList]);
78
-
79
- const patientName = patient && getPatientName(patient);
80
- return patient ? (
81
- <div className={styles.patientSearchContainer}>
82
- <AddPatientToQueueContext.Provider value={{ currentServiceQueueUuid }}>
83
- <div className={styles.patientBannerContainer}>
84
- <div className={styles.patientBanner}>
85
- <div className={styles.patientPhoto}>
86
- <PatientPhoto patientUuid={patient.id} patientName={patientName} />
87
- </div>
88
- <PatientBannerPatientInfo patient={patient} />
89
- <PatientBannerToggleContactDetailsButton
90
- showContactDetails={showContactDetails}
91
- toggleContactDetails={() => setContactDetails(!showContactDetails)}
92
- />
93
- </div>
94
- {showContactDetails ? (
95
- <PatientBannerContactDetails patientId={patient.id} deceased={patient.deceasedBoolean} />
96
- ) : null}
97
- </div>
98
- <div className={styles.backButton}>
99
- <Button
100
- kind="ghost"
101
- renderIcon={(props) => <ArrowLeftIcon size={24} {...props} />}
102
- iconDescription={backButtonDescription}
103
- size="sm"
104
- onClick={handleBackToAction}>
105
- <span>{backButtonDescription}</span>
106
- </Button>
107
- </div>
108
- {activeVisit ? (
109
- <ExistingVisitFormComponent visit={activeVisit} closeWorkspace={closeWorkspace} />
110
- ) : (
111
- <>
112
- {error ? (
113
- <ErrorState headerTitle={t('errorFetchingAppointments', 'Error fetching appointments')} error={error} />
114
- ) : null}
115
-
116
- {isLoading && !error ? (
117
- <DataTableSkeleton role="progressbar" />
118
- ) : searchType === SearchTypes.SCHEDULED_VISITS && hasAppointments ? (
119
- <PatientScheduledVisits
120
- appointments={appointments}
121
- patientUuid={selectedPatientUuid}
122
- toggleSearchType={toggleSearchType}
123
- closeWorkspace={closeWorkspace}
124
- />
125
- ) : searchType === SearchTypes.VISIT_FORM ? (
126
- <VisitForm patientUuid={selectedPatientUuid} closeWorkspace={closeWorkspace} />
127
- ) : null}
128
- </>
129
- )}
130
- </AddPatientToQueueContext.Provider>
131
- </div>
132
- ) : null;
133
- };
134
-
135
- export default PatientSearch;
@@ -1,27 +0,0 @@
1
- import React from 'react';
2
-
3
- export default function SearchIllustration({ width = '62', height = '48' }) {
4
- return (
5
- <svg width={width} height={height} xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
6
- <defs>
7
- <path
8
- d="M36.001 3.218C47.482 9.838 51.403 24.52 44.782 36 38.162 47.482 23.48 51.403 12 44.782.518 38.162-3.403 23.48 3.218 12 9.838.518 24.52-3.403 36 3.218z"
9
- id="a"
10
- />
11
- </defs>
12
- <g fill="none" fillRule="evenodd">
13
- <path d="M36.001 3.218C47.482 9.838 51.403 24.52 44.782 36 38.162 47.482 23.48 51.403 12 44.782.518 38.162-3.403 23.48 3.218 12 9.838.518 24.52-3.403 36 3.218z" />
14
- <mask id="b" fill="#fff">
15
- <use xlinkHref="#a" />
16
- </mask>
17
- <use fill="#CEE6E5" xlinkHref="#a" />
18
- <path
19
- d="M38 48v-2.618c0-6.696-4.58-12.296-10.72-13.798a8.159 8.159 0 0 0 4.76-7.427C32.04 19.653 28.44 16 24 16c-4.44 0-8.04 3.653-8.04 8.157a8.159 8.159 0 0 0 4.76 7.427C14.58 33.086 10 38.686 10 45.382v2.598"
20
- fill="#9ACBCA"
21
- mask="url(#b)"
22
- />
23
- <path fill="#9ACBCA" d="m45.34 35 17.124 10.33-1.55 2.57L43.79 37.568z" />
24
- </g>
25
- </svg>
26
- );
27
- }