@openmrs/esm-appointments-app 4.3.1-pre.1421 → 4.3.1-pre.1435
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 -6
- package/dist/437.js +1 -1
- package/dist/437.js.map +1 -1
- package/dist/574.js +1 -1
- package/dist/75.js +1 -0
- package/dist/75.js.map +1 -0
- package/dist/990.js +1 -1
- package/dist/990.js.map +1 -1
- package/dist/openmrs-esm-appointments-app.js.buildmanifest.json +29 -29
- package/package.json +2 -2
- package/src/appointments/common-components/{appointments-base-table.component.tsx → appointments-table.component.tsx} +13 -17
- package/src/appointments/common-components/appointments-table.scss +18 -0
- package/src/appointments/common-components/appointments-table.test.tsx +158 -0
- package/src/appointments/details/appointment-details.scss +1 -0
- package/src/appointments/details/appointment-details.test.tsx +57 -17
- package/src/appointments/scheduled/scheduled-appointments.component.tsx +3 -3
- package/src/appointments/unscheduled/unscheduled-appointments.component.tsx +24 -17
- package/src/appointments/unscheduled/unscheduled-appointments.test.tsx +146 -0
- package/src/appointments/utils.tsx +11 -14
- package/src/appointments-calendar/monthly/monthly-view-workload.component.tsx +2 -2
- package/src/appointments-calendar/monthly/monthly-view-workload.scss +8 -6
- package/src/home-appointments/appointments-list.scss +2 -0
- package/translations/en.json +0 -1
- package/dist/210.js +0 -1
- package/dist/210.js.map +0 -1
- package/src/appointments/common-components/appointment-base-table.test.tsx +0 -77
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import { useUnscheduledAppointments } from '../../hooks/useUnscheduledAppointments';
|
|
4
|
+
import { downloadUnscheduledAppointments } from '../../helpers/excel';
|
|
5
|
+
import { usePagination } from '@openmrs/esm-framework';
|
|
6
|
+
import UnscheduledAppointments from './unscheduled-appointments.component';
|
|
7
|
+
|
|
8
|
+
const mockUsePagination = usePagination as jest.Mock;
|
|
9
|
+
const mockGoToPage = jest.fn();
|
|
10
|
+
const mockDownloadAppointmentsAsExcel = downloadUnscheduledAppointments as jest.Mock;
|
|
11
|
+
const mockUseUnscheduledAppointments = useUnscheduledAppointments as jest.Mock;
|
|
12
|
+
|
|
13
|
+
jest.mock('../../helpers/excel');
|
|
14
|
+
jest.mock('../../hooks/useOverlay');
|
|
15
|
+
jest.mock('../../hooks/useUnscheduledAppointments');
|
|
16
|
+
|
|
17
|
+
jest.mock('@openmrs/esm-framework', () => {
|
|
18
|
+
const originalModule = jest.requireActual('@openmrs/esm-framework');
|
|
19
|
+
return {
|
|
20
|
+
...originalModule,
|
|
21
|
+
openmrsFetch: jest.fn(),
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('UnscheduledAppointments component', () => {
|
|
26
|
+
const mockUnscheduledAppointments = [
|
|
27
|
+
{
|
|
28
|
+
uuid: '1234',
|
|
29
|
+
name: 'Test Patient',
|
|
30
|
+
identifier: '1234-56-78',
|
|
31
|
+
gender: 'M',
|
|
32
|
+
phoneNumber: '123-456-7890',
|
|
33
|
+
age: 20,
|
|
34
|
+
dob: 1262304000,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
uuid: '5678',
|
|
38
|
+
name: 'Another Patient',
|
|
39
|
+
identifier: '2345-67-89',
|
|
40
|
+
gender: 'F',
|
|
41
|
+
phoneNumber: '',
|
|
42
|
+
age: 30,
|
|
43
|
+
dob: 1262304000,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
it('renders the component correctly', async () => {
|
|
48
|
+
mockUseUnscheduledAppointments.mockReturnValue({
|
|
49
|
+
isLoading: false,
|
|
50
|
+
data: mockUnscheduledAppointments,
|
|
51
|
+
error: null,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
mockUsePagination.mockReturnValue({
|
|
55
|
+
results: mockUnscheduledAppointments.slice(0, 2),
|
|
56
|
+
goTo: mockGoToPage,
|
|
57
|
+
currentPage: 1,
|
|
58
|
+
});
|
|
59
|
+
render(<UnscheduledAppointments />);
|
|
60
|
+
const header = screen.getByText('Unscheduled appointments 2');
|
|
61
|
+
expect(header).toBeInTheDocument();
|
|
62
|
+
|
|
63
|
+
const patientName = await screen.findByText('Test Patient');
|
|
64
|
+
expect(patientName).toBeInTheDocument();
|
|
65
|
+
|
|
66
|
+
const identifier = screen.getByText('1234-56-78');
|
|
67
|
+
expect(identifier).toBeInTheDocument();
|
|
68
|
+
|
|
69
|
+
const gender = screen.getByText('Male');
|
|
70
|
+
expect(gender).toBeInTheDocument();
|
|
71
|
+
|
|
72
|
+
const phoneNumber = screen.getByText('123-456-7890');
|
|
73
|
+
expect(phoneNumber).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('allows the user to search for appointments', async () => {
|
|
77
|
+
mockUseUnscheduledAppointments.mockReturnValue({
|
|
78
|
+
isLoading: false,
|
|
79
|
+
data: mockUnscheduledAppointments,
|
|
80
|
+
error: null,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
mockUsePagination.mockReturnValue({
|
|
84
|
+
results: mockUnscheduledAppointments.slice(0, 2),
|
|
85
|
+
goTo: mockGoToPage,
|
|
86
|
+
currentPage: 1,
|
|
87
|
+
});
|
|
88
|
+
render(<UnscheduledAppointments />);
|
|
89
|
+
|
|
90
|
+
const searchInput = await screen.findByRole('searchbox');
|
|
91
|
+
fireEvent.change(searchInput, { target: { value: 'Another' } });
|
|
92
|
+
|
|
93
|
+
const patientName = screen.getByText('Another Patient');
|
|
94
|
+
expect(patientName).toBeInTheDocument();
|
|
95
|
+
|
|
96
|
+
const identifier = screen.getByText('2345-67-89');
|
|
97
|
+
expect(identifier).toBeInTheDocument();
|
|
98
|
+
|
|
99
|
+
const gender = screen.getByText('Female');
|
|
100
|
+
expect(gender).toBeInTheDocument();
|
|
101
|
+
|
|
102
|
+
const phoneNumber = screen.getByText('--');
|
|
103
|
+
expect(phoneNumber).toBeInTheDocument();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('allows the user to download a list of unscheduled appointments', async () => {
|
|
107
|
+
mockUseUnscheduledAppointments.mockReturnValue({
|
|
108
|
+
isLoading: false,
|
|
109
|
+
data: mockUnscheduledAppointments,
|
|
110
|
+
error: null,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
mockUsePagination.mockReturnValue({
|
|
114
|
+
results: mockUnscheduledAppointments.slice(0, 2),
|
|
115
|
+
goTo: mockGoToPage,
|
|
116
|
+
currentPage: 1,
|
|
117
|
+
});
|
|
118
|
+
render(<UnscheduledAppointments />);
|
|
119
|
+
|
|
120
|
+
const downloadButton = await screen.findByText('Download');
|
|
121
|
+
expect(downloadButton).toBeInTheDocument();
|
|
122
|
+
|
|
123
|
+
fireEvent.click(downloadButton);
|
|
124
|
+
|
|
125
|
+
expect(mockDownloadAppointmentsAsExcel).toHaveBeenCalledWith(mockUnscheduledAppointments);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('renders a message if there are no unscheduled appointments', async () => {
|
|
129
|
+
mockUseUnscheduledAppointments.mockReturnValue({
|
|
130
|
+
isLoading: false,
|
|
131
|
+
data: [],
|
|
132
|
+
error: null,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
mockUsePagination.mockReturnValue({
|
|
136
|
+
results: mockUnscheduledAppointments.slice(0, 2),
|
|
137
|
+
goTo: mockGoToPage,
|
|
138
|
+
currentPage: 1,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
render(<UnscheduledAppointments />);
|
|
142
|
+
|
|
143
|
+
const emptyState = await screen.findByText('There are no unscheduled appointments to display');
|
|
144
|
+
expect(emptyState).toBeInTheDocument();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -19,21 +19,18 @@ export function getPageSizes<T>(data: Array<T>, pageSize: number = 10): Array<nu
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
export function useSearchResults(
|
|
30
|
-
appointments: Array<MappedAppointment>,
|
|
31
|
-
searchString: string,
|
|
32
|
-
): Array<MappedAppointment> {
|
|
22
|
+
|
|
23
|
+
Returns an array of filtered data that contains search string
|
|
24
|
+
@template T
|
|
25
|
+
@param {T[]} data - The array of data to filter
|
|
26
|
+
@param {string} searchString - The string to search for in the data
|
|
27
|
+
@returns {T[]} The filtered array of data
|
|
28
|
+
*/
|
|
29
|
+
export function useSearchResults<T>(data: T[], searchString: string): T[] {
|
|
33
30
|
const searchResults = useMemo(() => {
|
|
34
31
|
if (searchString && searchString.trim() !== '') {
|
|
35
32
|
const search = searchString.toLowerCase();
|
|
36
|
-
return
|
|
33
|
+
return data.filter((appointment) =>
|
|
37
34
|
Object.entries(appointment).some(([header, value]) => {
|
|
38
35
|
if (header === 'patientUuid') {
|
|
39
36
|
return false;
|
|
@@ -43,8 +40,8 @@ export function useSearchResults(
|
|
|
43
40
|
);
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
return
|
|
47
|
-
}, [searchString,
|
|
43
|
+
return data;
|
|
44
|
+
}, [searchString, data]);
|
|
48
45
|
|
|
49
46
|
return searchResults;
|
|
50
47
|
}
|
|
@@ -27,7 +27,7 @@ const MonthlyWorkload = ({ type, dateTime, currentDate, events }) => {
|
|
|
27
27
|
} ${layout === 'small-desktop' ? styles.smallDesktop : styles.largeDesktop}`}>
|
|
28
28
|
{type === 'monthly' && isSameMonth(dateTime, currentDate) && (
|
|
29
29
|
<p>
|
|
30
|
-
<b>{dateTime.format('D')}</b>
|
|
30
|
+
<b className={styles.calendarDate}>{dateTime.format('D')}</b>
|
|
31
31
|
{currentData?.service && (
|
|
32
32
|
<div className={styles.currentData}>
|
|
33
33
|
{currentData.service.map(({ serviceName, count }) => (
|
|
@@ -36,7 +36,7 @@ const MonthlyWorkload = ({ type, dateTime, currentDate, events }) => {
|
|
|
36
36
|
role="button"
|
|
37
37
|
tabIndex={0}
|
|
38
38
|
onClick={() => serviceAreaOnClick(serviceName)}
|
|
39
|
-
className={`${styles.serviceArea}
|
|
39
|
+
className={`${styles.serviceArea}`}>
|
|
40
40
|
<span>{serviceName}</span>
|
|
41
41
|
<span>{count}</span>
|
|
42
42
|
</div>
|
|
@@ -77,24 +77,22 @@
|
|
|
77
77
|
|
|
78
78
|
.currentData {
|
|
79
79
|
margin: 2px;
|
|
80
|
+
padding-top: 2px;
|
|
81
|
+
background-color: colors.$gray-10;
|
|
80
82
|
|
|
81
83
|
& > span {
|
|
82
84
|
@include type.type-style('label-02');
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
.greyBackground {
|
|
87
|
-
background-color: colors.$gray-10;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
88
|
.serviceArea {
|
|
91
89
|
padding: 0.0125rem;
|
|
92
90
|
display: grid;
|
|
93
91
|
grid-template-columns: 4fr 1fr;
|
|
94
92
|
justify-content: flex-start;
|
|
95
93
|
text-align: left;
|
|
96
|
-
margin: 0.
|
|
97
|
-
@include type.type-style('label-
|
|
94
|
+
margin: 0.125rem;
|
|
95
|
+
@include type.type-style('label-01');
|
|
98
96
|
color: #020f1b;
|
|
99
97
|
cursor: pointer;
|
|
100
98
|
|
|
@@ -144,3 +142,7 @@
|
|
|
144
142
|
color: colors.$white;
|
|
145
143
|
font-weight: bold;
|
|
146
144
|
}
|
|
145
|
+
|
|
146
|
+
.calendarDate {
|
|
147
|
+
@include type.type-style('heading-compact-01');
|
|
148
|
+
}
|
package/translations/en.json
CHANGED
|
@@ -76,7 +76,6 @@
|
|
|
76
76
|
"monthly": "Monthly",
|
|
77
77
|
"name": "Name",
|
|
78
78
|
"next": "Next",
|
|
79
|
-
"nextAppointmentDate": "Next appointment date",
|
|
80
79
|
"noAppointmentsScheduledForTodayToDisplay": "There are no appointments scheduled for today to display for this location",
|
|
81
80
|
"noAppointmentsToDisplay": "There are no appointments to display for this location",
|
|
82
81
|
"noEncountersFound": "No encounters found",
|