@openmrs/esm-appointments-app 4.1.1-pre.996 → 4.2.0
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 +20 -20
- package/dist/153.js +1 -1
- package/dist/153.js.map +1 -0
- package/dist/319.js +1 -1
- package/dist/34.js +1 -1
- package/dist/34.js.map +1 -0
- package/dist/351.js +1 -1
- package/dist/351.js.map +1 -0
- package/dist/352.js +1 -1
- package/dist/352.js.map +1 -0
- package/dist/430.js +1 -1
- package/dist/430.js.map +1 -0
- package/dist/437.js +1 -1
- package/dist/437.js.map +1 -0
- package/dist/45.js +1 -1
- package/dist/45.js.map +1 -0
- package/dist/456.js +1 -0
- package/dist/456.js.map +1 -0
- package/dist/458.js +2 -0
- package/dist/458.js.map +1 -0
- package/dist/497.js +1 -1
- package/dist/497.js.map +1 -0
- package/dist/542.js +1 -1
- package/dist/542.js.map +1 -0
- package/dist/568.js +1 -1
- package/dist/568.js.map +1 -0
- package/dist/574.js +1 -1
- package/dist/647.js +1 -1
- package/dist/647.js.map +1 -0
- package/dist/685.js +1 -1
- package/dist/685.js.map +1 -0
- package/dist/692.js +1 -1
- package/dist/692.js.map +1 -0
- package/dist/757.js +1 -1
- package/dist/784.js +1 -1
- package/dist/784.js.map +1 -0
- package/dist/807.js +1 -1
- package/dist/821.js +1 -1
- package/dist/821.js.map +1 -0
- package/dist/830.js +1 -1
- package/dist/830.js.map +1 -0
- package/dist/843.js +1 -1
- package/dist/843.js.map +1 -0
- package/dist/858.js +1 -1
- package/dist/858.js.map +1 -0
- package/dist/976.js +1 -0
- package/dist/976.js.map +1 -0
- package/dist/984.js +1 -0
- package/dist/984.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -0
- package/dist/openmrs-esm-appointments-app.js +1 -1
- package/dist/openmrs-esm-appointments-app.js.buildmanifest.json +205 -182
- package/dist/openmrs-esm-appointments-app.js.map +1 -0
- package/dist/openmrs-esm-appointments-app.old +1 -1
- package/package.json +2 -2
- package/src/appointment-forms/appointment-forms.resource.ts +5 -17
- package/src/appointment-forms/appointments-form.component.tsx +102 -234
- package/src/appointment-forms/appointments-form.scss +5 -5
- package/src/appointment-forms/appointments-forms.test.tsx +6 -16
- package/src/appointment-forms/useInitialFormValues.tsx +49 -0
- package/src/appointment-forms/workload-helper.ts +13 -19
- package/src/appointments/appointment-list.component.tsx +6 -6
- package/src/appointments/appointment-list.test.tsx +2 -2
- package/src/appointments-tabs/unscheduled-appointments.component.tsx +14 -9
- package/src/config-schema.ts +4 -13
- package/src/patient-search/patient-search.scss +1 -3
- package/translations/en.json +6 -7
- package/__mocks__/appointments.mock.ts +0 -411
- package/dist/268.js +0 -1
- package/dist/285.js +0 -2
- package/dist/339.js +0 -1
- package/dist/39.js +0 -1
- package/dist/842.js +0 -1
- /package/dist/{285.js.LICENSE.txt → 458.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { OpenmrsResource, useSession } from '@openmrs/esm-framework';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import { amPm } from '../helpers';
|
|
4
|
+
import { MappedAppointment } from '../types';
|
|
5
|
+
|
|
6
|
+
export interface PatientAppointment {
|
|
7
|
+
appointmentKind: string;
|
|
8
|
+
status: string;
|
|
9
|
+
serviceUuid: string;
|
|
10
|
+
startDateTime: string;
|
|
11
|
+
endDateTime: string;
|
|
12
|
+
providerUuid: string;
|
|
13
|
+
providers: Array<OpenmrsResource>;
|
|
14
|
+
comments: string;
|
|
15
|
+
locationUuid: string;
|
|
16
|
+
patientUuid: string;
|
|
17
|
+
appointmentNumber: string;
|
|
18
|
+
uuid?: string;
|
|
19
|
+
frequency: string;
|
|
20
|
+
visitDate: Date;
|
|
21
|
+
timeFormat: amPm;
|
|
22
|
+
isFullDay: boolean;
|
|
23
|
+
day: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const useInitialAppointmentFormValue = (appointment: MappedAppointment, patientUuid: string) => {
|
|
27
|
+
const session = useSession();
|
|
28
|
+
const patientAppointment: PatientAppointment = {
|
|
29
|
+
appointmentKind: appointment?.appointmentKind ?? 'Scheduled',
|
|
30
|
+
status: appointment?.status ?? 'Scheduled',
|
|
31
|
+
serviceUuid: appointment?.serviceUuid ?? '',
|
|
32
|
+
startDateTime: dayjs(new Date()).format('hh:mm'),
|
|
33
|
+
endDateTime: dayjs(new Date()).format('hh:mm'),
|
|
34
|
+
providers: appointment?.providers ?? [],
|
|
35
|
+
providerUuid: appointment?.providers[0]?.uuid ?? session?.currentProvider?.uuid,
|
|
36
|
+
comments: appointment?.comments ?? '',
|
|
37
|
+
locationUuid: appointment?.location ? appointment.location['uuid'] : session?.sessionLocation?.uuid,
|
|
38
|
+
frequency: '',
|
|
39
|
+
uuid: appointment?.id ?? '',
|
|
40
|
+
appointmentNumber: appointment?.appointmentNumber ?? '',
|
|
41
|
+
patientUuid: appointment?.patientUuid ? appointment.patientUuid : patientUuid,
|
|
42
|
+
visitDate: appointment?.dateTime ? new Date(appointment.dateTime) : new Date(),
|
|
43
|
+
timeFormat: new Date().getHours() >= 12 ? 'PM' : 'AM',
|
|
44
|
+
isFullDay: true,
|
|
45
|
+
day: appointment?.dateTime,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return patientAppointment;
|
|
49
|
+
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
|
+
import { useAppointmentDate } from '../helpers';
|
|
3
|
+
import { useAppointmentSummary } from './appointment-forms.resource';
|
|
4
|
+
interface AppointmentCount {
|
|
5
|
+
date: string;
|
|
6
|
+
count: number;
|
|
7
|
+
}
|
|
2
8
|
|
|
3
|
-
export const
|
|
4
|
-
startDate: Date,
|
|
5
|
-
appointmentCount: Array<{ date: string; count: number }>,
|
|
6
|
-
) => {
|
|
9
|
+
export const getMonthlyCalendarDistribution = (startDate: Date, appointmentCount: Array<AppointmentCount>) => {
|
|
7
10
|
const distributionHashTable = new Map<string, number>([]);
|
|
8
|
-
for (let i = 0; i <=
|
|
11
|
+
for (let i = 0; i <= 35; i++) {
|
|
9
12
|
distributionHashTable.set(dayjs(startDate).add(i, 'day').format('YYYY-MM-DD'), 0);
|
|
10
13
|
}
|
|
11
14
|
appointmentCount.map(({ date, count }) => {
|
|
@@ -16,19 +19,10 @@ export const getWeeklyCalendarDistribution = (
|
|
|
16
19
|
|
|
17
20
|
return Array.from(distributionHashTable).flatMap(([date, value]) => ({ date: date, count: value }));
|
|
18
21
|
};
|
|
19
|
-
export const getMonthlyCalendarDistribution = (
|
|
20
|
-
startDate: Date,
|
|
21
|
-
appointmentCount: Array<{ date: string; count: number }>,
|
|
22
|
-
) => {
|
|
23
|
-
const distributionHashTable = new Map<string, number>([]);
|
|
24
|
-
for (let i = 0; i <= 35; i++) {
|
|
25
|
-
distributionHashTable.set(dayjs(startDate).add(i, 'day').format('YYYY-MM-DD'), 0);
|
|
26
|
-
}
|
|
27
|
-
appointmentCount.map(({ date, count }) => {
|
|
28
|
-
if (distributionHashTable.has(date)) {
|
|
29
|
-
distributionHashTable.set(date, count);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
22
|
|
|
33
|
-
|
|
23
|
+
export const useCalendarDistribution = (servieUuid: string, distributionType: 'month' | 'week') => {
|
|
24
|
+
const appointmentStartDate = useAppointmentDate();
|
|
25
|
+
const appointmentSummary = useAppointmentSummary(new Date(appointmentStartDate), servieUuid);
|
|
26
|
+
const monthlyData = getMonthlyCalendarDistribution(new Date(appointmentStartDate), appointmentSummary) ?? [];
|
|
27
|
+
return distributionType === 'month' ? monthlyData : monthlyData.slice(0, 7);
|
|
34
28
|
};
|
|
@@ -10,7 +10,7 @@ import ScheduledAppointments from '../appointments-tabs/schedule-appointment.com
|
|
|
10
10
|
import CheckInAppointments from '../appointments-tabs/checkedinappointments.component';
|
|
11
11
|
import { useAppointmentDate } from '../helpers';
|
|
12
12
|
import dayjs from 'dayjs';
|
|
13
|
-
import
|
|
13
|
+
import UnscheduledAppointments from '../appointments-tabs/unscheduled-appointments.component';
|
|
14
14
|
import PendingAppointments from '../appointments-tabs/pending-appointments.component';
|
|
15
15
|
import { useAppointments } from '../appointments-tabs/appointments-table.resource';
|
|
16
16
|
|
|
@@ -63,9 +63,9 @@ const AppointmentList: React.FC = () => {
|
|
|
63
63
|
className={styles.tabs}>
|
|
64
64
|
<TabList style={{ paddingLeft: '1rem' }} aria-label="Appointment tabs" contained>
|
|
65
65
|
<Tab>{t('scheduled', 'Scheduled')}</Tab>
|
|
66
|
-
<Tab>{t('
|
|
66
|
+
<Tab>{t('unscheduled', 'Unscheduled')}</Tab>
|
|
67
67
|
<Tab>{t('completed', 'Completed')}</Tab>
|
|
68
|
-
<Tab disabled={!isToday}>{t('checkedIn', '
|
|
68
|
+
<Tab disabled={!isToday}>{t('checkedIn', 'Checked in')}</Tab>
|
|
69
69
|
<Tab>{t('pending', 'Pending')}</Tab>
|
|
70
70
|
<Button
|
|
71
71
|
className={styles.calendarButton}
|
|
@@ -73,8 +73,8 @@ const AppointmentList: React.FC = () => {
|
|
|
73
73
|
onClick={() => navigate({ to: `${spaBasePath}/calendar` })}
|
|
74
74
|
renderIcon={(props) => <Calendar size={16} {...props} />}
|
|
75
75
|
data-floating-menu-primary-focus
|
|
76
|
-
iconDescription={t('viewCalendar', 'View
|
|
77
|
-
{t('viewCalendar', 'View
|
|
76
|
+
iconDescription={t('viewCalendar', 'View calendar')}>
|
|
77
|
+
{t('viewCalendar', 'View calendar')}
|
|
78
78
|
</Button>
|
|
79
79
|
</TabList>
|
|
80
80
|
<TabPanels>
|
|
@@ -82,7 +82,7 @@ const AppointmentList: React.FC = () => {
|
|
|
82
82
|
<ScheduledAppointments status={AppointmentTypes.SCHEDULED} />
|
|
83
83
|
</TabPanel>
|
|
84
84
|
<TabPanel style={{ padding: 0 }}>
|
|
85
|
-
<
|
|
85
|
+
<UnscheduledAppointments />
|
|
86
86
|
</TabPanel>
|
|
87
87
|
<TabPanel style={{ padding: 0 }}>{<CompletedAppointments status={AppointmentTypes.COMPLETED} />}</TabPanel>
|
|
88
88
|
{isToday && (
|
|
@@ -22,8 +22,8 @@ describe('AppointmentList', () => {
|
|
|
22
22
|
|
|
23
23
|
const scheduledAppointmentsTab = screen.getByRole('tab', { name: /^scheduled$/i });
|
|
24
24
|
const completedAppointmentsTab = screen.getByRole('tab', { name: /completed/i });
|
|
25
|
-
const unsheduledAppointment = screen.getByRole('tab', { name: /^
|
|
26
|
-
const pendingAppointments = screen.getByRole('tab', { name: /^
|
|
25
|
+
const unsheduledAppointment = screen.getByRole('tab', { name: /^unscheduled$/i });
|
|
26
|
+
const pendingAppointments = screen.getByRole('tab', { name: /^unscheduled$/i });
|
|
27
27
|
|
|
28
28
|
expect(scheduledAppointmentsTab).toBeInTheDocument();
|
|
29
29
|
expect(completedAppointmentsTab).toBeInTheDocument();
|
|
@@ -21,12 +21,12 @@ import { ConfigurableLink, formatDatetime, usePagination } from '@openmrs/esm-fr
|
|
|
21
21
|
import { EmptyState } from '../empty-state/empty-state.component';
|
|
22
22
|
import isEmpty from 'lodash-es/isEmpty';
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const UnscheduledAppointments: React.FC = () => {
|
|
25
25
|
const { t } = useTranslation();
|
|
26
26
|
const { isLoading: isVisitLoading, visits } = useVisits();
|
|
27
27
|
const { appointments, isLoading } = useAppointments();
|
|
28
28
|
const patientUuids = appointments?.map(({ patientUuid }) => patientUuid);
|
|
29
|
-
const
|
|
29
|
+
const filteredAppointments = useMemo(
|
|
30
30
|
() => (!isVisitLoading ? visits?.filter((visit) => !patientUuids.includes(visit.patient.uuid)) : []),
|
|
31
31
|
[isVisitLoading, patientUuids, visits],
|
|
32
32
|
);
|
|
@@ -49,7 +49,7 @@ const UnScheduledAppointments: React.FC = () => {
|
|
|
49
49
|
},
|
|
50
50
|
];
|
|
51
51
|
|
|
52
|
-
const { results, currentPage, goTo } = usePagination(
|
|
52
|
+
const { results, currentPage, goTo } = usePagination(filteredAppointments, 10);
|
|
53
53
|
|
|
54
54
|
const rowData = results?.map((visit) => ({
|
|
55
55
|
id: `${visit.uuid}`,
|
|
@@ -66,25 +66,30 @@ const UnScheduledAppointments: React.FC = () => {
|
|
|
66
66
|
}));
|
|
67
67
|
|
|
68
68
|
const pageSizes = useMemo(() => {
|
|
69
|
-
const numberOfPages = Math.ceil(
|
|
69
|
+
const numberOfPages = Math.ceil(filteredAppointments.length / 10);
|
|
70
70
|
return [...Array(numberOfPages).keys()].map((x) => {
|
|
71
71
|
return (x + 1) * 10;
|
|
72
72
|
});
|
|
73
|
-
}, [
|
|
73
|
+
}, [filteredAppointments]);
|
|
74
74
|
|
|
75
75
|
if (isLoading && isVisitLoading) {
|
|
76
76
|
return <DataTableSkeleton />;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
if (isEmpty(
|
|
80
|
-
return
|
|
79
|
+
if (isEmpty(filteredAppointments)) {
|
|
80
|
+
return (
|
|
81
|
+
<EmptyState
|
|
82
|
+
headerTitle={t('unscheduledAppointments', 'Unscheduled appointments')}
|
|
83
|
+
displayText={t('unscheduledAppointments_lower', 'unscheduled appointments')}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
return (
|
|
84
89
|
<div>
|
|
85
90
|
<DataTable rows={rowData} headers={headerData} isSortable>
|
|
86
91
|
{({ rows, headers, getHeaderProps, getTableProps, onInputChange }) => (
|
|
87
|
-
<TableContainer title={`${t('
|
|
92
|
+
<TableContainer title={`${t('UnscheduledAppointments', 'Unscheduled appointments')} ${rowData.length}`}>
|
|
88
93
|
<TableToolbar>
|
|
89
94
|
<TableToolbarContent>
|
|
90
95
|
<TableToolbarSearch style={{ backgroundColor: '#f4f4f4' }} tabIndex={0} onChange={onInputChange} />
|
|
@@ -126,4 +131,4 @@ const UnScheduledAppointments: React.FC = () => {
|
|
|
126
131
|
);
|
|
127
132
|
};
|
|
128
133
|
|
|
129
|
-
export default
|
|
134
|
+
export default UnscheduledAppointments;
|
package/src/config-schema.ts
CHANGED
|
@@ -58,20 +58,10 @@ export const configSchema = {
|
|
|
58
58
|
_description: 'Configurable alternative URL for the Appointments UI. Eg, the Bahmni Appointments UI URL',
|
|
59
59
|
_default: `${spaBasePath}`,
|
|
60
60
|
},
|
|
61
|
-
|
|
61
|
+
hiddenFormFields: {
|
|
62
62
|
_type: Type.Array,
|
|
63
|
-
_description: '
|
|
64
|
-
_default: [
|
|
65
|
-
'Forgot Appoinment',
|
|
66
|
-
'Lack of Transport',
|
|
67
|
-
'Travelled',
|
|
68
|
-
'Work/Schedule/Busy',
|
|
69
|
-
'Had enough Medicine',
|
|
70
|
-
'Taking Herbal Medication',
|
|
71
|
-
'Spiritual Healed',
|
|
72
|
-
'Recieved Refill in another facility',
|
|
73
|
-
'Other',
|
|
74
|
-
],
|
|
63
|
+
_description: 'Array of form controls to be hidden on form load',
|
|
64
|
+
_default: [],
|
|
75
65
|
},
|
|
76
66
|
};
|
|
77
67
|
|
|
@@ -87,4 +77,5 @@ export interface ConfigObject {
|
|
|
87
77
|
useFullViewPrivilege: boolean;
|
|
88
78
|
fullViewPrivilege: string;
|
|
89
79
|
appointmentComments: Array<string>;
|
|
80
|
+
hiddenFormFields: Array<string>;
|
|
90
81
|
}
|
package/translations/en.json
CHANGED
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"chooseProvider": "Select Provider",
|
|
38
38
|
"chooseQueue": "Select a queue",
|
|
39
39
|
"chooseService": "Select service",
|
|
40
|
+
"comment": "Comment",
|
|
40
41
|
"community": "Community",
|
|
41
42
|
"complete": "Complete",
|
|
42
43
|
"completed": "Completed",
|
|
@@ -47,17 +48,14 @@
|
|
|
47
48
|
"date": "Date",
|
|
48
49
|
"dateAndTimeOfVisit": "Date and time of visit",
|
|
49
50
|
"dateTime": "Date & time",
|
|
50
|
-
"day": "Day",
|
|
51
51
|
"defaulters": "Defaulters",
|
|
52
52
|
"discard": "Discard",
|
|
53
|
-
"doubleBooking": "Appointment double booking",
|
|
54
|
-
"doublePatientBooking": "There exist an appointment on the specified service and appointment date",
|
|
55
53
|
"downloadAppointmentList": "Download appointment list",
|
|
56
54
|
"durationMins": "Duration min",
|
|
57
55
|
"editAppointment": "Edit Appointment",
|
|
58
56
|
"editAppointments": "Edit Appointment",
|
|
59
57
|
"emergency": "Emergency",
|
|
60
|
-
"emptyStateText": "There are no {displayText
|
|
58
|
+
"emptyStateText": "There are no {{displayText}} to display",
|
|
61
59
|
"encounters": "Encounters",
|
|
62
60
|
"encounterType": "Encounter type",
|
|
63
61
|
"endTime": "End Time",
|
|
@@ -66,7 +64,6 @@
|
|
|
66
64
|
"exitAndChangeStatus": "Change status",
|
|
67
65
|
"facility": "Facility",
|
|
68
66
|
"filter": "Filter",
|
|
69
|
-
"frequency": "Frequency",
|
|
70
67
|
"futureScheduledVisits": " {count, plural, one{{count} visit} other{{count} visits}} scheduled for dates in the future",
|
|
71
68
|
"futureScheduledVisits_plural": "",
|
|
72
69
|
"getAppointmentReminder": "Would you like to get a reminder about this appointment?",
|
|
@@ -130,8 +127,10 @@
|
|
|
130
127
|
"time": "Time",
|
|
131
128
|
"todaysAppointments": "Today's Appointments",
|
|
132
129
|
"total": "Total",
|
|
133
|
-
"
|
|
134
|
-
"
|
|
130
|
+
"typeInComments": "Type in appointment comment",
|
|
131
|
+
"unscheduled": "Unscheduled",
|
|
132
|
+
"unscheduledAppointments": "Unscheduled appointments",
|
|
133
|
+
"unscheduledAppointments_lower": "unscheduled appointments",
|
|
135
134
|
"upcomming": "Upcoming",
|
|
136
135
|
"view": "View",
|
|
137
136
|
"viewCalendar": "View Calendar",
|