@kenyaemr/esm-service-queues-app 8.1.1-pre.124 → 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.
- package/.turbo/turbo-build.log +26 -26
- package/dist/1006.js +1 -0
- package/dist/1006.js.map +1 -0
- package/dist/1060.js +1 -0
- package/dist/1060.js.map +1 -0
- package/dist/130.js +1 -1
- package/dist/130.js.map +1 -1
- package/dist/1325.js +1 -0
- package/dist/1325.js.map +1 -0
- package/dist/1644.js +1 -0
- package/dist/1727.js +1 -0
- package/dist/1727.js.map +1 -0
- package/dist/1800.js +1 -0
- package/dist/1800.js.map +1 -0
- package/dist/236.js +1 -1
- package/dist/2757.js +1 -0
- package/dist/{282.js → 2760.js} +1 -1
- package/dist/2760.js.map +1 -0
- package/dist/2784.js +2 -0
- package/dist/2784.js.map +1 -0
- package/dist/3199.js +1 -0
- package/dist/3199.js.map +1 -0
- package/dist/3372.js +2 -0
- package/dist/3372.js.map +1 -0
- package/dist/3574.js +1 -0
- package/dist/3604.js +1 -0
- package/dist/3604.js.map +1 -0
- package/dist/3652.js +1 -0
- package/dist/3760.js +1 -0
- package/dist/3760.js.map +1 -0
- package/dist/3818.js +1 -0
- package/dist/3818.js.map +1 -0
- package/dist/3828.js +1 -0
- package/dist/3828.js.map +1 -0
- package/dist/4272.js +1 -0
- package/dist/4378.js +1 -0
- package/dist/443.js +1 -0
- package/dist/443.js.map +1 -0
- package/dist/4460.js +1 -0
- package/dist/4705.js +1 -0
- package/dist/4911.js +1 -0
- package/dist/4911.js.map +1 -0
- package/dist/5236.js +1 -0
- package/dist/5236.js.map +1 -0
- package/dist/5240.js +1 -0
- package/dist/5282.js +1 -0
- package/dist/5282.js.map +1 -0
- package/dist/5336.js +1 -0
- package/dist/539.js +1 -0
- package/dist/5673.js +1 -0
- package/dist/5711.js +1 -0
- package/dist/5737.js +1 -0
- package/dist/5833.js +1 -0
- package/dist/6566.js +1 -0
- package/dist/6578.js +2 -0
- package/dist/{660.js.LICENSE.txt → 6578.js.LICENSE.txt} +5 -0
- package/dist/6578.js.map +1 -0
- package/dist/6591.js +2 -0
- package/dist/6591.js.map +1 -0
- package/dist/6670.js +1 -0
- package/dist/6670.js.map +1 -0
- package/dist/6727.js +1 -0
- package/dist/744.js +1 -0
- package/dist/752.js +1 -1
- package/dist/752.js.map +1 -1
- package/dist/7807.js +1 -0
- package/dist/8271.js +1 -0
- package/dist/8319.js +1 -0
- package/dist/8788.js +1 -0
- package/dist/899.js +1 -0
- package/dist/9261.js +1 -0
- package/dist/9392.js +1 -0
- package/dist/9392.js.map +1 -0
- package/dist/9993.js +1 -0
- package/dist/9993.js.map +1 -0
- package/dist/kenyaemr-esm-service-queues-app.js +1 -1
- package/dist/kenyaemr-esm-service-queues-app.js.buildmanifest.json +541 -234
- package/dist/kenyaemr-esm-service-queues-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +5 -0
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package-lock.json +5892 -0
- package/package.json +8 -5
- package/src/active-visits/active-visits-table.resource.ts +0 -62
- package/src/active-visits/change-status-dialog.component.tsx +10 -3
- package/src/active-visits/change-status-dialog.scss +29 -1
- package/src/active-visits/change-status-dialog.test.tsx +11 -3
- package/src/add-provider-queue-room/add-provider-queue-room.component.tsx +53 -54
- package/src/add-provider-queue-room/add-provider-queue-room.scss +28 -0
- package/src/add-provider-queue-room/add-provider-queue-room.test.tsx +1 -1
- package/src/clear-queue-entries-dialog/clear-queue-entries-dialog.component.tsx +1 -0
- package/src/clear-queue-entries-dialog/clear-queue-entries-dialog.scss +29 -0
- package/src/clear-queue-entries-dialog/clear-queue-entries-dialog.test.tsx +4 -1
- package/src/config-schema.ts +28 -8
- package/src/create-queue-entry/create-queue-entry.workspace.tsx +99 -0
- package/src/create-queue-entry/existing-visit-form/existing-visit-form.component.tsx +73 -0
- 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
- package/src/create-queue-entry/queue-fields/queue-fields.resource.ts +63 -0
- package/src/{patient-search/visit-form-queue-fields/visit-form-queue-fields.scss → create-queue-entry/queue-fields/queue-fields.scss} +0 -4
- 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
- package/src/create-queue-entry/queue-fields/visit-form-queue-fields.extension.tsx +31 -0
- package/src/hooks/useQueueEntries.ts +13 -12
- package/src/index.ts +8 -14
- package/src/patient-info/patient-info.component.tsx +10 -8
- package/src/patient-queue-header/patient-queue-header.component.tsx +18 -13
- package/src/patient-queue-metrics/metrics-header.component.tsx +4 -4
- package/src/queue-entry-table-components/queue-priority.component.tsx +16 -11
- package/src/queue-entry-table-components/queue-priority.scss +5 -0
- package/src/queue-entry-table-components/transition-entry.component.tsx +1 -1
- package/src/queue-patient-linelists/queue-linelist-base-table.component.tsx +1 -1
- package/src/queue-patient-linelists/queue-linelist-filter.workspace.tsx +13 -12
- package/src/queue-patient-linelists/scheduled-appointments-table.component.tsx +1 -1
- package/src/queue-rooms/queue-room-form.test.tsx +2 -2
- package/src/queue-rooms/queue-room-form.workspace.tsx +1 -1
- package/src/queue-screen/queue-screen.test.tsx +11 -4
- package/src/queue-services/queue-service-form.test.tsx +76 -16
- package/src/queue-services/queue-service-form.workspace.tsx +131 -131
- package/src/queue-services/queue-service.resource.ts +7 -2
- package/src/queue-table/cells/columns.resource.ts +10 -7
- package/src/queue-table/cells/queue-table-visit-attribute-queue-number-cell.component.tsx +1 -0
- package/src/queue-table/default-queue-table.component.tsx +13 -13
- package/src/queue-table/default-queue-table.test.tsx +3 -3
- package/src/queue-table/queue-entry-actions/queue-entry-actions-modal.scss +28 -0
- package/src/queue-table/queue-entry-actions/queue-entry-actions.modal.tsx +8 -2
- package/src/queue-table/queue-entry-actions/queue-entry-confirm-action.modal.tsx +2 -1
- package/src/queue-table/queue-entry-actions/queue-entry-confirm-action.scss +29 -0
- package/src/queue-table/queue-table.component.tsx +1 -1
- package/src/queue-table/queue-table.scss +12 -2
- package/src/queue-table/queue-table.test.tsx +10 -1
- package/src/remove-queue-entry-dialog/remove-queue-entry.component.tsx +16 -4
- package/src/remove-queue-entry-dialog/remove-queue-entry.scss +29 -0
- package/src/routes.json +4 -8
- package/src/transition-latest-queue-entry/transition-latest-queue-entry.resource.ts +2 -10
- package/src/transition-queue-entry/transition-queue-entry-dialog.component.tsx +41 -32
- package/src/transition-queue-entry/transition-queue-entry-dialog.scss +28 -0
- package/src/types/index.ts +0 -8
- package/src/views/queue-tables-for-all-statuses.component.tsx +12 -15
- package/translations/am.json +5 -78
- package/translations/ar.json +5 -78
- package/translations/de.json +235 -0
- package/translations/en.json +9 -86
- package/translations/es.json +3 -76
- package/translations/fr.json +5 -78
- package/translations/he.json +5 -78
- package/translations/hi.json +235 -0
- package/translations/hi_IN.json +235 -0
- package/translations/id.json +235 -0
- package/translations/it.json +235 -0
- package/translations/km.json +5 -78
- package/translations/ne.json +235 -0
- package/translations/pt.json +235 -0
- package/translations/pt_BR.json +235 -0
- package/translations/qu.json +235 -0
- package/translations/si.json +235 -0
- package/translations/sw.json +235 -0
- package/translations/sw_KE.json +235 -0
- package/translations/tr.json +235 -0
- package/translations/tr_TR.json +235 -0
- package/translations/uk.json +235 -0
- package/translations/vi.json +235 -0
- package/translations/zh.json +6 -79
- package/translations/zh_CN.json +5 -78
- package/dist/169.js +0 -1
- package/dist/169.js.map +0 -1
- package/dist/199.js +0 -1
- package/dist/199.js.map +0 -1
- package/dist/236.js.map +0 -1
- package/dist/271.js +0 -1
- package/dist/282.js.map +0 -1
- package/dist/319.js +0 -1
- package/dist/325.js +0 -1
- package/dist/325.js.map +0 -1
- package/dist/366.js +0 -1
- package/dist/366.js.map +0 -1
- package/dist/372.js +0 -2
- package/dist/372.js.map +0 -1
- package/dist/392.js +0 -1
- package/dist/392.js.map +0 -1
- package/dist/460.js +0 -1
- package/dist/501.js +0 -1
- package/dist/501.js.map +0 -1
- package/dist/574.js +0 -1
- package/dist/591.js +0 -2
- package/dist/591.js.map +0 -1
- package/dist/6.js +0 -1
- package/dist/6.js.map +0 -1
- package/dist/60.js +0 -1
- package/dist/60.js.map +0 -1
- package/dist/604.js +0 -1
- package/dist/604.js.map +0 -1
- package/dist/644.js +0 -1
- package/dist/660.js +0 -2
- package/dist/660.js.map +0 -1
- package/dist/670.js +0 -1
- package/dist/670.js.map +0 -1
- package/dist/727.js +0 -1
- package/dist/727.js.map +0 -1
- package/dist/748.js +0 -1
- package/dist/748.js.map +0 -1
- package/dist/757.js +0 -1
- package/dist/760.js +0 -1
- package/dist/760.js.map +0 -1
- package/dist/784.js +0 -2
- package/dist/784.js.map +0 -1
- package/dist/788.js +0 -1
- package/dist/800.js +0 -1
- package/dist/800.js.map +0 -1
- package/dist/807.js +0 -1
- package/dist/818.js +0 -1
- package/dist/818.js.map +0 -1
- package/dist/828.js +0 -1
- package/dist/828.js.map +0 -1
- package/dist/833.js +0 -1
- package/dist/911.js +0 -1
- package/dist/911.js.map +0 -1
- package/dist/940.js +0 -1
- package/dist/940.js.map +0 -1
- package/src/add-patient-toqueue/add-patient-toqueue-dialog.component.tsx +0 -228
- package/src/add-patient-toqueue/add-patient-toqueue-dialog.scss +0 -32
- package/src/patient-search/advanced-search.component.tsx +0 -191
- package/src/patient-search/advanced-search.scss +0 -154
- package/src/patient-search/advanced-search.test.tsx +0 -26
- package/src/patient-search/basic-search.component.tsx +0 -112
- package/src/patient-search/basic-search.scss +0 -139
- package/src/patient-search/basic-search.test.tsx +0 -18
- package/src/patient-search/empty-data-illustration.component.tsx +0 -41
- package/src/patient-search/hooks/useActivePatientEnrollment.tsx +0 -29
- package/src/patient-search/hooks/useDefaultLocation.ts +0 -14
- package/src/patient-search/hooks/usePatients.tsx +0 -25
- package/src/patient-search/hooks/useRecommendedVisitTypes.tsx +0 -35
- package/src/patient-search/hooks/useScheduledVisits.ts +0 -52
- package/src/patient-search/patient-scheduled-visits.component.tsx +0 -315
- package/src/patient-search/patient-scheduled-visits.scss +0 -131
- package/src/patient-search/patient-scheduled-visits.test.tsx +0 -39
- package/src/patient-search/patient-search.workspace.tsx +0 -135
- package/src/patient-search/search-illustration.component.tsx +0 -27
- package/src/patient-search/search-results.component.tsx +0 -75
- package/src/patient-search/search-results.scss +0 -80
- package/src/patient-search/search-results.test.tsx +0 -69
- package/src/patient-search/search.resource.ts +0 -10
- package/src/patient-search/visit-form/existing-visit-form.component.tsx +0 -112
- package/src/patient-search/visit-form/queue.resource.ts +0 -64
- package/src/patient-search/visit-form/visit-form.component.tsx +0 -337
- package/src/patient-search/visit-form/visit-type-selector.component.tsx +0 -153
- package/src/patient-search/visit-form/visit-type-selector.scss +0 -100
- package/src/patient-search/visit-form/visit-type-selector.test.tsx +0 -84
- package/src/visits-missing-inqueue/visits-missing-inqueue.component.tsx +0 -277
- package/src/visits-missing-inqueue/visits-missing-inqueue.resource.ts +0 -93
- package/src/visits-missing-inqueue/visits-missing-inqueue.scss +0 -111
- /package/dist/{784.js.LICENSE.txt → 2784.js.LICENSE.txt} +0 -0
- /package/dist/{372.js.LICENSE.txt → 3372.js.LICENSE.txt} +0 -0
- /package/dist/{591.js.LICENSE.txt → 6591.js.LICENSE.txt} +0 -0
- /package/src/{patient-search/patient-search.scss → create-queue-entry/create-queue-entry.scss} +0 -0
- /package/src/{patient-search/visit-form/visit-form.scss → create-queue-entry/existing-visit-form/existing-visit-form.scss} +0 -0
- /package/src/{patient-search → create-queue-entry}/hooks/useQueueLocations.tsx +0 -0
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import dayjs from 'dayjs';
|
|
3
|
-
import {
|
|
4
|
-
Button,
|
|
5
|
-
ButtonSet,
|
|
6
|
-
ContentSwitcher,
|
|
7
|
-
DatePicker,
|
|
8
|
-
DatePickerInput,
|
|
9
|
-
Form,
|
|
10
|
-
FormGroup,
|
|
11
|
-
InlineNotification,
|
|
12
|
-
RadioButton,
|
|
13
|
-
RadioButtonGroup,
|
|
14
|
-
Row,
|
|
15
|
-
Select,
|
|
16
|
-
SelectItem,
|
|
17
|
-
Stack,
|
|
18
|
-
Switch,
|
|
19
|
-
TimePicker,
|
|
20
|
-
TimePickerSelect,
|
|
21
|
-
} from '@carbon/react';
|
|
22
|
-
import { useTranslation } from 'react-i18next';
|
|
23
|
-
import {
|
|
24
|
-
ExtensionSlot,
|
|
25
|
-
ResponsiveWrapper,
|
|
26
|
-
saveVisit,
|
|
27
|
-
showSnackbar,
|
|
28
|
-
toDateObjectStrict,
|
|
29
|
-
toOmrsIsoString,
|
|
30
|
-
useConfig,
|
|
31
|
-
useLayoutType,
|
|
32
|
-
useLocations,
|
|
33
|
-
useSession,
|
|
34
|
-
} from '@openmrs/esm-framework';
|
|
35
|
-
import { RecommendedVisitTypeSelector, VisitTypeSelector } from './visit-type-selector.component';
|
|
36
|
-
import { postQueueEntry } from '../../active-visits/active-visits-table.resource';
|
|
37
|
-
import { type amPm, convertTime12to24 } from '../../helpers/time-helpers';
|
|
38
|
-
import { useActivePatientEnrollment } from '../hooks/useActivePatientEnrollment';
|
|
39
|
-
import { type NewVisitPayload, type PatientProgram } from '../../types';
|
|
40
|
-
import styles from './visit-form.scss';
|
|
41
|
-
import { useDefaultLoginLocation } from '../hooks/useDefaultLocation';
|
|
42
|
-
import isEmpty from 'lodash-es/isEmpty';
|
|
43
|
-
import { useMutateQueueEntries } from '../../hooks/useQueueEntries';
|
|
44
|
-
import { type ConfigObject } from '../../config-schema';
|
|
45
|
-
import { datePickerFormat, datePickerPlaceHolder } from '../../constants';
|
|
46
|
-
import VisitFormQueueFields from '../visit-form-queue-fields/visit-form-queue-fields.component';
|
|
47
|
-
|
|
48
|
-
interface VisitFormProps {
|
|
49
|
-
patientUuid: string;
|
|
50
|
-
closeWorkspace: () => void;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const VisitForm: React.FC<VisitFormProps> = ({ patientUuid, closeWorkspace }) => {
|
|
54
|
-
const { t } = useTranslation();
|
|
55
|
-
const isTablet = useLayoutType() === 'tablet';
|
|
56
|
-
const locations = useLocations();
|
|
57
|
-
const sessionUser = useSession();
|
|
58
|
-
const { defaultFacility, isLoading: loadingDefaultFacility } = useDefaultLoginLocation();
|
|
59
|
-
|
|
60
|
-
const config = useConfig<ConfigObject>();
|
|
61
|
-
const [contentSwitcherIndex, setContentSwitcherIndex] = useState(config.showRecommendedVisitTypeTab ? 0 : 1);
|
|
62
|
-
const [isMissingVisitType, setIsMissingVisitType] = useState(false);
|
|
63
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
64
|
-
const [timeFormat, setTimeFormat] = useState<amPm>(new Date().getHours() >= 12 ? 'PM' : 'AM');
|
|
65
|
-
const [visitDate, setVisitDate] = useState(new Date());
|
|
66
|
-
const [visitTime, setVisitTime] = useState(dayjs(new Date()).format('hh:mm'));
|
|
67
|
-
const state = useMemo(() => ({ patientUuid }), [patientUuid]);
|
|
68
|
-
const [ignoreChanges, setIgnoreChanges] = useState(true);
|
|
69
|
-
const { activePatientEnrollment } = useActivePatientEnrollment(patientUuid);
|
|
70
|
-
const [enrollment, setEnrollment] = useState<PatientProgram>(activePatientEnrollment[0]);
|
|
71
|
-
const { mutateQueueEntries } = useMutateQueueEntries();
|
|
72
|
-
const visitQueueNumberAttributeUuid = config.visitQueueNumberAttributeUuid;
|
|
73
|
-
const [selectedLocation, setSelectedLocation] = useState('');
|
|
74
|
-
const [visitType, setVisitType] = useState('');
|
|
75
|
-
const [{ service, priority, status, sortWeight, queueLocation }, setVisitFormFields] = useState({
|
|
76
|
-
service: null,
|
|
77
|
-
priority: null,
|
|
78
|
-
status: null,
|
|
79
|
-
sortWeight: null,
|
|
80
|
-
queueLocation: null,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
if (locations?.length && sessionUser) {
|
|
85
|
-
setSelectedLocation(sessionUser?.sessionLocation?.uuid);
|
|
86
|
-
} else if (!loadingDefaultFacility && defaultFacility) {
|
|
87
|
-
setSelectedLocation(defaultFacility?.uuid);
|
|
88
|
-
}
|
|
89
|
-
}, [locations, sessionUser, loadingDefaultFacility]);
|
|
90
|
-
|
|
91
|
-
const handleSubmit = useCallback(
|
|
92
|
-
(event) => {
|
|
93
|
-
event.preventDefault();
|
|
94
|
-
|
|
95
|
-
if (!visitType) {
|
|
96
|
-
setIsMissingVisitType(true);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
setIsSubmitting(true);
|
|
101
|
-
|
|
102
|
-
const [hours, minutes] = convertTime12to24(visitTime, timeFormat);
|
|
103
|
-
|
|
104
|
-
const payload: NewVisitPayload = {
|
|
105
|
-
patient: patientUuid,
|
|
106
|
-
startDatetime: toDateObjectStrict(
|
|
107
|
-
toOmrsIsoString(
|
|
108
|
-
new Date(dayjs(visitDate).year(), dayjs(visitDate).month(), dayjs(visitDate).date(), hours, minutes),
|
|
109
|
-
),
|
|
110
|
-
),
|
|
111
|
-
visitType: visitType,
|
|
112
|
-
location: selectedLocation,
|
|
113
|
-
attributes: [],
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const abortController = new AbortController();
|
|
117
|
-
|
|
118
|
-
saveVisit(payload, abortController).then((response) => {
|
|
119
|
-
// add new queue entry if visit created successfully
|
|
120
|
-
postQueueEntry(
|
|
121
|
-
response.data.uuid,
|
|
122
|
-
service,
|
|
123
|
-
patientUuid,
|
|
124
|
-
priority,
|
|
125
|
-
status,
|
|
126
|
-
sortWeight,
|
|
127
|
-
queueLocation,
|
|
128
|
-
visitQueueNumberAttributeUuid,
|
|
129
|
-
)
|
|
130
|
-
.then(() => {
|
|
131
|
-
showSnackbar({
|
|
132
|
-
kind: 'success',
|
|
133
|
-
isLowContrast: true,
|
|
134
|
-
title: t('startAVisit', 'Start a visit'),
|
|
135
|
-
subtitle: t(
|
|
136
|
-
'startVisitQueueSuccessfully',
|
|
137
|
-
'Patient has been added to active visits list and queue.',
|
|
138
|
-
`${hours} : ${minutes}`,
|
|
139
|
-
),
|
|
140
|
-
});
|
|
141
|
-
closeWorkspace();
|
|
142
|
-
setIsSubmitting(false);
|
|
143
|
-
mutateQueueEntries();
|
|
144
|
-
})
|
|
145
|
-
.catch((error) => {
|
|
146
|
-
showSnackbar({
|
|
147
|
-
title: t('queueEntryError', 'Error adding patient to the queue'),
|
|
148
|
-
kind: 'error',
|
|
149
|
-
subtitle: error?.message,
|
|
150
|
-
});
|
|
151
|
-
setIsSubmitting(false);
|
|
152
|
-
})
|
|
153
|
-
.catch((error) => {
|
|
154
|
-
showSnackbar({
|
|
155
|
-
title: t('startVisitError', 'Error starting visit'),
|
|
156
|
-
kind: 'error',
|
|
157
|
-
subtitle: error?.message,
|
|
158
|
-
});
|
|
159
|
-
setIsSubmitting(false);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
},
|
|
163
|
-
[
|
|
164
|
-
closeWorkspace,
|
|
165
|
-
mutateQueueEntries,
|
|
166
|
-
patientUuid,
|
|
167
|
-
selectedLocation,
|
|
168
|
-
t,
|
|
169
|
-
timeFormat,
|
|
170
|
-
visitDate,
|
|
171
|
-
visitQueueNumberAttributeUuid,
|
|
172
|
-
visitTime,
|
|
173
|
-
visitType,
|
|
174
|
-
],
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
const handleOnChange = useCallback(() => {
|
|
178
|
-
setIgnoreChanges((prevState) => !prevState);
|
|
179
|
-
}, []);
|
|
180
|
-
|
|
181
|
-
return (
|
|
182
|
-
<Form className={styles.form} onChange={handleOnChange} onSubmit={handleSubmit}>
|
|
183
|
-
<div>
|
|
184
|
-
{isTablet && (
|
|
185
|
-
<Row className={styles.headerGridRow}>
|
|
186
|
-
<ExtensionSlot name="visit-form-header-slot" className={styles.dataGridRow} state={state} />
|
|
187
|
-
</Row>
|
|
188
|
-
)}
|
|
189
|
-
<Stack gap={8} className={styles.container}>
|
|
190
|
-
<section className={styles.section}>
|
|
191
|
-
<div className={styles.sectionTitle}>{t('dateAndTimeOfVisit', 'Date and time of visit')}</div>
|
|
192
|
-
<div className={styles.dateTimeSection}>
|
|
193
|
-
<DatePicker
|
|
194
|
-
dateFormat={datePickerFormat}
|
|
195
|
-
datePickerType="single"
|
|
196
|
-
id="visitDate"
|
|
197
|
-
style={{ paddingBottom: '1rem' }}
|
|
198
|
-
maxDate={new Date().toISOString()}
|
|
199
|
-
onChange={([date]) => setVisitDate(date)}
|
|
200
|
-
value={visitDate}>
|
|
201
|
-
<DatePickerInput
|
|
202
|
-
id="visitStartDateInput"
|
|
203
|
-
labelText={t('date', 'Date')}
|
|
204
|
-
placeholder={datePickerPlaceHolder}
|
|
205
|
-
style={{ width: '100%' }}
|
|
206
|
-
/>
|
|
207
|
-
</DatePicker>
|
|
208
|
-
<ResponsiveWrapper>
|
|
209
|
-
<TimePicker
|
|
210
|
-
id="visitStartTime"
|
|
211
|
-
labelText={t('time', 'Time')}
|
|
212
|
-
onChange={(event) => setVisitTime(event.target.value as amPm)}
|
|
213
|
-
pattern="^(1[0-2]|0?[1-9]):([0-5]?[0-9])$"
|
|
214
|
-
style={{ marginLeft: '0.125rem', flex: 'none' }}
|
|
215
|
-
value={visitTime}>
|
|
216
|
-
<TimePickerSelect
|
|
217
|
-
id="visitStartTimeSelect"
|
|
218
|
-
onChange={(event) => setTimeFormat(event.target.value as amPm)}
|
|
219
|
-
value={timeFormat}
|
|
220
|
-
labelText={t('time', 'Time')}
|
|
221
|
-
aria-label={t('time', 'Time')}>
|
|
222
|
-
<SelectItem value="AM" text="AM" />
|
|
223
|
-
<SelectItem value="PM" text="PM" />
|
|
224
|
-
</TimePickerSelect>
|
|
225
|
-
</TimePicker>
|
|
226
|
-
</ResponsiveWrapper>
|
|
227
|
-
</div>
|
|
228
|
-
</section>
|
|
229
|
-
|
|
230
|
-
<section className={styles.section}>
|
|
231
|
-
<div className={styles.sectionTitle}>{t('facility', 'Facility')}</div>
|
|
232
|
-
<Select
|
|
233
|
-
labelText={t('selectFacility', 'Select a facility')}
|
|
234
|
-
id="location"
|
|
235
|
-
invalidText="Required"
|
|
236
|
-
value={selectedLocation}
|
|
237
|
-
defaultSelected={selectedLocation}
|
|
238
|
-
onChange={(event) => setSelectedLocation(event.target.value)}>
|
|
239
|
-
{!selectedLocation ? <SelectItem text={t('selectOption', 'Select an option')} value="" /> : null}
|
|
240
|
-
{!isEmpty(defaultFacility) ? (
|
|
241
|
-
<SelectItem key={defaultFacility?.uuid} text={defaultFacility?.display} value={defaultFacility?.uuid}>
|
|
242
|
-
{defaultFacility?.display}
|
|
243
|
-
</SelectItem>
|
|
244
|
-
) : locations?.length > 0 ? (
|
|
245
|
-
locations.map((location) => (
|
|
246
|
-
<SelectItem key={location.uuid} text={location.display} value={location.uuid}>
|
|
247
|
-
{location.display}
|
|
248
|
-
</SelectItem>
|
|
249
|
-
))
|
|
250
|
-
) : null}
|
|
251
|
-
</Select>
|
|
252
|
-
</section>
|
|
253
|
-
|
|
254
|
-
{config.showRecommendedVisitTypeTab && (
|
|
255
|
-
<section>
|
|
256
|
-
<div className={styles.sectionTitle}>{t('program', 'Program')}</div>
|
|
257
|
-
<FormGroup legendText={t('selectProgramType', 'Select program type')}>
|
|
258
|
-
<RadioButtonGroup
|
|
259
|
-
defaultSelected={enrollment?.program?.uuid}
|
|
260
|
-
orientation="vertical"
|
|
261
|
-
onChange={(uuid) =>
|
|
262
|
-
setEnrollment(activePatientEnrollment.find(({ program }) => program.uuid === uuid))
|
|
263
|
-
}
|
|
264
|
-
name="program-type-radio-group"
|
|
265
|
-
valueSelected="default-selected">
|
|
266
|
-
{activePatientEnrollment.map(({ uuid, display, program }) => (
|
|
267
|
-
<RadioButton
|
|
268
|
-
key={uuid}
|
|
269
|
-
className={styles.radioButton}
|
|
270
|
-
id={uuid}
|
|
271
|
-
labelText={display}
|
|
272
|
-
value={program.uuid}
|
|
273
|
-
/>
|
|
274
|
-
))}
|
|
275
|
-
</RadioButtonGroup>
|
|
276
|
-
</FormGroup>
|
|
277
|
-
</section>
|
|
278
|
-
)}
|
|
279
|
-
<section>
|
|
280
|
-
<div className={styles.sectionTitle}>{t('visitType', 'Visit Type')}</div>
|
|
281
|
-
{config.showRecommendedVisitTypeTab && (
|
|
282
|
-
<ContentSwitcher
|
|
283
|
-
selectedIndex={contentSwitcherIndex}
|
|
284
|
-
className={styles.contentSwitcher}
|
|
285
|
-
onChange={({ index }) => setContentSwitcherIndex(index)}>
|
|
286
|
-
<Switch name="recommended" text={t('recommended', 'Recommended')} />
|
|
287
|
-
<Switch name="all" text={t('all', 'All')} />
|
|
288
|
-
</ContentSwitcher>
|
|
289
|
-
)}
|
|
290
|
-
{config.showRecommendedVisitTypeTab && contentSwitcherIndex === 0 && (
|
|
291
|
-
<RecommendedVisitTypeSelector
|
|
292
|
-
onChange={(visitType) => {
|
|
293
|
-
setVisitType(visitType);
|
|
294
|
-
setIsMissingVisitType(false);
|
|
295
|
-
}}
|
|
296
|
-
patientUuid={patientUuid}
|
|
297
|
-
patientProgram={enrollment}
|
|
298
|
-
locationUuid={selectedLocation}
|
|
299
|
-
/>
|
|
300
|
-
)}
|
|
301
|
-
{(!config.showRecommendedVisitTypeTab || contentSwitcherIndex === 1) && (
|
|
302
|
-
<VisitTypeSelector
|
|
303
|
-
onChange={(visitType) => {
|
|
304
|
-
setVisitType(visitType);
|
|
305
|
-
setIsMissingVisitType(false);
|
|
306
|
-
}}
|
|
307
|
-
/>
|
|
308
|
-
)}
|
|
309
|
-
</section>
|
|
310
|
-
{isMissingVisitType && (
|
|
311
|
-
<section>
|
|
312
|
-
<InlineNotification
|
|
313
|
-
style={{ margin: '0', minWidth: '100%' }}
|
|
314
|
-
kind="error"
|
|
315
|
-
lowContrast={true}
|
|
316
|
-
title={t('missingVisitType', 'Missing visit type')}
|
|
317
|
-
subtitle={t('selectVisitType', 'Please select a Visit Type')}
|
|
318
|
-
/>
|
|
319
|
-
</section>
|
|
320
|
-
)}
|
|
321
|
-
|
|
322
|
-
<VisitFormQueueFields setFormFields={setVisitFormFields} />
|
|
323
|
-
</Stack>
|
|
324
|
-
</div>
|
|
325
|
-
<ButtonSet className={isTablet ? styles.tabletButtons : styles.desktopButtons}>
|
|
326
|
-
<Button className={styles.button} kind="secondary" onClick={closeWorkspace}>
|
|
327
|
-
{t('discard', 'Discard')}
|
|
328
|
-
</Button>
|
|
329
|
-
<Button className={styles.button} disabled={isSubmitting} kind="primary" type="submit">
|
|
330
|
-
{t('startVisit', 'Start visit')}
|
|
331
|
-
</Button>
|
|
332
|
-
</ButtonSet>
|
|
333
|
-
</Form>
|
|
334
|
-
);
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
export default VisitForm;
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import React, { useState, useMemo, useEffect } from 'react';
|
|
2
|
-
import classNames from 'classnames';
|
|
3
|
-
import isEmpty from 'lodash-es/isEmpty';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import {
|
|
6
|
-
InlineNotification,
|
|
7
|
-
Layer,
|
|
8
|
-
RadioButton,
|
|
9
|
-
RadioButtonGroup,
|
|
10
|
-
Search,
|
|
11
|
-
StructuredListSkeleton,
|
|
12
|
-
Tile,
|
|
13
|
-
} from '@carbon/react';
|
|
14
|
-
import { ResponsiveWrapper, useDebounce, useLayoutType, useVisitTypes, type VisitType } from '@openmrs/esm-framework';
|
|
15
|
-
import EmptyDataIllustration from '../empty-data-illustration.component';
|
|
16
|
-
import styles from './visit-type-selector.scss';
|
|
17
|
-
import { useRecommendedVisitTypes } from '../hooks/useRecommendedVisitTypes';
|
|
18
|
-
import { type PatientProgram } from '../../types';
|
|
19
|
-
|
|
20
|
-
export interface VisitTypeSelectorProps {
|
|
21
|
-
onChange: (event) => void;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const VisitTypeSelector: React.FC<VisitTypeSelectorProps> = ({ onChange }) => {
|
|
25
|
-
const allVisitTypes = useVisitTypes();
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<div>
|
|
29
|
-
{allVisitTypes.length == 0 ? (
|
|
30
|
-
<StructuredListSkeleton />
|
|
31
|
-
) : (
|
|
32
|
-
<VisitTypeSelectorPresentation visitTypes={allVisitTypes} onChange={onChange} />
|
|
33
|
-
)}
|
|
34
|
-
</div>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export interface RecommendedVisitTypeSelectorProps {
|
|
39
|
-
onChange: (event) => void;
|
|
40
|
-
patientUuid: string;
|
|
41
|
-
patientProgram: PatientProgram;
|
|
42
|
-
locationUuid: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** Recommended visits are specfic to a patient, patient program, and location. */
|
|
46
|
-
export const RecommendedVisitTypeSelector: React.FC<RecommendedVisitTypeSelectorProps> = ({
|
|
47
|
-
onChange,
|
|
48
|
-
patientUuid,
|
|
49
|
-
patientProgram,
|
|
50
|
-
locationUuid,
|
|
51
|
-
}) => {
|
|
52
|
-
const { t } = useTranslation();
|
|
53
|
-
const { recommendedVisitTypes, error, isLoading } = useRecommendedVisitTypes(
|
|
54
|
-
patientUuid,
|
|
55
|
-
patientProgram?.uuid,
|
|
56
|
-
patientProgram?.program?.uuid,
|
|
57
|
-
locationUuid,
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<div style={{ marginTop: '0.625rem' }}>
|
|
62
|
-
{isLoading ? (
|
|
63
|
-
<StructuredListSkeleton />
|
|
64
|
-
) : (
|
|
65
|
-
<VisitTypeSelectorPresentation onChange={onChange} visitTypes={recommendedVisitTypes} />
|
|
66
|
-
)}
|
|
67
|
-
{error && (
|
|
68
|
-
<InlineNotification
|
|
69
|
-
kind="error"
|
|
70
|
-
title={t('failedToLoadRecommendedVisitTypes', 'Failed to load recommended visit types')}></InlineNotification>
|
|
71
|
-
)}
|
|
72
|
-
</div>
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
interface VisitTypeSelectorPresentationProps {
|
|
77
|
-
onChange: (event) => void;
|
|
78
|
-
visitTypes: VisitType[];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const MAX_RESULTS = 5;
|
|
82
|
-
|
|
83
|
-
const VisitTypeSelectorPresentation: React.FC<VisitTypeSelectorPresentationProps> = ({ visitTypes, onChange }) => {
|
|
84
|
-
const { t } = useTranslation();
|
|
85
|
-
const isTablet = useLayoutType() === 'tablet';
|
|
86
|
-
const [searchTerm, setSearchTerm] = useState<string>('');
|
|
87
|
-
const debouncedSearchTerm = useDebounce(searchTerm);
|
|
88
|
-
const [selectedVisitType, setSelectedVisitType] = useState<string>();
|
|
89
|
-
|
|
90
|
-
const results = useMemo(() => {
|
|
91
|
-
if (!isEmpty(debouncedSearchTerm)) {
|
|
92
|
-
return visitTypes.filter(
|
|
93
|
-
(visitType) => visitType.display.toLowerCase().search(debouncedSearchTerm.toLowerCase()) !== -1,
|
|
94
|
-
);
|
|
95
|
-
} else {
|
|
96
|
-
return visitTypes;
|
|
97
|
-
}
|
|
98
|
-
}, [debouncedSearchTerm, visitTypes]);
|
|
99
|
-
|
|
100
|
-
const truncatedResults = results.slice(0, MAX_RESULTS);
|
|
101
|
-
|
|
102
|
-
useEffect(() => {
|
|
103
|
-
if (results.length > 0) {
|
|
104
|
-
onChange(results[0].uuid);
|
|
105
|
-
setSelectedVisitType(results[0].uuid);
|
|
106
|
-
}
|
|
107
|
-
}, [results]);
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<div
|
|
111
|
-
className={classNames(styles.visitTypeOverviewWrapper, {
|
|
112
|
-
[styles.tablet]: isTablet,
|
|
113
|
-
[styles.desktop]: !isTablet,
|
|
114
|
-
})}>
|
|
115
|
-
{truncatedResults.length < visitTypes.length ? (
|
|
116
|
-
<ResponsiveWrapper>
|
|
117
|
-
<Search
|
|
118
|
-
onChange={(event) => setSearchTerm(event.target.value)}
|
|
119
|
-
placeholder={t('searchForAVisitType', 'Search for a visit type')}
|
|
120
|
-
labelText=""
|
|
121
|
-
/>
|
|
122
|
-
</ResponsiveWrapper>
|
|
123
|
-
) : null}
|
|
124
|
-
{truncatedResults.length ? (
|
|
125
|
-
<RadioButtonGroup
|
|
126
|
-
className={styles.radioButtonGroup}
|
|
127
|
-
defaultSelected={results[0].uuid}
|
|
128
|
-
orientation="vertical"
|
|
129
|
-
onChange={(visitType) => {
|
|
130
|
-
setSelectedVisitType(visitType);
|
|
131
|
-
onChange(visitType);
|
|
132
|
-
}}
|
|
133
|
-
name="radio-button-group"
|
|
134
|
-
valueSelected={selectedVisitType}>
|
|
135
|
-
{truncatedResults.map(({ uuid, display, name }) => (
|
|
136
|
-
<RadioButton key={uuid} className={styles.radioButton} id={name} labelText={display} value={uuid} />
|
|
137
|
-
))}
|
|
138
|
-
{/* TODO: This is supposed to paginate. Right now it just shows the user a truncated list
|
|
139
|
-
with no indication that the list is truncated. */}
|
|
140
|
-
</RadioButtonGroup>
|
|
141
|
-
) : (
|
|
142
|
-
<Layer>
|
|
143
|
-
<Tile className={styles.tile}>
|
|
144
|
-
<EmptyDataIllustration />
|
|
145
|
-
<p className={styles.content}>
|
|
146
|
-
{t('noVisitTypesMatchingSearch', 'There are no visit types matching this search text')}
|
|
147
|
-
</p>
|
|
148
|
-
</Tile>
|
|
149
|
-
</Layer>
|
|
150
|
-
)}
|
|
151
|
-
</div>
|
|
152
|
-
);
|
|
153
|
-
};
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
@use '@carbon/layout';
|
|
2
|
-
@use '@carbon/type';
|
|
3
|
-
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
4
|
-
|
|
5
|
-
.visitTypeOverviewWrapper {
|
|
6
|
-
margin: layout.$spacing-05 0;
|
|
7
|
-
border: 0.0625rem solid $grey-2;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.tablet {
|
|
11
|
-
background-color: $ui-02;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.desktop {
|
|
15
|
-
background-color: $ui-01;
|
|
16
|
-
|
|
17
|
-
.paginationContainer div {
|
|
18
|
-
background-color: $ui-01;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.visitTypeOverviewWrapper div:nth-child(3) > div:nth-child(2) {
|
|
23
|
-
position: relative;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.visitTypeOverviewWrapper div:nth-child(3) span * {
|
|
27
|
-
display: none;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.radioButtonGroup {
|
|
31
|
-
display: flex;
|
|
32
|
-
flex-direction: column;
|
|
33
|
-
align-items: flex-start;
|
|
34
|
-
margin-top: layout.$spacing-03;
|
|
35
|
-
min-height: layout.$spacing-10;
|
|
36
|
-
width: 100%;
|
|
37
|
-
@include type.type-style('body-compact-01');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.radioButton {
|
|
41
|
-
padding: layout.$spacing-02 layout.$spacing-05;
|
|
42
|
-
margin: layout.$spacing-03 0;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.content {
|
|
46
|
-
@include type.type-style('heading-compact-01');
|
|
47
|
-
color: $text-02;
|
|
48
|
-
margin-top: layout.$spacing-05;
|
|
49
|
-
margin-bottom: layout.$spacing-03;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.desktopHeading {
|
|
53
|
-
h4 {
|
|
54
|
-
@include type.type-style('heading-compact-02');
|
|
55
|
-
color: $text-02;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.tabletHeading {
|
|
60
|
-
h4 {
|
|
61
|
-
@include type.type-style('heading-03');
|
|
62
|
-
color: $text-02;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.desktopHeading,
|
|
67
|
-
.tabletHeading {
|
|
68
|
-
text-align: left;
|
|
69
|
-
text-transform: capitalize;
|
|
70
|
-
margin-bottom: layout.$spacing-05;
|
|
71
|
-
|
|
72
|
-
h4:after {
|
|
73
|
-
content: '';
|
|
74
|
-
display: block;
|
|
75
|
-
width: layout.$spacing-07;
|
|
76
|
-
padding-top: 0.188rem;
|
|
77
|
-
border-bottom: 0.375rem solid var(--brand-03);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.heading:after {
|
|
82
|
-
content: '';
|
|
83
|
-
display: block;
|
|
84
|
-
width: layout.$spacing-07;
|
|
85
|
-
padding-top: 0.188rem;
|
|
86
|
-
border-bottom: 0.375rem solid var(--brand-03);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.tile {
|
|
90
|
-
text-align: center;
|
|
91
|
-
border: 1px solid $ui-03;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Overriding styles for RTL support
|
|
95
|
-
html[dir='rtl'] {
|
|
96
|
-
.desktopHeading,
|
|
97
|
-
.tabletHeading {
|
|
98
|
-
text-align: right;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/* eslint-disable testing-library/no-node-access */
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import userEvent from '@testing-library/user-event';
|
|
4
|
-
import { render, screen } from '@testing-library/react';
|
|
5
|
-
import { mockVisitTypes } from '__mocks__';
|
|
6
|
-
import { useVisitTypes } from '@openmrs/esm-framework';
|
|
7
|
-
import { VisitTypeSelector } from './visit-type-selector.component';
|
|
8
|
-
|
|
9
|
-
const mockUseVisitTypes = jest.mocked(useVisitTypes);
|
|
10
|
-
|
|
11
|
-
describe('VisitTypeSelector', () => {
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
mockUseVisitTypes.mockReturnValue(mockVisitTypes);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('renders visit types with no search bar if there are 5 or fewer', () => {
|
|
17
|
-
const fewVisitTypes = mockVisitTypes.slice(0, 3);
|
|
18
|
-
mockUseVisitTypes.mockReturnValue(fewVisitTypes);
|
|
19
|
-
render(<VisitTypeSelector onChange={() => {}} />);
|
|
20
|
-
|
|
21
|
-
expect(screen.queryByRole('searchbox')).not.toBeInTheDocument();
|
|
22
|
-
|
|
23
|
-
fewVisitTypes.forEach((visitType) => {
|
|
24
|
-
const radioButton = screen.getByLabelText(visitType.display);
|
|
25
|
-
expect(radioButton).toBeInTheDocument();
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('renders the first 5 visit types with a search bar if there are more than 5', () => {
|
|
30
|
-
render(<VisitTypeSelector onChange={() => {}} />);
|
|
31
|
-
|
|
32
|
-
expect(screen.getByRole('searchbox')).toBeInTheDocument();
|
|
33
|
-
|
|
34
|
-
mockVisitTypes.slice(0, 5).forEach((visitType) => {
|
|
35
|
-
const radioButton = screen.getByLabelText(visitType.display);
|
|
36
|
-
expect(radioButton).toBeInTheDocument();
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('filters by search input and calls onChange', async () => {
|
|
41
|
-
const user = userEvent.setup();
|
|
42
|
-
|
|
43
|
-
const mockOnChange = jest.fn();
|
|
44
|
-
render(<VisitTypeSelector onChange={mockOnChange} />);
|
|
45
|
-
|
|
46
|
-
const searchInput = screen.getByRole('searchbox').closest('input');
|
|
47
|
-
await user.type(searchInput, 'hiv');
|
|
48
|
-
|
|
49
|
-
expect(searchInput.value).toBe('hiv');
|
|
50
|
-
expect(screen.getByLabelText('HIV Return Visit')).toBeInTheDocument();
|
|
51
|
-
expect(screen.getByLabelText('HIV Initial Visit')).toBeInTheDocument();
|
|
52
|
-
expect(screen.queryByLabelText('Outpatient Visit')).not.toBeInTheDocument();
|
|
53
|
-
expect(screen.queryByLabelText('Diabetes Clinic Visit')).not.toBeInTheDocument();
|
|
54
|
-
|
|
55
|
-
expect(mockOnChange).toHaveBeenLastCalledWith(
|
|
56
|
-
mockVisitTypes.filter((vt) => vt.display == 'HIV Return Visit')[0].uuid,
|
|
57
|
-
);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('calls onChange when a visit type is selected', async () => {
|
|
61
|
-
const user = userEvent.setup();
|
|
62
|
-
|
|
63
|
-
const mockOnChange = jest.fn();
|
|
64
|
-
render(<VisitTypeSelector onChange={mockOnChange} />);
|
|
65
|
-
|
|
66
|
-
const radioButton = screen.getByLabelText(mockVisitTypes[1].display).closest('input');
|
|
67
|
-
await user.click(radioButton);
|
|
68
|
-
expect(radioButton).toBeChecked();
|
|
69
|
-
expect(mockOnChange).toHaveBeenLastCalledWith(mockVisitTypes[1].uuid);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('allows changing the search input if no results are returned from a search', async () => {
|
|
73
|
-
const user = userEvent.setup();
|
|
74
|
-
|
|
75
|
-
render(<VisitTypeSelector onChange={() => {}} />);
|
|
76
|
-
|
|
77
|
-
const searchInput: HTMLInputElement = screen.getByRole('searchbox');
|
|
78
|
-
await user.type(searchInput, 'asdfasdf');
|
|
79
|
-
|
|
80
|
-
const searchInputAfter: HTMLInputElement = screen.getByRole('searchbox');
|
|
81
|
-
expect(searchInputAfter).toBeInTheDocument();
|
|
82
|
-
expect(screen.getByText(/no visit types/i)).toBeInTheDocument();
|
|
83
|
-
});
|
|
84
|
-
});
|