@kenyaemr/esm-service-queues-app 8.1.1-pre.129 → 8.1.2-pre.154
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 +2 -2
- 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 +12 -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
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Button, DataTableSkeleton } from '@carbon/react';
|
|
2
|
+
import {
|
|
3
|
+
ArrowLeftIcon,
|
|
4
|
+
ErrorState,
|
|
5
|
+
ExtensionSlot,
|
|
6
|
+
getPatientName,
|
|
7
|
+
PatientBannerContactDetails,
|
|
8
|
+
PatientBannerPatientInfo,
|
|
9
|
+
PatientBannerToggleContactDetailsButton,
|
|
10
|
+
PatientPhoto,
|
|
11
|
+
usePatient,
|
|
12
|
+
useVisit,
|
|
13
|
+
type DefaultWorkspaceProps,
|
|
14
|
+
} from '@openmrs/esm-framework';
|
|
15
|
+
import React, { useState } from 'react';
|
|
16
|
+
import { useTranslation } from 'react-i18next';
|
|
17
|
+
import styles from './create-queue-entry.scss';
|
|
18
|
+
import ExistingVisitFormComponent from './existing-visit-form/existing-visit-form.component';
|
|
19
|
+
|
|
20
|
+
interface PatientSearchProps extends DefaultWorkspaceProps {
|
|
21
|
+
selectedPatientUuid: string;
|
|
22
|
+
currentServiceQueueUuid?: string;
|
|
23
|
+
handleBackToSearchList?: () => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const AddPatientToQueueContext = React.createContext({
|
|
27
|
+
currentServiceQueueUuid: '',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* This is the component that appears when clicking on a search result in the "Add patient to queue" workspace,
|
|
33
|
+
*/
|
|
34
|
+
const CreateQueueEntryWorkspace: React.FC<PatientSearchProps> = ({
|
|
35
|
+
closeWorkspace,
|
|
36
|
+
promptBeforeClosing,
|
|
37
|
+
selectedPatientUuid,
|
|
38
|
+
currentServiceQueueUuid,
|
|
39
|
+
handleBackToSearchList,
|
|
40
|
+
}) => {
|
|
41
|
+
const { t } = useTranslation();
|
|
42
|
+
const { patient } = usePatient(selectedPatientUuid);
|
|
43
|
+
const { activeVisit, isLoading, error } = useVisit(selectedPatientUuid);
|
|
44
|
+
|
|
45
|
+
const [showContactDetails, setContactDetails] = useState(false);
|
|
46
|
+
|
|
47
|
+
const patientName = patient && getPatientName(patient);
|
|
48
|
+
|
|
49
|
+
return patient ? (
|
|
50
|
+
<div className={styles.patientSearchContainer}>
|
|
51
|
+
<AddPatientToQueueContext.Provider value={{ currentServiceQueueUuid }}>
|
|
52
|
+
<div className={styles.patientBannerContainer}>
|
|
53
|
+
<div className={styles.patientBanner}>
|
|
54
|
+
<div className={styles.patientPhoto}>
|
|
55
|
+
<PatientPhoto patientUuid={patient.id} patientName={patientName} />
|
|
56
|
+
</div>
|
|
57
|
+
<PatientBannerPatientInfo patient={patient} />
|
|
58
|
+
<PatientBannerToggleContactDetailsButton
|
|
59
|
+
showContactDetails={showContactDetails}
|
|
60
|
+
toggleContactDetails={() => setContactDetails(!showContactDetails)}
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
{showContactDetails ? (
|
|
64
|
+
<PatientBannerContactDetails patientId={patient.id} deceased={patient.deceasedBoolean} />
|
|
65
|
+
) : null}
|
|
66
|
+
</div>
|
|
67
|
+
<div className={styles.backButton}>
|
|
68
|
+
<Button
|
|
69
|
+
kind="ghost"
|
|
70
|
+
renderIcon={(props) => <ArrowLeftIcon size={24} {...props} />}
|
|
71
|
+
iconDescription={t('backToSearchResults', 'Back to search results')}
|
|
72
|
+
size="sm"
|
|
73
|
+
onClick={() => handleBackToSearchList?.()}>
|
|
74
|
+
<span>{t('backToSearchResults', 'Back to search results')}</span>
|
|
75
|
+
</Button>
|
|
76
|
+
</div>
|
|
77
|
+
{isLoading ? (
|
|
78
|
+
<DataTableSkeleton role="progressbar" />
|
|
79
|
+
) : error ? (
|
|
80
|
+
<ErrorState headerTitle={t('errorFetchingVisit', 'Error fetching patient visit')} error={error} />
|
|
81
|
+
) : activeVisit ? (
|
|
82
|
+
<ExistingVisitFormComponent visit={activeVisit} closeWorkspace={closeWorkspace} />
|
|
83
|
+
) : (
|
|
84
|
+
<ExtensionSlot
|
|
85
|
+
name="start-visit-workspace-form-slot"
|
|
86
|
+
state={{
|
|
87
|
+
patientUuid: selectedPatientUuid,
|
|
88
|
+
closeWorkspace,
|
|
89
|
+
promptBeforeClosing,
|
|
90
|
+
openedFrom: 'service-queues-add-patient',
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
)}
|
|
94
|
+
</AddPatientToQueueContext.Provider>
|
|
95
|
+
</div>
|
|
96
|
+
) : null;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default CreateQueueEntryWorkspace;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Button, ButtonSet, Form, Row } from '@carbon/react';
|
|
2
|
+
import { ExtensionSlot, useLayoutType, type Visit } from '@openmrs/esm-framework';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import React, { useCallback, useState } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { useMutateQueueEntries } from '../../hooks/useQueueEntries';
|
|
7
|
+
import QueueFields from '../queue-fields/queue-fields.component';
|
|
8
|
+
import styles from './existing-visit-form.scss';
|
|
9
|
+
|
|
10
|
+
interface ExistingVisitFormProps {
|
|
11
|
+
closeWorkspace: () => void;
|
|
12
|
+
visit: Visit;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* This is the form that appears when clicking on a search result in the "Add patient to queue" workspace,
|
|
17
|
+
* when the patient already has an active visit.
|
|
18
|
+
*/
|
|
19
|
+
const ExistingVisitForm: React.FC<ExistingVisitFormProps> = ({ visit, closeWorkspace }) => {
|
|
20
|
+
const { t } = useTranslation();
|
|
21
|
+
const isTablet = useLayoutType() === 'tablet';
|
|
22
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
23
|
+
|
|
24
|
+
const { mutateQueueEntries } = useMutateQueueEntries();
|
|
25
|
+
const [callback, setCallback] = useState<{
|
|
26
|
+
submitQueueEntry: (visit: Visit) => Promise<any>;
|
|
27
|
+
}>(null);
|
|
28
|
+
|
|
29
|
+
const handleSubmit = useCallback(
|
|
30
|
+
(event) => {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
setIsSubmitting(true);
|
|
33
|
+
|
|
34
|
+
callback
|
|
35
|
+
?.submitQueueEntry?.(visit)
|
|
36
|
+
?.then(() => {
|
|
37
|
+
closeWorkspace();
|
|
38
|
+
mutateQueueEntries();
|
|
39
|
+
})
|
|
40
|
+
?.finally(() => {
|
|
41
|
+
setIsSubmitting(false);
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
[closeWorkspace, callback, visit, mutateQueueEntries],
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return visit ? (
|
|
48
|
+
<>
|
|
49
|
+
{isTablet && (
|
|
50
|
+
<Row className={styles.headerGridRow}>
|
|
51
|
+
<ExtensionSlot
|
|
52
|
+
name="visit-form-header-slot"
|
|
53
|
+
className={styles.dataGridRow}
|
|
54
|
+
state={{ patientUuid: visit.patient.uuid }}
|
|
55
|
+
/>
|
|
56
|
+
</Row>
|
|
57
|
+
)}
|
|
58
|
+
<Form className={classNames(styles.form, styles.container)} onSubmit={handleSubmit}>
|
|
59
|
+
<QueueFields setOnSubmit={(onSubmit) => setCallback({ submitQueueEntry: onSubmit })} />
|
|
60
|
+
<ButtonSet className={isTablet ? styles.tablet : styles.desktop}>
|
|
61
|
+
<Button className={styles.button} kind="secondary" onClick={closeWorkspace}>
|
|
62
|
+
{t('discard', 'Discard')}
|
|
63
|
+
</Button>
|
|
64
|
+
<Button className={styles.button} disabled={isSubmitting} kind="primary" type="submit">
|
|
65
|
+
{t('addPatientToQueue', 'Add patient to queue')}
|
|
66
|
+
</Button>
|
|
67
|
+
</ButtonSet>
|
|
68
|
+
</Form>
|
|
69
|
+
</>
|
|
70
|
+
) : null;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default ExistingVisitForm;
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import React, { useContext, useEffect, useState } from 'react';
|
|
2
|
-
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import classNames from 'classnames';
|
|
4
1
|
import {
|
|
5
2
|
InlineNotification,
|
|
6
3
|
RadioButton,
|
|
@@ -9,67 +6,106 @@ import {
|
|
|
9
6
|
Select,
|
|
10
7
|
SelectItem,
|
|
11
8
|
SelectSkeleton,
|
|
12
|
-
TextInput,
|
|
13
9
|
} from '@carbon/react';
|
|
14
|
-
import {
|
|
10
|
+
import { ResponsiveWrapper, showSnackbar, useConfig, useSession, type Visit } from '@openmrs/esm-framework';
|
|
11
|
+
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
|
12
|
+
import { useTranslation } from 'react-i18next';
|
|
13
|
+
import { type ConfigObject } from '../../config-schema';
|
|
14
|
+
import { useMutateQueueEntries } from '../../hooks/useQueueEntries';
|
|
15
15
|
import { useQueues } from '../../hooks/useQueues';
|
|
16
|
+
import { AddPatientToQueueContext } from '../create-queue-entry.workspace';
|
|
16
17
|
import { useQueueLocations } from '../hooks/useQueueLocations';
|
|
17
|
-
import {
|
|
18
|
-
import
|
|
19
|
-
import styles from './visit-form-queue-fields.scss';
|
|
18
|
+
import { postQueueEntry } from './queue-fields.resource';
|
|
19
|
+
import styles from './queue-fields.scss';
|
|
20
20
|
|
|
21
|
-
export interface
|
|
22
|
-
|
|
23
|
-
queueLocation: string;
|
|
24
|
-
service: string;
|
|
25
|
-
status: string;
|
|
26
|
-
priority: string;
|
|
27
|
-
sortWeight: number;
|
|
28
|
-
}) => void;
|
|
21
|
+
export interface QueueFieldsProps {
|
|
22
|
+
setOnSubmit(onSubmit: (visit: Visit) => Promise<any>);
|
|
29
23
|
}
|
|
30
24
|
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
/**
|
|
26
|
+
* This component contains form fields for starting a patient's queue entry.
|
|
27
|
+
*/
|
|
28
|
+
const QueueFields: React.FC<QueueFieldsProps> = ({ setOnSubmit }) => {
|
|
33
29
|
const { t } = useTranslation();
|
|
34
30
|
const { queueLocations, isLoading: isLoadingQueueLocations } = useQueueLocations();
|
|
35
31
|
const { sessionLocation } = useSession();
|
|
36
|
-
const
|
|
32
|
+
const {
|
|
33
|
+
visitQueueNumberAttributeUuid,
|
|
34
|
+
concepts: { defaultStatusConceptUuid, defaultPriorityConceptUuid, emergencyPriorityConceptUuid },
|
|
35
|
+
} = useConfig<ConfigObject>();
|
|
37
36
|
const [selectedQueueLocation, setSelectedQueueLocation] = useState(queueLocations[0]?.id);
|
|
38
37
|
const { queues, isLoading: isLoadingQueues } = useQueues(selectedQueueLocation);
|
|
39
|
-
const defaultStatus = config.concepts.defaultStatusConceptUuid;
|
|
40
38
|
const [selectedService, setSelectedService] = useState('');
|
|
41
39
|
const { currentServiceQueueUuid } = useContext(AddPatientToQueueContext);
|
|
42
|
-
const [priority, setPriority] = useState(
|
|
40
|
+
const [priority, setPriority] = useState(defaultPriorityConceptUuid);
|
|
43
41
|
const priorities = queues.find((q) => q.uuid === selectedService)?.allowedPriorities ?? [];
|
|
44
|
-
const
|
|
42
|
+
const { mutateQueueEntries } = useMutateQueueEntries();
|
|
43
|
+
const memoMutateQueueEntries = useCallback(mutateQueueEntries, [mutateQueueEntries]);
|
|
44
|
+
|
|
45
|
+
const sortWeight = priority === emergencyPriorityConceptUuid ? 1 : 0;
|
|
46
|
+
|
|
47
|
+
const onSubmit = useCallback(
|
|
48
|
+
(visit: Visit) => {
|
|
49
|
+
if (selectedQueueLocation && selectedService && priority) {
|
|
50
|
+
return postQueueEntry(
|
|
51
|
+
visit.uuid,
|
|
52
|
+
selectedService,
|
|
53
|
+
visit.patient.uuid,
|
|
54
|
+
priority,
|
|
55
|
+
defaultStatusConceptUuid,
|
|
56
|
+
sortWeight,
|
|
57
|
+
selectedQueueLocation,
|
|
58
|
+
visitQueueNumberAttributeUuid,
|
|
59
|
+
)
|
|
60
|
+
.then(() => {
|
|
61
|
+
showSnackbar({
|
|
62
|
+
kind: 'success',
|
|
63
|
+
isLowContrast: true,
|
|
64
|
+
title: t('addedPatientToQueue', 'Added patient to queue'),
|
|
65
|
+
subtitle: t('queueEntryAddedSuccessfully', 'Queue entry added successfully'),
|
|
66
|
+
});
|
|
67
|
+
memoMutateQueueEntries();
|
|
68
|
+
})
|
|
69
|
+
.catch((error) => {
|
|
70
|
+
showSnackbar({
|
|
71
|
+
title: t('queueEntryError', 'Error adding patient to the queue'),
|
|
72
|
+
kind: 'error',
|
|
73
|
+
isLowContrast: false,
|
|
74
|
+
subtitle: error?.message,
|
|
75
|
+
});
|
|
76
|
+
throw error;
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
return Promise.resolve();
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
[
|
|
83
|
+
selectedQueueLocation,
|
|
84
|
+
selectedService,
|
|
85
|
+
priority,
|
|
86
|
+
sortWeight,
|
|
87
|
+
defaultStatusConceptUuid,
|
|
88
|
+
visitQueueNumberAttributeUuid,
|
|
89
|
+
memoMutateQueueEntries,
|
|
90
|
+
t,
|
|
91
|
+
],
|
|
92
|
+
);
|
|
45
93
|
|
|
46
94
|
useEffect(() => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
}, [priority]);
|
|
95
|
+
setOnSubmit?.(onSubmit);
|
|
96
|
+
}, [onSubmit, setOnSubmit]);
|
|
51
97
|
|
|
52
98
|
useEffect(() => {
|
|
53
99
|
if (currentServiceQueueUuid) {
|
|
54
100
|
setSelectedService(currentServiceQueueUuid);
|
|
55
101
|
}
|
|
56
|
-
}, [queues]);
|
|
102
|
+
}, [currentServiceQueueUuid, queues]);
|
|
57
103
|
|
|
58
104
|
useEffect(() => {
|
|
59
105
|
if (queueLocations.map((l) => l.id).includes(sessionLocation.uuid)) {
|
|
60
106
|
setSelectedQueueLocation(sessionLocation.uuid);
|
|
61
107
|
}
|
|
62
|
-
}, [queueLocations]);
|
|
63
|
-
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
setFormFields({
|
|
66
|
-
queueLocation: selectedQueueLocation,
|
|
67
|
-
service: selectedService,
|
|
68
|
-
status: defaultStatus,
|
|
69
|
-
priority,
|
|
70
|
-
sortWeight,
|
|
71
|
-
});
|
|
72
|
-
}, [selectedQueueLocation, selectedService, defaultStatus, priority, sortWeight]);
|
|
108
|
+
}, [queueLocations, sessionLocation.uuid]);
|
|
73
109
|
|
|
74
110
|
return (
|
|
75
111
|
<div>
|
|
@@ -159,7 +195,7 @@ const VisitFormQueueFields: React.FC<VisitFormQueueFieldsProps> = (props) => {
|
|
|
159
195
|
className={styles.radioButtonWrapper}
|
|
160
196
|
name="priority"
|
|
161
197
|
id="priority"
|
|
162
|
-
defaultSelected={
|
|
198
|
+
defaultSelected={defaultPriorityConceptUuid}
|
|
163
199
|
onChange={(uuid) => setPriority(uuid)}>
|
|
164
200
|
{priorities.map(({ uuid, display }) => (
|
|
165
201
|
<RadioButton key={uuid} labelText={display} value={uuid} />
|
|
@@ -168,18 +204,8 @@ const VisitFormQueueFields: React.FC<VisitFormQueueFieldsProps> = (props) => {
|
|
|
168
204
|
) : null}
|
|
169
205
|
</section>
|
|
170
206
|
) : null}
|
|
171
|
-
|
|
172
|
-
<section className={classNames(styles.section, styles.sectionHidden)}>
|
|
173
|
-
<TextInput
|
|
174
|
-
type="number"
|
|
175
|
-
id="sortWeight"
|
|
176
|
-
name="sortWeight"
|
|
177
|
-
labelText={t('sortWeight', 'Sort weight')}
|
|
178
|
-
value={sortWeight}
|
|
179
|
-
/>
|
|
180
|
-
</section>
|
|
181
207
|
</div>
|
|
182
208
|
);
|
|
183
209
|
};
|
|
184
210
|
|
|
185
|
-
export default
|
|
211
|
+
export default QueueFields;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
|
|
3
|
+
export async function generateVisitQueueNumber(
|
|
4
|
+
location: string,
|
|
5
|
+
visitUuid: string,
|
|
6
|
+
queueUuid: string,
|
|
7
|
+
visitQueueNumberAttributeUuid: string,
|
|
8
|
+
) {
|
|
9
|
+
const abortController = new AbortController();
|
|
10
|
+
|
|
11
|
+
await openmrsFetch(
|
|
12
|
+
`${restBaseUrl}/queue-entry-number?location=${location}&queue=${queueUuid}&visit=${visitUuid}&visitAttributeType=${visitQueueNumberAttributeUuid}`,
|
|
13
|
+
{
|
|
14
|
+
method: 'GET',
|
|
15
|
+
headers: {
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
},
|
|
18
|
+
signal: abortController.signal,
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function postQueueEntry(
|
|
24
|
+
visitUuid: string,
|
|
25
|
+
queueUuid: string,
|
|
26
|
+
patientUuid: string,
|
|
27
|
+
priority: string,
|
|
28
|
+
status: string,
|
|
29
|
+
sortWeight: number,
|
|
30
|
+
locationUuid: string,
|
|
31
|
+
visitQueueNumberAttributeUuid: string,
|
|
32
|
+
) {
|
|
33
|
+
const abortController = new AbortController();
|
|
34
|
+
|
|
35
|
+
await Promise.all([generateVisitQueueNumber(locationUuid, visitUuid, queueUuid, visitQueueNumberAttributeUuid)]);
|
|
36
|
+
|
|
37
|
+
return openmrsFetch(`${restBaseUrl}/visit-queue-entry`, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: {
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
|
+
},
|
|
42
|
+
signal: abortController.signal,
|
|
43
|
+
body: {
|
|
44
|
+
visit: { uuid: visitUuid },
|
|
45
|
+
queueEntry: {
|
|
46
|
+
status: {
|
|
47
|
+
uuid: status,
|
|
48
|
+
},
|
|
49
|
+
priority: {
|
|
50
|
+
uuid: priority,
|
|
51
|
+
},
|
|
52
|
+
queue: {
|
|
53
|
+
uuid: queueUuid,
|
|
54
|
+
},
|
|
55
|
+
patient: {
|
|
56
|
+
uuid: patientUuid,
|
|
57
|
+
},
|
|
58
|
+
startedAt: new Date(),
|
|
59
|
+
sortWeight: sortWeight,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -2,10 +2,18 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import userEvent from '@testing-library/user-event';
|
|
4
4
|
import { render, screen } from '@testing-library/react';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type FetchResponse,
|
|
7
|
+
getDefaultsFromConfigSchema,
|
|
8
|
+
useConfig,
|
|
9
|
+
useLayoutType,
|
|
10
|
+
useSession,
|
|
11
|
+
type Visit,
|
|
12
|
+
} from '@openmrs/esm-framework';
|
|
6
13
|
import { configSchema, type ConfigObject } from '../../config-schema';
|
|
7
|
-
import { mockSession } from '__mocks__';
|
|
8
|
-
import
|
|
14
|
+
import { mockSession, mockVisitAlice } from '__mocks__';
|
|
15
|
+
import QueueFields from './queue-fields.component';
|
|
16
|
+
import { postQueueEntry } from './queue-fields.resource';
|
|
9
17
|
|
|
10
18
|
const mockUseConfig = jest.mocked(useConfig<ConfigObject>);
|
|
11
19
|
const mockUseLayoutType = jest.mocked(useLayoutType);
|
|
@@ -32,7 +40,14 @@ jest.mock('../../hooks/useQueues', () => {
|
|
|
32
40
|
};
|
|
33
41
|
});
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
jest.mock('./queue-fields.resource', () => {
|
|
44
|
+
return {
|
|
45
|
+
postQueueEntry: jest.fn(),
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
const mockPostQueueEntry = jest.mocked(postQueueEntry).mockResolvedValue({} as FetchResponse);
|
|
49
|
+
|
|
50
|
+
describe('QueueFields', () => {
|
|
36
51
|
beforeEach(() => {
|
|
37
52
|
mockUseLayoutType.mockReturnValue('small-desktop');
|
|
38
53
|
mockUseSession.mockReturnValue(mockSession.data);
|
|
@@ -43,27 +58,32 @@ describe('VisitFormQueueFields', () => {
|
|
|
43
58
|
|
|
44
59
|
it('renders the form fields and returns the set values', async () => {
|
|
45
60
|
const user = userEvent.setup();
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
let onSubmit: (visit: Visit) => Promise<any> = null;
|
|
62
|
+
const setOnSubmit = (callback) => {
|
|
63
|
+
onSubmit = callback;
|
|
64
|
+
};
|
|
65
|
+
render(<QueueFields setOnSubmit={setOnSubmit} />);
|
|
48
66
|
|
|
49
67
|
expect(screen.getByLabelText('Select a queue location')).toBeInTheDocument();
|
|
50
68
|
expect(screen.getByLabelText('Select a service')).toBeInTheDocument();
|
|
51
|
-
expect(screen.getByLabelText('Sort weight')).toBeInTheDocument();
|
|
52
69
|
|
|
70
|
+
const queueUuid = 'e2ec9cf0-ec38-4d2b-af6c-59c82fa30b90';
|
|
53
71
|
const serviceSelect = screen.getByLabelText('Select a service').closest('select');
|
|
54
|
-
await user.selectOptions(serviceSelect,
|
|
72
|
+
await user.selectOptions(serviceSelect, queueUuid);
|
|
55
73
|
|
|
56
74
|
expect(screen.getByText('Priority')).toBeInTheDocument();
|
|
57
75
|
expect(screen.getByText('High')).toBeInTheDocument();
|
|
58
76
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
await onSubmit(mockVisitAlice);
|
|
78
|
+
expect(mockPostQueueEntry).toHaveBeenCalledWith(
|
|
79
|
+
mockVisitAlice.uuid,
|
|
80
|
+
queueUuid, // queueUuid
|
|
81
|
+
mockVisitAlice.patient.uuid,
|
|
82
|
+
'f4620bfa-3625-4883-bd3f-84c2cce14470', // priority
|
|
83
|
+
'51ae5e4d-b72b-4912-bf31-a17efb690aeb', // status
|
|
84
|
+
0, // sortWeight
|
|
85
|
+
'1', // locationUuid
|
|
86
|
+
null, // visitQueueNumberAttributeUuid
|
|
87
|
+
);
|
|
68
88
|
});
|
|
69
89
|
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Visit } from '@openmrs/esm-framework';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import QueueFields from './queue-fields.component';
|
|
4
|
+
|
|
5
|
+
interface VisitFormCallbacks {
|
|
6
|
+
onVisitCreatedOrUpdated: (visit: Visit) => Promise<any>;
|
|
7
|
+
}
|
|
8
|
+
// See VisitFormExtensionState in esm-patient-chart-app
|
|
9
|
+
export interface VisitFormQueueFieldsProps {
|
|
10
|
+
setVisitFormCallbacks: (callbacks: VisitFormCallbacks) => void;
|
|
11
|
+
visitFormOpenedFrom: string;
|
|
12
|
+
patientChartConfig?: {
|
|
13
|
+
showServiceQueueFields: boolean;
|
|
14
|
+
};
|
|
15
|
+
patientUuid: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* This extension contains form fields for starting a patient's queue entry.
|
|
20
|
+
* It is used slotted into the patient-chart's start visit form
|
|
21
|
+
*/
|
|
22
|
+
const VisitFormQueueFields: React.FC<VisitFormQueueFieldsProps> = (props) => {
|
|
23
|
+
const { setVisitFormCallbacks, visitFormOpenedFrom, patientChartConfig } = props;
|
|
24
|
+
if (patientChartConfig.showServiceQueueFields || visitFormOpenedFrom == 'service-queues-add-patient') {
|
|
25
|
+
return <QueueFields setOnSubmit={(onSubmit) => setVisitFormCallbacks({ onVisitCreatedOrUpdated: onSubmit })} />;
|
|
26
|
+
} else {
|
|
27
|
+
return <></>;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default VisitFormQueueFields;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
-
import { type QueueEntry, type QueueEntrySearchCriteria } from '../types';
|
|
3
|
-
import useSWR from 'swr';
|
|
4
1
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
5
|
-
import { useSWRConfig } from 'swr/_internal';
|
|
6
2
|
import isEqual from 'lodash-es/isEqual';
|
|
3
|
+
import useSWR from 'swr';
|
|
4
|
+
import { useSWRConfig } from 'swr/_internal';
|
|
5
|
+
import { type FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
6
|
+
import { type QueueEntry, type QueueEntrySearchCriteria } from '../types';
|
|
7
7
|
|
|
8
8
|
type QueueEntryResponse = FetchResponse<{
|
|
9
9
|
results: Array<QueueEntry>;
|
|
@@ -82,14 +82,15 @@ export function useQueueEntries(searchCriteria?: QueueEntrySearchCriteria, rep:
|
|
|
82
82
|
// for it yet. Next it returns stale data again, this time with `isValidating` set to true. At this
|
|
83
83
|
// point we say we are no longer waiting for mutate. Finally, it returns fresh data with `isValidating`
|
|
84
84
|
// again set to false. We may then update the data array and move on to the next page.
|
|
85
|
-
const [data, setData] = useState<Array<Array<QueueEntry>>>([]);
|
|
86
|
-
const [totalCount, setTotalCount] = useState<number>();
|
|
87
|
-
const [currentPage, setCurrentPage] = useState<number>(0);
|
|
88
|
-
const [currentSearchCriteria, setCurrentSearchCriteria] = useState(searchCriteria);
|
|
89
|
-
const [currentRep, setCurrentRep] = useState(rep);
|
|
90
|
-
const [pageUrl, setPageUrl] = useState<string>(getInitialUrl(currentRep, currentSearchCriteria));
|
|
91
|
-
const [error, setError] = useState<Error>();
|
|
92
85
|
const { mutateQueueEntries } = useMutateQueueEntries();
|
|
86
|
+
|
|
87
|
+
const [currentPage, setCurrentPage] = useState(0);
|
|
88
|
+
const [currentRep, setCurrentRep] = useState(rep);
|
|
89
|
+
const [currentSearchCriteria, setCurrentSearchCriteria] = useState(searchCriteria);
|
|
90
|
+
const [data, setData] = useState<Array<Array<QueueEntry>>>([]);
|
|
91
|
+
const [error, setError] = useState<Error | undefined>(undefined);
|
|
92
|
+
const [pageUrl, setPageUrl] = useState(getInitialUrl(currentRep, currentSearchCriteria));
|
|
93
|
+
const [totalCount, setTotalCount] = useState(0);
|
|
93
94
|
const [waitingForMutate, setWaitingForMutate] = useState(false);
|
|
94
95
|
|
|
95
96
|
const refetchAllData = useCallback(
|
|
@@ -114,7 +115,7 @@ export function useQueueEntries(searchCriteria?: QueueEntrySearchCriteria, rep:
|
|
|
114
115
|
}
|
|
115
116
|
refetchAllData(rep, searchCriteria);
|
|
116
117
|
}
|
|
117
|
-
}, [
|
|
118
|
+
}, [currentRep, currentSearchCriteria, refetchAllData, rep, searchCriteria, setCurrentSearchCriteria]);
|
|
118
119
|
|
|
119
120
|
const { data: pageData, isValidating, error: pageError } = useSWR<QueueEntryResponse, Error>(pageUrl, openmrsFetch);
|
|
120
121
|
|
package/src/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ import outpatientSideNavComponent from './side-menu/side-menu.component';
|
|
|
10
10
|
import homeDashboardComponent from './home.component';
|
|
11
11
|
import patientInfoBannerSlotComponent from './patient-info/patient-info.component';
|
|
12
12
|
import pastVisitSummaryComponent from './past-visit/past-visit.component';
|
|
13
|
-
import VisitFormQueueFields from './
|
|
13
|
+
import VisitFormQueueFields from './create-queue-entry/queue-fields/visit-form-queue-fields.extension';
|
|
14
14
|
|
|
15
15
|
export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
|
|
16
16
|
|
|
@@ -64,14 +64,6 @@ export const clearAllQueueEntries = getAsyncLifecycle(
|
|
|
64
64
|
},
|
|
65
65
|
);
|
|
66
66
|
|
|
67
|
-
export const addVisitToQueueModal = getAsyncLifecycle(
|
|
68
|
-
() => import('./add-patient-toqueue/add-patient-toqueue-dialog.component'),
|
|
69
|
-
{
|
|
70
|
-
featureName: 'add visit to queue',
|
|
71
|
-
moduleName,
|
|
72
|
-
},
|
|
73
|
-
);
|
|
74
|
-
|
|
75
67
|
export const transitionQueueEntryStatusModal = getAsyncLifecycle(
|
|
76
68
|
() => import('./transition-queue-entry/transition-queue-entry-dialog.component'),
|
|
77
69
|
{
|
|
@@ -157,11 +149,13 @@ export const addNewQueueServiceRoomWorkspace = getAsyncLifecycle(
|
|
|
157
149
|
|
|
158
150
|
export const visitFormQueueFields = getSyncLifecycle(VisitFormQueueFields, options);
|
|
159
151
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
152
|
+
export const createQueueEntryWorkspace = getAsyncLifecycle(
|
|
153
|
+
() => import('./create-queue-entry/create-queue-entry.workspace'),
|
|
154
|
+
{
|
|
155
|
+
featureName: 'create-queue-entry-workspace',
|
|
156
|
+
moduleName,
|
|
157
|
+
},
|
|
158
|
+
);
|
|
165
159
|
|
|
166
160
|
export const activeVisitsRowActions = getAsyncLifecycle(
|
|
167
161
|
() => import('./active-visits/active-visits-row-actions.component'),
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
1
4
|
import { ClickableTile } from '@carbon/react';
|
|
2
5
|
import { Edit } from '@carbon/react/icons';
|
|
3
6
|
import {
|
|
4
|
-
ConfigurableLink,
|
|
5
|
-
PatientBannerContactDetails,
|
|
6
|
-
PatientBannerToggleContactDetailsButton,
|
|
7
|
-
PatientPhoto,
|
|
8
7
|
age,
|
|
8
|
+
ConfigurableLink,
|
|
9
9
|
formatDate,
|
|
10
10
|
getPatientName,
|
|
11
11
|
parseDate,
|
|
12
|
+
PatientBannerContactDetails,
|
|
13
|
+
PatientBannerToggleContactDetailsButton,
|
|
14
|
+
PatientPhoto,
|
|
12
15
|
} from '@openmrs/esm-framework';
|
|
13
|
-
import classNames from 'classnames';
|
|
14
|
-
import React, { useState } from 'react';
|
|
15
|
-
import { useTranslation } from 'react-i18next';
|
|
16
16
|
import AppointmentDetails from './appointment-details.component';
|
|
17
17
|
import styles from './patient-info.scss';
|
|
18
18
|
|
|
@@ -23,8 +23,8 @@ interface PatientInfoProps {
|
|
|
23
23
|
|
|
24
24
|
const PatientInfo: React.FC<PatientInfoProps> = ({ patient, handlePatientInfoClick }) => {
|
|
25
25
|
const { t } = useTranslation();
|
|
26
|
-
const [showContactDetails, setShowContactDetails] = useState<boolean>(false);
|
|
27
26
|
const patientName = getPatientName(patient);
|
|
27
|
+
const [showContactDetails, setShowContactDetails] = useState(false);
|
|
28
28
|
|
|
29
29
|
const toggleShowMore = (e: React.MouseEvent) => {
|
|
30
30
|
e.stopPropagation();
|
|
@@ -32,6 +32,8 @@ const PatientInfo: React.FC<PatientInfoProps> = ({ patient, handlePatientInfoCli
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
+
// TODO: Fix this warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>.
|
|
36
|
+
// This is because the ConfigurableLink is inside a ClickableTile.
|
|
35
37
|
<ClickableTile className={styles.container} onClick={handlePatientInfoClick}>
|
|
36
38
|
<div
|
|
37
39
|
className={classNames({
|