@openmrs/esm-appointments-app 10.0.2 → 10.0.3-pre.1
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 +6 -5
- package/dist/1339.js +1 -0
- package/dist/1339.js.map +1 -0
- package/dist/1465.js +1 -0
- package/dist/1465.js.map +1 -0
- package/dist/1480.js +1 -0
- package/dist/1480.js.map +1 -0
- package/dist/1646.js +1 -0
- package/dist/1646.js.map +1 -0
- package/dist/1789.js +1 -0
- package/dist/1789.js.map +1 -0
- package/dist/1869.js +1 -0
- package/dist/1869.js.map +1 -0
- package/dist/1877.js +1 -0
- package/dist/1877.js.map +1 -0
- package/dist/1884.js +1 -0
- package/dist/1884.js.map +1 -0
- package/dist/1962.js +1 -0
- package/dist/1962.js.map +1 -0
- package/dist/2317.js +1 -0
- package/dist/2317.js.map +1 -0
- package/dist/2416.js +1 -0
- package/dist/2416.js.map +1 -0
- package/dist/2495.js +1 -0
- package/dist/2495.js.map +1 -0
- package/dist/2539.js +1 -0
- package/dist/2539.js.map +1 -0
- package/dist/2620.js +1 -0
- package/dist/2620.js.map +1 -0
- package/dist/2717.js +1 -0
- package/dist/2717.js.map +1 -0
- package/dist/282.js +1 -0
- package/dist/282.js.map +1 -0
- package/dist/2881.js +1 -0
- package/dist/2881.js.map +1 -0
- package/dist/3198.js +11 -0
- package/dist/3198.js.map +1 -0
- package/dist/3220.js +1 -0
- package/dist/3220.js.map +1 -0
- package/dist/3378.js +1 -0
- package/dist/3378.js.map +1 -0
- package/dist/3720.js +1 -0
- package/dist/3720.js.map +1 -0
- package/dist/3930.js +1 -0
- package/dist/3930.js.map +1 -0
- package/dist/3963.js +1 -0
- package/dist/3963.js.map +1 -0
- package/dist/3989.js +1 -0
- package/dist/3989.js.map +1 -0
- package/dist/4106.js +1 -0
- package/dist/4106.js.map +1 -0
- package/dist/4111.js +1 -0
- package/dist/4111.js.map +1 -0
- package/dist/4307.js +1 -0
- package/dist/4307.js.map +1 -0
- package/dist/434.js +1 -0
- package/dist/434.js.map +1 -0
- package/dist/4348.js +1 -0
- package/dist/4348.js.map +1 -0
- package/dist/4383.js +1 -0
- package/dist/4383.js.map +1 -0
- package/dist/4658.js +1 -0
- package/dist/4658.js.map +1 -0
- package/dist/466.js +1 -0
- package/dist/466.js.map +1 -0
- package/dist/4928.js +1 -0
- package/dist/4928.js.map +1 -0
- package/dist/5117.js +1 -0
- package/dist/5117.js.map +1 -0
- package/dist/5132.js +1 -0
- package/dist/5132.js.map +1 -0
- package/dist/5145.js +1 -0
- package/dist/5145.js.map +1 -0
- package/dist/5503.js +1 -0
- package/dist/5503.js.map +1 -0
- package/dist/556.js +1 -0
- package/dist/556.js.map +1 -0
- package/dist/5640.js +1 -0
- package/dist/5640.js.map +1 -0
- package/dist/5644.js +1 -0
- package/dist/5644.js.map +1 -0
- package/dist/5940.js +1 -0
- package/dist/5940.js.map +1 -0
- package/dist/6047.js +1 -0
- package/dist/6047.js.map +1 -0
- package/dist/6098.js +38 -0
- package/dist/6098.js.map +1 -0
- package/dist/6236.js +1 -0
- package/dist/6236.js.map +1 -0
- package/dist/635.js +1 -0
- package/dist/635.js.map +1 -0
- package/dist/6371.js +1 -0
- package/dist/6371.js.map +1 -0
- package/dist/6377.js +1 -0
- package/dist/6377.js.map +1 -0
- package/dist/6444.js +1 -0
- package/dist/6444.js.map +1 -0
- package/dist/6508.js +1 -0
- package/dist/6508.js.map +1 -0
- package/dist/6724.js +1 -0
- package/dist/6724.js.map +1 -0
- package/dist/6789.js +1 -0
- package/dist/6789.js.map +1 -0
- package/dist/689.js +1 -0
- package/dist/689.js.map +1 -0
- package/dist/6904.js +1 -0
- package/dist/6904.js.map +1 -0
- package/dist/7045.js +1 -0
- package/dist/7045.js.map +1 -0
- package/dist/7138.js +1 -0
- package/dist/7138.js.map +1 -0
- package/dist/7159.js +1 -0
- package/dist/7159.js.map +1 -0
- package/dist/7175.js +1 -0
- package/dist/7175.js.map +1 -0
- package/dist/7182.js +1 -0
- package/dist/7182.js.map +1 -0
- package/dist/7357.js +1 -0
- package/dist/7357.js.map +1 -0
- package/dist/7609.js +1 -0
- package/dist/7609.js.map +1 -0
- package/dist/7654.js +1 -0
- package/dist/7654.js.map +1 -0
- package/dist/7742.js +1 -0
- package/dist/7742.js.map +1 -0
- package/dist/7912.js +1 -0
- package/dist/7912.js.map +1 -0
- package/dist/8063.js +1 -0
- package/dist/8063.js.map +1 -0
- package/dist/8346.js +1 -0
- package/dist/8346.js.map +1 -0
- package/dist/8358.js +1 -0
- package/dist/8358.js.map +1 -0
- package/dist/8359.js +1 -0
- package/dist/8359.js.map +1 -0
- package/dist/8695.js +1 -0
- package/dist/8695.js.map +1 -0
- package/dist/8937.js +1 -0
- package/dist/8937.js.map +1 -0
- package/dist/8981.js +1 -0
- package/dist/8981.js.map +1 -0
- package/dist/903.js +1 -0
- package/dist/903.js.map +1 -0
- package/dist/9061.js +1 -0
- package/dist/9061.js.map +1 -0
- package/dist/9072.js +1 -0
- package/dist/9072.js.map +1 -0
- package/dist/9282.js +1 -0
- package/dist/9282.js.map +1 -0
- package/dist/9399.js +1 -0
- package/dist/9399.js.map +1 -0
- package/dist/9443.js +1 -0
- package/dist/9443.js.map +1 -0
- package/dist/9581.js +1 -0
- package/dist/9581.js.map +1 -0
- package/dist/9712.js +1 -0
- package/dist/9712.js.map +1 -0
- package/dist/9771.js +1 -0
- package/dist/9771.js.map +1 -0
- package/dist/9806.js +1 -0
- package/dist/9806.js.map +1 -0
- package/dist/main.js +6 -5
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-appointments-app.js +6 -5
- package/dist/openmrs-esm-appointments-app.js.buildmanifest.json +625 -620
- package/dist/openmrs-esm-appointments-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +3 -2
- package/src/appointments/appointment-tabs.component.tsx +38 -16
- package/src/appointments/common-components/appointments-actions.component.tsx +39 -47
- package/src/appointments/common-components/appointments-actions.test.tsx +52 -99
- package/src/appointments/common-components/appointments-table.component.tsx +109 -135
- package/src/appointments/common-components/appointments-table.scss +10 -6
- package/src/appointments/common-components/appointments-table.test.tsx +2 -9
- package/src/appointments/common-components/batch-change-appointment-statuses.modal.tsx +1 -1
- package/src/appointments/common-components/batch-change-appointment-statuses.test.tsx +8 -6
- package/src/appointments/common-components/checkin-button.component.tsx +60 -29
- package/src/appointments/common-components/end-appointment.modal.tsx +1 -1
- package/src/appointments/common-components/end-appointment.test.tsx +1 -1
- package/src/appointments/scheduled/early-appointments.component.tsx +6 -7
- package/src/appointments/scheduled/scheduled-appointments.component.tsx +26 -206
- package/src/appointments/utils.tsx +29 -16
- package/src/appointments.component.tsx +5 -13
- package/src/appointments.test.tsx +16 -4
- package/src/calendar/appointments-calendar-view.component.tsx +3 -12
- package/src/calendar/appointments-calendar-view.test.tsx +6 -1
- package/src/calendar/header/calendar-header.component.tsx +2 -2
- package/src/calendar/monthly/monthly-calendar-view.component.tsx +2 -2
- package/src/calendar/monthly/monthly-header.component.tsx +9 -8
- package/src/calendar/monthly/monthly-workload-view.component.tsx +2 -2
- package/src/config-schema.ts +17 -9
- package/src/constants.ts +12 -1
- package/src/form/appointments-form.resource.ts +1 -120
- package/src/form/appointments-form.workspace.tsx +15 -18
- package/src/header/appointments-header.component.tsx +27 -9
- package/src/helpers/functions.ts +1 -50
- package/src/home/home-appointments.component.tsx +17 -4
- package/src/hooks/useActiveVisits.ts +14 -0
- package/src/hooks/useAppointmentList.ts +12 -29
- package/src/hooks/useAppointmentService.ts +6 -1
- package/src/hooks/useAppointmentsAppContext.ts +19 -0
- package/src/hooks/useAppointmentsCalendar.ts +2 -1
- package/src/hooks/useMutateAppointments.ts +24 -0
- package/src/hooks/usePatientAppointmentHistory.ts +3 -2
- package/src/hooks/useSelectedDate.ts +24 -0
- package/src/hooks/useUnscheduledAppointments.ts +5 -1
- package/src/index.ts +0 -21
- package/src/metrics/metrics-cards/highest-volume-service.extension.tsx +27 -6
- package/src/metrics/metrics-cards/metrics-card.component.tsx +2 -1
- package/src/metrics/metrics-cards/providers-booked.extension.tsx +14 -6
- package/src/metrics/metrics-cards/scheduled-appointments.extension.tsx +20 -16
- package/src/metrics/metrics-container.component.tsx +1 -5
- package/src/metrics/metrics-header.component.tsx +2 -2
- package/src/patient-appointments/patient-appointments-detailed-summary.extension.tsx +1 -1
- package/src/patient-appointments/patient-upcoming-appointments-card.component.tsx +3 -4
- package/src/routes.json +2 -26
- package/src/store.ts +24 -41
- package/src/types/index.ts +7 -0
- package/src/workload/monthly-view-workload/monthly-view.component.tsx +2 -2
- package/src/workload/workload.component.tsx +3 -3
- package/src/workload/workload.resource.ts +1 -1
- package/translations/am.json +15 -6
- package/translations/ar.json +15 -6
- package/translations/ar_SY.json +15 -6
- package/translations/bn.json +15 -6
- package/translations/cs.json +15 -6
- package/translations/de.json +177 -168
- package/translations/en.json +15 -6
- package/translations/en_US.json +15 -6
- package/translations/es.json +15 -6
- package/translations/es_MX.json +15 -6
- package/translations/fr.json +15 -6
- package/translations/he.json +15 -6
- package/translations/hi.json +15 -6
- package/translations/hi_IN.json +15 -6
- package/translations/id.json +15 -6
- package/translations/it.json +15 -6
- package/translations/ka.json +15 -6
- package/translations/km.json +15 -6
- package/translations/ku.json +15 -6
- package/translations/ky.json +15 -6
- package/translations/lg.json +15 -6
- package/translations/ne.json +15 -6
- package/translations/pl.json +15 -6
- package/translations/pt.json +15 -6
- package/translations/pt_BR.json +15 -6
- package/translations/qu.json +15 -6
- package/translations/ro_RO.json +15 -6
- package/translations/ru_RU.json +15 -6
- package/translations/si.json +15 -6
- package/translations/sq.json +15 -6
- package/translations/sw.json +15 -6
- package/translations/sw_KE.json +15 -6
- package/translations/tr.json +15 -6
- package/translations/tr_TR.json +15 -6
- package/translations/uk.json +15 -6
- package/translations/uz.json +15 -6
- package/translations/uz@Latn.json +15 -6
- package/translations/uz_UZ.json +15 -6
- package/translations/vi.json +15 -6
- package/translations/zh.json +63 -54
- package/translations/zh_CN.json +19 -10
- package/translations/zh_TW.json +15 -6
- package/dist/1187.js +0 -1
- package/dist/1187.js.map +0 -1
- package/dist/126.js +0 -1
- package/dist/1499.js +0 -1
- package/dist/1499.js.map +0 -1
- package/dist/15.js +0 -1
- package/dist/1522.js +0 -1
- package/dist/1522.js.map +0 -1
- package/dist/1564.js +0 -1
- package/dist/1567.js +0 -1
- package/dist/1777.js +0 -1
- package/dist/1777.js.map +0 -1
- package/dist/1845.js +0 -1
- package/dist/1899.js +0 -1
- package/dist/1899.js.map +0 -1
- package/dist/1953.js +0 -1
- package/dist/2056.js +0 -11
- package/dist/2056.js.map +0 -1
- package/dist/2104.js +0 -1
- package/dist/2104.js.map +0 -1
- package/dist/215.js +0 -1
- package/dist/2178.js +0 -1
- package/dist/2417.js +0 -1
- package/dist/2417.js.map +0 -1
- package/dist/2566.js +0 -1
- package/dist/2586.js +0 -1
- package/dist/2586.js.map +0 -1
- package/dist/2759.js +0 -1
- package/dist/276.js +0 -1
- package/dist/276.js.map +0 -1
- package/dist/3089.js +0 -1
- package/dist/3089.js.map +0 -1
- package/dist/3127.js +0 -1
- package/dist/3127.js.map +0 -1
- package/dist/3230.js +0 -1
- package/dist/3277.js +0 -1
- package/dist/3277.js.map +0 -1
- package/dist/3441.js +0 -1
- package/dist/3565.js +0 -1
- package/dist/3571.js +0 -1
- package/dist/3571.js.map +0 -1
- package/dist/3746.js +0 -1
- package/dist/3925.js +0 -1
- package/dist/3946.js +0 -1
- package/dist/4085.js +0 -1
- package/dist/4085.js.map +0 -1
- package/dist/4108.js +0 -1
- package/dist/4108.js.map +0 -1
- package/dist/4448.js +0 -1
- package/dist/4448.js.map +0 -1
- package/dist/4744.js +0 -1
- package/dist/4744.js.map +0 -1
- package/dist/4809.js +0 -1
- package/dist/486.js +0 -1
- package/dist/486.js.map +0 -1
- package/dist/4894.js +0 -1
- package/dist/4970.js +0 -1
- package/dist/4970.js.map +0 -1
- package/dist/5130.js +0 -1
- package/dist/5187.js +0 -1
- package/dist/5218.js +0 -1
- package/dist/5218.js.map +0 -1
- package/dist/5327.js +0 -1
- package/dist/5327.js.map +0 -1
- package/dist/5388.js +0 -1
- package/dist/5388.js.map +0 -1
- package/dist/5491.js +0 -1
- package/dist/5491.js.map +0 -1
- package/dist/5595.js +0 -1
- package/dist/5657.js +0 -38
- package/dist/5657.js.map +0 -1
- package/dist/5961.js +0 -1
- package/dist/6133.js +0 -1
- package/dist/634.js +0 -1
- package/dist/634.js.map +0 -1
- package/dist/6456.js +0 -1
- package/dist/6466.js +0 -1
- package/dist/6613.js +0 -1
- package/dist/6783.js +0 -1
- package/dist/703.js +0 -1
- package/dist/703.js.map +0 -1
- package/dist/7251.js +0 -1
- package/dist/7251.js.map +0 -1
- package/dist/7348.js +0 -1
- package/dist/7433.js +0 -1
- package/dist/7433.js.map +0 -1
- package/dist/7513.js +0 -1
- package/dist/7513.js.map +0 -1
- package/dist/7543.js +0 -1
- package/dist/7607.js +0 -1
- package/dist/772.js +0 -1
- package/dist/8139.js +0 -1
- package/dist/8139.js.map +0 -1
- package/dist/8456.js +0 -1
- package/dist/8456.js.map +0 -1
- package/dist/8588.js +0 -1
- package/dist/8588.js.map +0 -1
- package/dist/8599.js +0 -1
- package/dist/8727.js +0 -1
- package/dist/8847.js +0 -1
- package/dist/8919.js +0 -1
- package/dist/8919.js.map +0 -1
- package/dist/9015.js +0 -1
- package/dist/9051.js +0 -1
- package/dist/9051.js.map +0 -1
- package/dist/906.js +0 -1
- package/dist/9065.js +0 -1
- package/dist/9182.js +0 -1
- package/dist/9260.js +0 -1
- package/dist/9260.js.map +0 -1
- package/dist/9327.js +0 -1
- package/dist/9327.js.map +0 -1
- package/dist/9339.js +0 -1
- package/dist/9453.js +0 -1
- package/dist/9589.js +0 -1
- package/dist/9589.js.map +0 -1
- package/dist/9650.js +0 -1
- package/dist/9650.js.map +0 -1
- package/dist/9833.js +0 -1
- package/dist/9833.js.map +0 -1
- package/dist/9920.js +0 -1
- package/dist/9938.js +0 -1
- package/dist/9943.js +0 -1
- package/dist/9943.js.map +0 -1
- package/src/appointments/scheduled/appointments-list.component.tsx +0 -51
- package/src/hooks/useClinicalMetrics.ts +0 -94
- package/src/hooks/useTodaysVisits.ts +0 -19
- package/src/scheduled-appointments-config-schema.ts +0 -177
|
@@ -3,19 +3,18 @@ import { useTranslation } from 'react-i18next';
|
|
|
3
3
|
import { filterByServiceType } from '../utils';
|
|
4
4
|
import { useEarlyAppointmentList } from '../../hooks/useAppointmentList';
|
|
5
5
|
import AppointmentsTable from '../common-components/appointments-table.component';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
appointmentServiceTypes?: Array<string>;
|
|
9
|
-
date: string;
|
|
10
|
-
}
|
|
6
|
+
import { useAppointmentsStore } from '../../store';
|
|
7
|
+
import { useSelectedDate } from '../../hooks/useSelectedDate';
|
|
11
8
|
|
|
12
9
|
/**
|
|
13
10
|
* Component to display early appointments
|
|
14
11
|
* Note that although we define this extension in routes.jsx, we currently don't wire it into the scheduled-appointments-panels-slot by default because it requests a custom endpoint (see useEarlyAppointments) not provided by the standard Bahmni Appointments module
|
|
15
12
|
*/
|
|
16
|
-
const EarlyAppointments: React.FC
|
|
13
|
+
const EarlyAppointments: React.FC = () => {
|
|
17
14
|
const { t } = useTranslation();
|
|
18
|
-
const {
|
|
15
|
+
const { appointmentServiceTypes } = useAppointmentsStore();
|
|
16
|
+
const selectedDate = useSelectedDate();
|
|
17
|
+
const { earlyAppointmentList, isLoading } = useEarlyAppointmentList(selectedDate);
|
|
19
18
|
|
|
20
19
|
const appointments = filterByServiceType(earlyAppointmentList, appointmentServiceTypes).map((appointment, index) => {
|
|
21
20
|
return {
|
|
@@ -1,225 +1,45 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
|
-
import { ContentSwitcher, Switch } from '@carbon/react';
|
|
5
4
|
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
|
|
6
|
-
import {
|
|
7
|
-
ExtensionSlot,
|
|
8
|
-
Extension,
|
|
9
|
-
useConnectedExtensions,
|
|
10
|
-
type ConnectedExtension,
|
|
11
|
-
type ConfigObject,
|
|
12
|
-
useLayoutType,
|
|
13
|
-
isDesktop,
|
|
14
|
-
useAssignedExtensions,
|
|
15
|
-
} from '@openmrs/esm-framework';
|
|
5
|
+
import { formatDate, parseDate, useDefineAppContext } from '@openmrs/esm-framework';
|
|
16
6
|
import { useAppointmentsStore } from '../../store';
|
|
7
|
+
import { type AppointmentsAppContext } from '../../types';
|
|
8
|
+
import { useAppointmentList } from '../../hooks/useAppointmentList';
|
|
9
|
+
import AppointmentsTable from '../common-components/appointments-table.component';
|
|
10
|
+
import { useSelectedDate } from '../../hooks/useSelectedDate';
|
|
17
11
|
import styles from './scheduled-appointments.scss';
|
|
18
|
-
import { type AppointmentPanelConfig } from '../../scheduled-appointments-config-schema';
|
|
19
12
|
|
|
20
13
|
dayjs.extend(isSameOrBefore);
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
appointmentServiceTypes?: Array<string>;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type DateType = 'pastDate' | 'today' | 'futureDate';
|
|
27
|
-
|
|
28
|
-
const scheduledAppointmentsPanelsSlot = 'scheduled-appointments-panels-slot';
|
|
29
|
-
|
|
30
|
-
const ScheduledAppointments: React.FC<ScheduledAppointmentsProps> = ({ appointmentServiceTypes }) => {
|
|
15
|
+
const ScheduledAppointments: React.FC<{}> = () => {
|
|
31
16
|
const { t } = useTranslation();
|
|
32
|
-
const {
|
|
33
|
-
const
|
|
34
|
-
const responsiveSize = isDesktop(layout) ? 'sm' : 'md';
|
|
17
|
+
const { appointmentServiceTypes } = useAppointmentsStore();
|
|
18
|
+
const selectedDate = useSelectedDate();
|
|
35
19
|
|
|
36
|
-
|
|
37
|
-
// t('checkedIn', 'Checked in');
|
|
38
|
-
// t('expected', 'Expected');
|
|
20
|
+
const { appointmentList: appointmentsForSelectedDate, isLoading, error } = useAppointmentList(selectedDate);
|
|
39
21
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const shouldShowPanel = useCallback(
|
|
45
|
-
(panel: Omit<ConnectedExtension, 'config'>) => allowedExtensions[panel.name] ?? false,
|
|
46
|
-
[allowedExtensions],
|
|
47
|
-
);
|
|
22
|
+
const appointmentForSelectedDateFilteredByServiceTypes =
|
|
23
|
+
appointmentServiceTypes.length > 0
|
|
24
|
+
? appointmentsForSelectedDate.filter(({ service }) => appointmentServiceTypes.includes(service.uuid))
|
|
25
|
+
: appointmentsForSelectedDate;
|
|
48
26
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
setDateType('futureDate');
|
|
56
|
-
} else {
|
|
57
|
-
setDateType('today');
|
|
58
|
-
}
|
|
59
|
-
}, [selectedDate]);
|
|
60
|
-
|
|
61
|
-
useEffect(() => {
|
|
62
|
-
// This is intended to cover two things:
|
|
63
|
-
// 1. If no current tab is set, set it to the first allowed tab
|
|
64
|
-
// 2. If a current tab is set, but the tab is no longer allowed in this context, set it to the
|
|
65
|
-
// first allowed tab
|
|
66
|
-
if (allowedExtensions && (currentTab === null || !allowedExtensions[currentTab])) {
|
|
67
|
-
for (const extension of Object.getOwnPropertyNames(allowedExtensions)) {
|
|
68
|
-
if (allowedExtensions[extension]) {
|
|
69
|
-
setCurrentTab(extension);
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}, [allowedExtensions, currentTab]);
|
|
75
|
-
|
|
76
|
-
const panelsToShow = scheduledAppointmentPanels.filter(shouldShowPanel);
|
|
27
|
+
useDefineAppContext<AppointmentsAppContext>('appointments', {
|
|
28
|
+
appointmentForSelectedDateFilteredByServiceTypes,
|
|
29
|
+
isLoading,
|
|
30
|
+
error,
|
|
31
|
+
});
|
|
32
|
+
const formattedDate = formatDate(parseDate(selectedDate), { mode: 'standard', time: false });
|
|
77
33
|
|
|
78
34
|
return (
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
selectedIndex={panelsToShow.findIndex((panel) => panel.name == currentTab) ?? 0}
|
|
85
|
-
selectionMode="manual">
|
|
86
|
-
{panelsToShow.map((panel) => (
|
|
87
|
-
<Switch key={`panel-${panel.name}`} name={panel.name}>
|
|
88
|
-
{t(panel.config.title)}
|
|
89
|
-
</Switch>
|
|
90
|
-
))}
|
|
91
|
-
</ContentSwitcher>
|
|
92
|
-
|
|
93
|
-
<ExtensionSlot name={scheduledAppointmentsPanelsSlot}>
|
|
94
|
-
{(extension) => {
|
|
95
|
-
return (
|
|
96
|
-
<ExtensionWrapper
|
|
97
|
-
appointmentServiceTypes={appointmentServiceTypes}
|
|
98
|
-
currentTab={currentTab}
|
|
99
|
-
date={selectedDate}
|
|
100
|
-
dateType={dateType}
|
|
101
|
-
extension={extension}
|
|
102
|
-
hideExtensionTab={hideExtension}
|
|
103
|
-
showExtensionTab={showExtension}
|
|
104
|
-
/>
|
|
105
|
-
);
|
|
106
|
-
}}
|
|
107
|
-
</ExtensionSlot>
|
|
108
|
-
</>
|
|
109
|
-
);
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
function useAllowedExtensions() {
|
|
113
|
-
const [allowedExtensions, dispatch] = useReducer(
|
|
114
|
-
(state: Record<string, boolean>, action: { type: 'show_extension' | 'hide_extension'; extension: string }) => {
|
|
115
|
-
let addedState = {} as Record<string, boolean>;
|
|
116
|
-
switch (action.type) {
|
|
117
|
-
case 'show_extension':
|
|
118
|
-
addedState[action.extension] = true;
|
|
119
|
-
break;
|
|
120
|
-
case 'hide_extension':
|
|
121
|
-
addedState[action.extension] = false;
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return { ...state, ...addedState };
|
|
126
|
-
},
|
|
127
|
-
{},
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
allowedExtensions: allowedExtensions as Readonly<Record<string, boolean>>,
|
|
132
|
-
showExtension: (extension: string) => dispatch({ type: 'show_extension', extension }),
|
|
133
|
-
hideExtension: (extension: string) => dispatch({ type: 'hide_extension', extension }),
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function ExtensionWrapper({
|
|
138
|
-
extension,
|
|
139
|
-
currentTab,
|
|
140
|
-
appointmentServiceTypes,
|
|
141
|
-
date,
|
|
142
|
-
dateType,
|
|
143
|
-
showExtensionTab,
|
|
144
|
-
hideExtensionTab,
|
|
145
|
-
}: {
|
|
146
|
-
extension: ConnectedExtension;
|
|
147
|
-
currentTab: string;
|
|
148
|
-
appointmentServiceTypes: Array<string>;
|
|
149
|
-
date: string;
|
|
150
|
-
dateType: DateType;
|
|
151
|
-
showExtensionTab: (extension: string) => void;
|
|
152
|
-
hideExtensionTab: (extension: string) => void;
|
|
153
|
-
}) {
|
|
154
|
-
const currentConfig = useRef(null);
|
|
155
|
-
const currentDateType = useRef(dateType);
|
|
156
|
-
|
|
157
|
-
// This use effect hook controls whether the tab for this extension should render
|
|
158
|
-
useEffect(() => {
|
|
159
|
-
if (
|
|
160
|
-
currentConfig.current === null ||
|
|
161
|
-
(currentConfig.current !== null && !shallowEqual(currentConfig.current, extension.config)) ||
|
|
162
|
-
currentDateType.current !== dateType
|
|
163
|
-
) {
|
|
164
|
-
currentConfig.current = extension.config;
|
|
165
|
-
currentDateType.current = dateType;
|
|
166
|
-
if (shouldDisplayExtensionTab(extension?.config as AppointmentPanelConfig, dateType)) {
|
|
167
|
-
showExtensionTab(extension.name);
|
|
168
|
-
} else {
|
|
169
|
-
hideExtensionTab(extension.name);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}, [extension, dateType, showExtensionTab, hideExtensionTab]);
|
|
173
|
-
|
|
174
|
-
if (extension.config == null) {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return (
|
|
179
|
-
<div
|
|
180
|
-
key={extension.name}
|
|
181
|
-
className={styles.container}
|
|
182
|
-
style={{ display: currentTab === extension.name ? 'block' : 'none' }}>
|
|
183
|
-
<Extension
|
|
184
|
-
state={{
|
|
185
|
-
date,
|
|
186
|
-
appointmentServiceTypes,
|
|
187
|
-
status: extension.config?.status,
|
|
188
|
-
title: extension.config?.title,
|
|
189
|
-
}}
|
|
35
|
+
<div className={styles.container}>
|
|
36
|
+
<AppointmentsTable
|
|
37
|
+
appointments={appointmentForSelectedDateFilteredByServiceTypes}
|
|
38
|
+
isLoading={isLoading}
|
|
39
|
+
tableHeading={t('appointmentsForDate', 'Appointments for: {{date}}', { date: formattedDate })}
|
|
190
40
|
/>
|
|
191
41
|
</div>
|
|
192
42
|
);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function shouldDisplayExtensionTab(config: AppointmentPanelConfig | undefined, dateType: DateType): boolean {
|
|
196
|
-
if (!config) {
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
switch (dateType) {
|
|
201
|
-
case 'futureDate':
|
|
202
|
-
return config.showForFutureDate ?? false;
|
|
203
|
-
case 'pastDate':
|
|
204
|
-
return config.showForPastDate ?? false;
|
|
205
|
-
case 'today':
|
|
206
|
-
return config.showForToday ?? false;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function shallowEqual(objA: object, objB: object) {
|
|
211
|
-
if (Object.is(objA, objB)) {
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
|
216
|
-
return false;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const objAKeys = Object.getOwnPropertyNames(objA);
|
|
220
|
-
const objBKeys = Object.getOwnPropertyNames(objB);
|
|
221
|
-
|
|
222
|
-
return objAKeys.length === objBKeys.length && objAKeys.every((key) => objA[key] === objB[key]);
|
|
223
|
-
}
|
|
43
|
+
};
|
|
224
44
|
|
|
225
45
|
export default ScheduledAppointments;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import { type Appointment } from '../types';
|
|
2
|
+
import { type AppointmentStatus, type Appointment } from '../types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Returns an array of page sizes for the given data and page size.
|
|
@@ -46,31 +46,44 @@ export function useSearchResults<T>(data: T[], searchString: string): T[] {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
49
|
+
* Performs client-side filtering of appointments based on the selected
|
|
50
|
+
* statuses and the search string.
|
|
51
|
+
* The search string matches on the following:
|
|
51
52
|
* case-insensitive partial match on patient name
|
|
52
53
|
* case-insensitive partial match on the primary patient identifier
|
|
53
54
|
* case-insensitive exact match on any of the patient identifiers
|
|
54
55
|
* @param {Appointment[]} data - The array of data to filter
|
|
55
56
|
* @param {string} searchString - The string to search for in the data
|
|
57
|
+
* @param {Array<AppointmentStatus>} selectedAppointmentStatuses - The array of selected appointment statuses to filter by
|
|
56
58
|
* @returns {Appointment[]} The filtered array of data
|
|
57
59
|
*/
|
|
58
|
-
export function useAppointmentSearchResults(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
export function useAppointmentSearchResults(
|
|
61
|
+
data: Appointment[],
|
|
62
|
+
searchString: string,
|
|
63
|
+
selectedAppointmentStatuses: Array<AppointmentStatus>,
|
|
64
|
+
): Appointment[] {
|
|
65
|
+
return useMemo(
|
|
66
|
+
() =>
|
|
67
|
+
data.filter((appointment) => {
|
|
68
|
+
if (selectedAppointmentStatuses.length > 0 && !selectedAppointmentStatuses.includes(appointment.status)) {
|
|
69
|
+
return false;
|
|
65
70
|
}
|
|
66
|
-
|
|
71
|
+
|
|
72
|
+
if (searchString && searchString.trim() !== '') {
|
|
73
|
+
const lowerCaseSearch = searchString.toLowerCase();
|
|
74
|
+
if (appointment.patient.name?.toLowerCase()?.includes(lowerCaseSearch)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if (appointment.patient.identifier?.toLowerCase()?.includes(lowerCaseSearch)) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
} else {
|
|
67
82
|
return true;
|
|
68
83
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return data;
|
|
73
|
-
}, [searchString, data]);
|
|
84
|
+
}),
|
|
85
|
+
[searchString, data, selectedAppointmentStatuses],
|
|
86
|
+
);
|
|
74
87
|
}
|
|
75
88
|
|
|
76
89
|
export function filterByServiceType(appointmentList: Array<Appointment>, appointmentServiceTypes: Array<string>) {
|
|
@@ -1,36 +1,28 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
|
-
import dayjs from 'dayjs';
|
|
3
2
|
import { useTranslation } from 'react-i18next';
|
|
4
3
|
import { useParams } from 'react-router-dom';
|
|
5
|
-
import { omrsDateFormat } from './constants';
|
|
6
4
|
import AppointmentTabs from './appointments/appointment-tabs.component';
|
|
7
5
|
import AppointmentsHeader from './header/appointments-header.component';
|
|
8
6
|
import AppointmentMetrics from './metrics/metrics-container.component';
|
|
9
|
-
import { useAppointmentsStore
|
|
7
|
+
import { useAppointmentsStore } from './store';
|
|
10
8
|
|
|
11
9
|
const Appointments: React.FC = () => {
|
|
12
10
|
const { t } = useTranslation();
|
|
13
|
-
const {
|
|
11
|
+
const { setAppointmentServiceTypes } = useAppointmentsStore();
|
|
14
12
|
|
|
15
13
|
const params = useParams();
|
|
16
14
|
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
if (params.date) {
|
|
19
|
-
setSelectedDate(dayjs(params.date).startOf('day').format(omrsDateFormat));
|
|
20
|
-
}
|
|
21
|
-
}, [params.date]);
|
|
22
|
-
|
|
23
15
|
useEffect(() => {
|
|
24
16
|
if (params.serviceType) {
|
|
25
17
|
setAppointmentServiceTypes([params.serviceType]);
|
|
26
18
|
}
|
|
27
|
-
}, [params.serviceType]);
|
|
19
|
+
}, [params.serviceType, setAppointmentServiceTypes]);
|
|
28
20
|
|
|
29
21
|
return (
|
|
30
22
|
<>
|
|
31
23
|
<AppointmentsHeader title={t('appointments', 'Appointments')} showServiceTypeFilter />
|
|
32
|
-
<AppointmentMetrics
|
|
33
|
-
<AppointmentTabs
|
|
24
|
+
<AppointmentMetrics />
|
|
25
|
+
<AppointmentTabs />
|
|
34
26
|
</>
|
|
35
27
|
);
|
|
36
28
|
};
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { useConfig, getDefaultsFromConfigSchema } from '@openmrs/esm-framework';
|
|
3
4
|
import Appointments from './appointments.component';
|
|
5
|
+
import { type ConfigObject, configSchema } from './config-schema';
|
|
6
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
7
|
+
|
|
8
|
+
const mockUseConfig = jest.mocked(useConfig<ConfigObject>);
|
|
4
9
|
|
|
5
|
-
// TODO: Tweak the ExtensionSlot stub in the framework to not return a function. Functions are not valid React children.
|
|
6
10
|
describe('Appointments', () => {
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
mockUseConfig.mockReturnValue({
|
|
13
|
+
...getDefaultsFromConfigSchema(configSchema),
|
|
14
|
+
});
|
|
15
|
+
});
|
|
9
16
|
|
|
10
|
-
|
|
17
|
+
it('renders the appointments dashboard', async () => {
|
|
18
|
+
render(
|
|
19
|
+
<BrowserRouter>
|
|
20
|
+
<Appointments />
|
|
21
|
+
</BrowserRouter>,
|
|
22
|
+
);
|
|
11
23
|
|
|
12
24
|
expect(screen.getByRole('button', { name: /appointments calendar/i })).toBeInTheDocument();
|
|
13
25
|
expect(screen.getByText(/filter appointments by service type/i)).toBeInTheDocument();
|
|
@@ -1,27 +1,18 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
import { useParams } from 'react-router-dom';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { omrsDateFormat } from '../constants';
|
|
6
5
|
import { useAppointmentsCalendar } from '../hooks/useAppointmentsCalendar';
|
|
7
6
|
import AppointmentsHeader from '../header/appointments-header.component';
|
|
8
7
|
import CalendarHeader from './header/calendar-header.component';
|
|
9
8
|
import MonthlyCalendarView from './monthly/monthly-calendar-view.component';
|
|
10
|
-
import {
|
|
9
|
+
import { useSelectedDate } from '../hooks/useSelectedDate';
|
|
11
10
|
|
|
12
11
|
const AppointmentsCalendarView: React.FC = () => {
|
|
13
12
|
const { t } = useTranslation();
|
|
14
|
-
const
|
|
13
|
+
const selectedDate = useSelectedDate();
|
|
15
14
|
const { calendarEvents } = useAppointmentsCalendar(dayjs(selectedDate).toISOString(), 'monthly');
|
|
16
15
|
|
|
17
|
-
let params = useParams();
|
|
18
|
-
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
if (params.date) {
|
|
21
|
-
setSelectedDate(dayjs(params.date).startOf('day').format(omrsDateFormat));
|
|
22
|
-
}
|
|
23
|
-
}, [params.date]);
|
|
24
|
-
|
|
25
16
|
return (
|
|
26
17
|
<div data-testid="appointments-calendar">
|
|
27
18
|
<AppointmentsHeader title={t('calendar', 'Calendar')} />
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, screen } from '@testing-library/react';
|
|
3
3
|
import AppointmentsCalendarView from './appointments-calendar-view.component';
|
|
4
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
4
5
|
|
|
5
6
|
describe('Appointment calendar view', () => {
|
|
6
7
|
it('renders appointments in calendar view from appointments list', async () => {
|
|
7
|
-
render(
|
|
8
|
+
render(
|
|
9
|
+
<BrowserRouter>
|
|
10
|
+
<AppointmentsCalendarView />
|
|
11
|
+
</BrowserRouter>,
|
|
12
|
+
);
|
|
8
13
|
|
|
9
14
|
const expectedTableRows = [
|
|
10
15
|
/John Wilson 30-Aug-2021 03:35 03:35 Dr James Cook Outpatient Walk in appointments/,
|
|
@@ -5,12 +5,12 @@ import { Button } from '@carbon/react';
|
|
|
5
5
|
import { ArrowLeft } from '@carbon/react/icons';
|
|
6
6
|
import { navigate } from '@openmrs/esm-framework';
|
|
7
7
|
import { spaHomePage } from '../../constants';
|
|
8
|
-
import {
|
|
8
|
+
import { useSelectedDate } from '../../hooks/useSelectedDate';
|
|
9
9
|
import styles from './calendar-header.scss';
|
|
10
10
|
|
|
11
11
|
const CalendarHeader: React.FC = () => {
|
|
12
12
|
const { t } = useTranslation();
|
|
13
|
-
const
|
|
13
|
+
const selectedDate = useSelectedDate();
|
|
14
14
|
|
|
15
15
|
const handleClick = () => {
|
|
16
16
|
navigate({ to: `${spaHomePage}/appointments/${dayjs(selectedDate).format('YYYY-MM-DD')}` });
|
|
@@ -2,10 +2,10 @@ import React from 'react';
|
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
import isBetween from 'dayjs/plugin/isBetween';
|
|
4
4
|
import { type DailyAppointmentsCountByService } from '../../types';
|
|
5
|
-
import { useAppointmentsStore } from '../../store';
|
|
6
5
|
import { monthDays } from '../../helpers';
|
|
7
6
|
import MonthlyViewWorkload from './monthly-workload-view.component';
|
|
8
7
|
import MonthlyHeader from './monthly-header.component';
|
|
8
|
+
import { useSelectedDate } from '../../hooks/useSelectedDate';
|
|
9
9
|
import styles from '../appointments-calendar-view-view.scss';
|
|
10
10
|
|
|
11
11
|
dayjs.extend(isBetween);
|
|
@@ -15,7 +15,7 @@ interface MonthlyCalendarViewProps {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const MonthlyCalendarView: React.FC<MonthlyCalendarViewProps> = ({ events }) => {
|
|
18
|
-
const
|
|
18
|
+
const selectedDate = useSelectedDate();
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<div className={styles.calendarViewContainer}>
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import React, { useCallback } from 'react';
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { Button } from '@carbon/react';
|
|
5
5
|
import { formatDate } from '@openmrs/esm-framework';
|
|
6
|
-
import { omrsDateFormat } from '../../constants';
|
|
7
|
-
import { useAppointmentsStore, setSelectedDate } from '../../store';
|
|
8
6
|
import DaysOfWeekCard from './days-of-week.component';
|
|
9
7
|
import styles from './monthly-header.scss';
|
|
8
|
+
import { useSelectedDate } from '../../hooks/useSelectedDate';
|
|
10
9
|
|
|
11
10
|
const DAYS_IN_WEEK = ['SUN', 'MON', 'TUE', 'WED', 'THUR', 'FRI', 'SAT'];
|
|
12
11
|
|
|
13
12
|
const MonthlyHeader: React.FC = () => {
|
|
14
13
|
const { t } = useTranslation();
|
|
15
|
-
const
|
|
14
|
+
const selectedDate = useSelectedDate();
|
|
15
|
+
|
|
16
|
+
const [calendarSelectedDate, setCalendarSelectedDate] = useState(dayjs(selectedDate));
|
|
16
17
|
|
|
17
18
|
const handleSelectPrevMonth = useCallback(() => {
|
|
18
|
-
|
|
19
|
-
}, [
|
|
19
|
+
setCalendarSelectedDate(calendarSelectedDate.subtract(1, 'month'));
|
|
20
|
+
}, [calendarSelectedDate, setCalendarSelectedDate]);
|
|
20
21
|
|
|
21
22
|
const handleSelectNextMonth = useCallback(() => {
|
|
22
|
-
|
|
23
|
-
}, [
|
|
23
|
+
setCalendarSelectedDate(calendarSelectedDate.add(1, 'month'));
|
|
24
|
+
}, [calendarSelectedDate, setCalendarSelectedDate]);
|
|
24
25
|
|
|
25
26
|
return (
|
|
26
27
|
<>
|
|
@@ -6,8 +6,8 @@ import { navigate, useLayoutType } from '@openmrs/esm-framework';
|
|
|
6
6
|
import { spaHomePage } from '../../constants';
|
|
7
7
|
import { isSameMonth } from '../../helpers';
|
|
8
8
|
import { type DailyAppointmentsCountByService } from '../../types';
|
|
9
|
-
import { useAppointmentsStore } from '../../store';
|
|
10
9
|
import MonthlyWorkloadViewExpanded from './monthly-workload-view-expanded.component';
|
|
10
|
+
import { useSelectedDate } from '../../hooks/useSelectedDate';
|
|
11
11
|
import styles from './monthly-view-workload.scss';
|
|
12
12
|
|
|
13
13
|
export interface MonthlyWorkloadViewProps {
|
|
@@ -18,7 +18,7 @@ export interface MonthlyWorkloadViewProps {
|
|
|
18
18
|
|
|
19
19
|
const MonthlyWorkloadView: React.FC<MonthlyWorkloadViewProps> = ({ dateTime, events, showAllServices = false }) => {
|
|
20
20
|
const layout = useLayoutType();
|
|
21
|
-
const
|
|
21
|
+
const selectedDate = useSelectedDate();
|
|
22
22
|
|
|
23
23
|
const currentData = useMemo(
|
|
24
24
|
() =>
|
package/src/config-schema.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Type, validators } from '@openmrs/esm-framework';
|
|
2
2
|
import { appointmentColumnTypes } from './constants';
|
|
3
3
|
|
|
4
|
-
type AppointmentColumnType = (typeof appointmentColumnTypes)[number];
|
|
5
|
-
|
|
6
4
|
export const configSchema = {
|
|
7
5
|
allowAllDayAppointments: {
|
|
8
6
|
_type: Type.Boolean,
|
|
@@ -33,11 +31,6 @@ export const configSchema = {
|
|
|
33
31
|
_default: true,
|
|
34
32
|
_description: 'Whether the check-in button on the "Appointments" list should be enabled',
|
|
35
33
|
},
|
|
36
|
-
showIfActiveVisit: {
|
|
37
|
-
_type: Type.Boolean,
|
|
38
|
-
_default: false,
|
|
39
|
-
_description: 'Whether to show the check-in button if the patient currently has an active visit',
|
|
40
|
-
},
|
|
41
34
|
customUrl: {
|
|
42
35
|
_type: Type.String,
|
|
43
36
|
_default: '',
|
|
@@ -80,11 +73,26 @@ export const configSchema = {
|
|
|
80
73
|
_description:
|
|
81
74
|
'Whether to show the Unscheduled Appointments tab. Note that configuring this to true requires a custom unscheduledAppointment endpoint not currently available',
|
|
82
75
|
},
|
|
76
|
+
showEarlyAppointmentsTab: {
|
|
77
|
+
_type: Type.Boolean,
|
|
78
|
+
_default: false,
|
|
79
|
+
_description:
|
|
80
|
+
'Whether to show the Early Appointments tab. Note that configuring this to true requires a custom earlyAppointment endpoint not currently available',
|
|
81
|
+
},
|
|
83
82
|
appointmentsTableColumns: {
|
|
84
83
|
_type: Type.Array,
|
|
85
84
|
_description:
|
|
86
85
|
'Columns to display in the appointment table. Available options: ' + appointmentColumnTypes.join(', '),
|
|
87
|
-
_default: [
|
|
86
|
+
_default: [
|
|
87
|
+
'patientName',
|
|
88
|
+
'identifier',
|
|
89
|
+
'location',
|
|
90
|
+
'serviceType',
|
|
91
|
+
'dateTime',
|
|
92
|
+
'visitStartTime',
|
|
93
|
+
'status',
|
|
94
|
+
'actions',
|
|
95
|
+
],
|
|
88
96
|
_elements: {
|
|
89
97
|
_type: Type.String,
|
|
90
98
|
_validators: [validators.oneOf(appointmentColumnTypes)],
|
|
@@ -99,7 +107,6 @@ export interface ConfigObject {
|
|
|
99
107
|
appointmentsTableColumns: Array<string>;
|
|
100
108
|
checkInButton: {
|
|
101
109
|
enabled: boolean;
|
|
102
|
-
showIfActiveVisit: boolean;
|
|
103
110
|
customUrl: string;
|
|
104
111
|
};
|
|
105
112
|
checkOutButton: {
|
|
@@ -110,4 +117,5 @@ export interface ConfigObject {
|
|
|
110
117
|
includePhoneNumberInExcelSpreadsheet: boolean;
|
|
111
118
|
patientIdentifierType: string;
|
|
112
119
|
showUnscheduledAppointmentsTab: boolean;
|
|
120
|
+
showEarlyAppointmentsTab: boolean;
|
|
113
121
|
}
|
package/src/constants.ts
CHANGED
|
@@ -65,8 +65,19 @@ export const appointmentColumnTypes = [
|
|
|
65
65
|
'serviceType',
|
|
66
66
|
// t('status', 'Status')
|
|
67
67
|
'status',
|
|
68
|
-
// t('dateTime', '
|
|
68
|
+
// t('dateTime', 'Appointment time')
|
|
69
69
|
'dateTime',
|
|
70
70
|
// t('provider', 'Provider')
|
|
71
71
|
'provider',
|
|
72
|
+
// t('actions', 'Actions')
|
|
73
|
+
'actions',
|
|
74
|
+
// t('visitStartTime', 'Visit start time')
|
|
75
|
+
'visitStartTime',
|
|
72
76
|
] as const;
|
|
77
|
+
|
|
78
|
+
// added to prevent auto-removal of translations for dynamic keys
|
|
79
|
+
// t('Scheduled', 'Scheduled')
|
|
80
|
+
// t('CheckedIn', 'Checked in')
|
|
81
|
+
// t('Cancelled', 'Cancelled')
|
|
82
|
+
// t('Missed', 'Missed')
|
|
83
|
+
// t('Completed', 'Completed')
|