@kenyaemr/esm-appointments-app 7.0.2-pre.65

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.
Files changed (181) hide show
  1. package/.turbo/turbo-build.log +42 -0
  2. package/dist/130.js +2 -0
  3. package/dist/130.js.LICENSE.txt +3 -0
  4. package/dist/130.js.map +1 -0
  5. package/dist/152.js +1 -0
  6. package/dist/152.js.map +1 -0
  7. package/dist/224.js +1 -0
  8. package/dist/224.js.map +1 -0
  9. package/dist/255.js +2 -0
  10. package/dist/255.js.LICENSE.txt +9 -0
  11. package/dist/255.js.map +1 -0
  12. package/dist/271.js +1 -0
  13. package/dist/303.js +1 -0
  14. package/dist/303.js.map +1 -0
  15. package/dist/309.js +1 -0
  16. package/dist/309.js.map +1 -0
  17. package/dist/319.js +1 -0
  18. package/dist/4.js +1 -0
  19. package/dist/4.js.map +1 -0
  20. package/dist/445.js +2 -0
  21. package/dist/445.js.LICENSE.txt +54 -0
  22. package/dist/445.js.map +1 -0
  23. package/dist/460.js +1 -0
  24. package/dist/501.js +1 -0
  25. package/dist/501.js.map +1 -0
  26. package/dist/574.js +1 -0
  27. package/dist/591.js +2 -0
  28. package/dist/591.js.LICENSE.txt +32 -0
  29. package/dist/591.js.map +1 -0
  30. package/dist/644.js +1 -0
  31. package/dist/729.js +1 -0
  32. package/dist/729.js.map +1 -0
  33. package/dist/757.js +1 -0
  34. package/dist/784.js +2 -0
  35. package/dist/784.js.LICENSE.txt +9 -0
  36. package/dist/784.js.map +1 -0
  37. package/dist/788.js +1 -0
  38. package/dist/807.js +1 -0
  39. package/dist/833.js +1 -0
  40. package/dist/857.js +2 -0
  41. package/dist/857.js.LICENSE.txt +5 -0
  42. package/dist/857.js.map +1 -0
  43. package/dist/904.js +1 -0
  44. package/dist/904.js.map +1 -0
  45. package/dist/kenyaemr-esm-appointments-app.js +1 -0
  46. package/dist/kenyaemr-esm-appointments-app.js.buildmanifest.json +699 -0
  47. package/dist/kenyaemr-esm-appointments-app.js.map +1 -0
  48. package/dist/main.js +2 -0
  49. package/dist/main.js.LICENSE.txt +64 -0
  50. package/dist/main.js.map +1 -0
  51. package/dist/routes.json +1 -0
  52. package/jest.config.js +3 -0
  53. package/package.json +57 -0
  54. package/src/admin/appointment-services/appointment-services-hook.ts +31 -0
  55. package/src/admin/appointment-services/appointment-services-validation.ts +17 -0
  56. package/src/admin/appointment-services/appointment-services.component.tsx +182 -0
  57. package/src/admin/appointment-services/appointment-services.scss +25 -0
  58. package/src/appointments/appointment-tabs.component.tsx +48 -0
  59. package/src/appointments/appointment-tabs.scss +53 -0
  60. package/src/appointments/appointment-tabs.test.tsx +55 -0
  61. package/src/appointments/common-components/appointments-actions.component.tsx +86 -0
  62. package/src/appointments/common-components/appointments-actions.scss +4 -0
  63. package/src/appointments/common-components/appointments-actions.test.tsx +201 -0
  64. package/src/appointments/common-components/appointments-table.component.tsx +277 -0
  65. package/src/appointments/common-components/appointments-table.scss +133 -0
  66. package/src/appointments/common-components/appointments-table.test.tsx +134 -0
  67. package/src/appointments/common-components/checkin-button.component.tsx +43 -0
  68. package/src/appointments/common-components/end-appointment-modal.component.tsx +104 -0
  69. package/src/appointments/common-components/end-appointment-modal.test.tsx +80 -0
  70. package/src/appointments/common-components/location-select-option.component.tsx +48 -0
  71. package/src/appointments/details/appointment-details.component.tsx +91 -0
  72. package/src/appointments/details/appointment-details.scss +81 -0
  73. package/src/appointments/details/appointment-details.test.tsx +103 -0
  74. package/src/appointments/scheduled/appointments-list.component.tsx +33 -0
  75. package/src/appointments/scheduled/early-appointments.component.tsx +32 -0
  76. package/src/appointments/scheduled/scheduled-appointments.component.tsx +215 -0
  77. package/src/appointments/scheduled/scheduled-appointments.scss +4 -0
  78. package/src/appointments/unscheduled/unscheduled-appointments.component.tsx +146 -0
  79. package/src/appointments/unscheduled/unscheduled-appointments.test.tsx +131 -0
  80. package/src/appointments/utils.tsx +80 -0
  81. package/src/appointments.component.tsx +44 -0
  82. package/src/appointments.test.tsx +15 -0
  83. package/src/calendar/appointments-calendar-view-view.scss +24 -0
  84. package/src/calendar/appointments-calendar-view.component.tsx +36 -0
  85. package/src/calendar/appointments-calendar-view.test.tsx +22 -0
  86. package/src/calendar/header/calendar-header.component.tsx +34 -0
  87. package/src/calendar/header/calendar-header.scss +32 -0
  88. package/src/calendar/monthly/days-of-week.component.tsx +16 -0
  89. package/src/calendar/monthly/days-of-week.scss +33 -0
  90. package/src/calendar/monthly/monthly-calendar-view.component.tsx +34 -0
  91. package/src/calendar/monthly/monthly-header.module.scss +14 -0
  92. package/src/calendar/monthly/monthly-header.module.tsx +40 -0
  93. package/src/calendar/monthly/monthly-view-workload.scss +188 -0
  94. package/src/calendar/monthly/monthly-workload-view-expanded.component.tsx +42 -0
  95. package/src/calendar/monthly/monthly-workload-view.component.tsx +109 -0
  96. package/src/config-schema.ts +151 -0
  97. package/src/constants.ts +55 -0
  98. package/src/createDashboardLink.component.tsx +39 -0
  99. package/src/dashboard.meta.ts +21 -0
  100. package/src/declarations.d.ts +4 -0
  101. package/src/empty-state/empty-data-illustration.component.tsx +39 -0
  102. package/src/empty-state/empty-state.component.tsx +32 -0
  103. package/src/empty-state/empty-state.scss +69 -0
  104. package/src/form/appointments-form.component.tsx +891 -0
  105. package/src/form/appointments-form.resource.ts +165 -0
  106. package/src/form/appointments-form.scss +113 -0
  107. package/src/form/appointments-form.test.tsx +212 -0
  108. package/src/header/appointments-header.component.tsx +79 -0
  109. package/src/header/appointments-header.scss +95 -0
  110. package/src/header/appointments-illustration.component.tsx +22 -0
  111. package/src/helpers/excel.ts +61 -0
  112. package/src/helpers/functions.ts +82 -0
  113. package/src/helpers/index.ts +2 -0
  114. package/src/helpers/time.tsx +15 -0
  115. package/src/home/home-appointments.component.tsx +22 -0
  116. package/src/home/home-appointments.scss +10 -0
  117. package/src/hooks/patientAppointmentContext.ts +15 -0
  118. package/src/hooks/selectedDateContext.ts +10 -0
  119. package/src/hooks/useAppointmentList.ts +48 -0
  120. package/src/hooks/useAppointmentService.ts +11 -0
  121. package/src/hooks/useAppointmentsCalendar.ts +68 -0
  122. package/src/hooks/useClinicalMetrics.ts +79 -0
  123. package/src/hooks/useDefaultLocation.ts +14 -0
  124. package/src/hooks/useOverlay.tsx +45 -0
  125. package/src/hooks/usePatientAppointmentHistory.ts +49 -0
  126. package/src/hooks/useProviders.ts +18 -0
  127. package/src/hooks/useTodaysVisits.ts +19 -0
  128. package/src/hooks/useUnscheduledAppointments.ts +45 -0
  129. package/src/index.ts +111 -0
  130. package/src/metrics/appointments-metrics.component.tsx +71 -0
  131. package/src/metrics/appointments-metrics.scss +15 -0
  132. package/src/metrics/appointments-metrics.test.tsx +49 -0
  133. package/src/metrics/metrics-card.component.tsx +76 -0
  134. package/src/metrics/metrics-card.scss +77 -0
  135. package/src/metrics/metrics-header.component.tsx +62 -0
  136. package/src/metrics/metrics-header.scss +33 -0
  137. package/src/past-visit/encounter-list.component.tsx +54 -0
  138. package/src/past-visit/past-visit.component.tsx +106 -0
  139. package/src/past-visit/past-visit.resource.ts +25 -0
  140. package/src/past-visit/past-visit.scss +106 -0
  141. package/src/patient-appointments/patient-appointments-action-menu.component.tsx +65 -0
  142. package/src/patient-appointments/patient-appointments-action-menu.scss +7 -0
  143. package/src/patient-appointments/patient-appointments-base.component.tsx +165 -0
  144. package/src/patient-appointments/patient-appointments-base.scss +85 -0
  145. package/src/patient-appointments/patient-appointments-base.test.tsx +91 -0
  146. package/src/patient-appointments/patient-appointments-cancel-modal.component.tsx +66 -0
  147. package/src/patient-appointments/patient-appointments-detailed-summary.component.tsx +15 -0
  148. package/src/patient-appointments/patient-appointments-header.scss +27 -0
  149. package/src/patient-appointments/patient-appointments-header.tsx +42 -0
  150. package/src/patient-appointments/patient-appointments-overview.component.tsx +35 -0
  151. package/src/patient-appointments/patient-appointments-overview.scss +7 -0
  152. package/src/patient-appointments/patient-appointments-table.scss +0 -0
  153. package/src/patient-appointments/patient-appointments-table.tsx +128 -0
  154. package/src/patient-appointments/patient-appointments.resource.ts +72 -0
  155. package/src/patient-appointments/patient-upcoming-appointments-card.component.tsx +122 -0
  156. package/src/patient-appointments/patient-upcoming-appointments-card.scss +46 -0
  157. package/src/patient-search/patient-search.component.tsx +34 -0
  158. package/src/patient-search/patient-search.scss +23 -0
  159. package/src/root.component.tsx +26 -0
  160. package/src/root.scss +50 -0
  161. package/src/routes.json +153 -0
  162. package/src/scheduled-appointments-config-schema.ts +169 -0
  163. package/src/types/index.ts +189 -0
  164. package/src/workload/monthly-view-workload/monthly-view.component.tsx +69 -0
  165. package/src/workload/monthly-view-workload/monthly-workload.scss +223 -0
  166. package/src/workload/monthly-view-workload/monthlyWorkCard.tsx +45 -0
  167. package/src/workload/workload-card.component.tsx +31 -0
  168. package/src/workload/workload.component.tsx +47 -0
  169. package/src/workload/workload.resource.ts +78 -0
  170. package/src/workload/workload.scss +92 -0
  171. package/translations/am.json +148 -0
  172. package/translations/ar.json +148 -0
  173. package/translations/en.json +159 -0
  174. package/translations/es.json +148 -0
  175. package/translations/fr.json +148 -0
  176. package/translations/he.json +148 -0
  177. package/translations/km.json +148 -0
  178. package/translations/zh.json +148 -0
  179. package/translations/zh_CN.json +148 -0
  180. package/tsconfig.json +5 -0
  181. package/webpack.config.js +1 -0
@@ -0,0 +1,223 @@
1
+ @use '@carbon/styles/scss/type';
2
+ @use '@carbon/colors';
3
+ @use '@carbon/layout';
4
+ @import '~@openmrs/esm-styleguide/src/vars';
5
+ .monthly-cell {
6
+ border-left: 1px solid colors.$gray-20;
7
+ border-bottom: 1px solid colors.$gray-20;
8
+ border-right: 1px solid colors.$gray-20;
9
+ background: colors.$white;
10
+ color: colors.$black;
11
+ cursor: pointer;
12
+ text-align: right;
13
+ @include type.type-style('body-compact-02');
14
+ &:nth-child(-n + 7) {
15
+ border-top: 1px solid colors.$gray-20;
16
+ }
17
+
18
+ &:nth-child(7n) {
19
+ border-right: 1px solid colors.$gray-20;
20
+ }
21
+
22
+ &-today {
23
+ background-color: colors.$blue-70;
24
+ color: colors.$white;
25
+ }
26
+
27
+ &-selected {
28
+ background-color: colors.$gray-10;
29
+ color: colors.$white;
30
+ }
31
+
32
+ &-current {
33
+ color: colors.$black;
34
+ }
35
+ &:hover {
36
+ background-color: colors.$blue-30-hover;
37
+ color: colors.$white;
38
+ }
39
+ &-active {
40
+ background-color: colors.$magenta-30;
41
+ color: colors.$white;
42
+ }
43
+ }
44
+
45
+ .monthly-cell-disabled {
46
+ background: colors.$white;
47
+ color: colors.$gray-20;
48
+ }
49
+
50
+ .monthly-cell-disabled:last-child {
51
+ display: none;
52
+ }
53
+
54
+ .identifiers {
55
+ @include type.type-style('body-compact-02');
56
+ color: $ui-04;
57
+ display: list-item;
58
+
59
+ span:not(:first-child) {
60
+ margin: 0rem 0.75rem;
61
+ }
62
+ }
63
+ .identifierTag {
64
+ display: flex;
65
+ align-items: center;
66
+ }
67
+ .weekly-cell {
68
+ position: relative;
69
+ border-right: 1px solid colors.$gray-20;
70
+ border-bottom: 1px solid colors.$gray-20;
71
+ min-height: 120px;
72
+ color: colors.$white;
73
+
74
+ .week-time {
75
+ display: none;
76
+ }
77
+
78
+ &:nth-child(-n + 8) {
79
+ border-top: 1px solid colors.$gray-20;
80
+ }
81
+
82
+ &:first-child {
83
+ border-top: none;
84
+ }
85
+
86
+ &:nth-child(8n + 1) {
87
+ border-bottom: none;
88
+
89
+ .week-time {
90
+ white-space: nowrap;
91
+ display: inline;
92
+ color: colors.$white;
93
+ position: absolute;
94
+ top: -11px;
95
+ height: layout.$spacing-06;
96
+ width: layout.$spacing-07;
97
+ }
98
+ }
99
+ }
100
+ .selectedDate {
101
+ background-color: #005d5d;
102
+ height: 100%;
103
+ width: 100%;
104
+ }
105
+
106
+ .currentData {
107
+ margin: 2px;
108
+ padding-top: 2px;
109
+ }
110
+
111
+ .serviceArea {
112
+ padding: 0.0125rem;
113
+ display: grid;
114
+ grid-template-columns: 4fr 1fr;
115
+ justify-content: flex-start;
116
+ text-align: left;
117
+ margin: 0.125rem;
118
+ @include type.type-style('label-01');
119
+ color: #020f1b;
120
+ cursor: pointer;
121
+
122
+ & > span:first-child {
123
+ text-align: left;
124
+ text-overflow: ellipsis;
125
+ }
126
+
127
+ & > span:nth-child(2) {
128
+ text-align: right;
129
+ }
130
+ }
131
+
132
+ .smallDesktop {
133
+ height: auto;
134
+ }
135
+
136
+ .largeDesktop {
137
+ height: auto;
138
+ }
139
+
140
+ .red {
141
+ background-color: colors.$red-70;
142
+ color: colors.$white;
143
+ font-weight: bold;
144
+ }
145
+
146
+ .purple {
147
+ background-color: colors.$yellow-70;
148
+ color: colors.$white;
149
+ font-weight: bold;
150
+ }
151
+
152
+ .blue {
153
+ color: colors.$blue-70;
154
+ font-weight: bold;
155
+ }
156
+ .black {
157
+ color: colors.$black;
158
+ font-weight: bold;
159
+ }
160
+
161
+ .green {
162
+ background-color: colors.$green-70;
163
+ color: colors.$white;
164
+ font-weight: bold;
165
+ }
166
+
167
+ .calendarDate {
168
+ @include type.type-style('heading-compact-01');
169
+ }
170
+
171
+ .wrapper {
172
+ position: relative;
173
+ }
174
+ .monthlyCalendar {
175
+ display: grid;
176
+ grid-template-columns: repeat(7, minmax(0px, 1fr));
177
+ grid-template-rows: repeat(6, minmax(0px, 1fr));
178
+ }
179
+ .selectedDate {
180
+ background-color: red;
181
+ }
182
+
183
+ .calendarViewContainer {
184
+ margin: 5px;
185
+ }
186
+ .backgroundColor {
187
+ margin: 1px 0 0;
188
+ transition: width 0.24s ease-in-out;
189
+ position: relative;
190
+ min-height: calc(100vh - 80px);
191
+ background-color: colors.$white;
192
+ }
193
+ .container {
194
+ display: flex;
195
+ justify-content: center;
196
+ align-items: center;
197
+ width: 100%;
198
+ height: layout.$spacing-06;
199
+ }
200
+ .workLoadCard {
201
+ display: flex;
202
+ color: colors.$black;
203
+ }
204
+ .activeWorkloadCard {
205
+ background-color: colors.$blue-10;
206
+
207
+ & label {
208
+ color: colors.$blue-60;
209
+ }
210
+ }
211
+ .workLoadContainer {
212
+ display: flex;
213
+ flex-direction: column;
214
+ background-color: white;
215
+ padding-bottom: 1rem;
216
+ }
217
+ .headerContainer {
218
+ display: flex;
219
+ justify-content: center;
220
+ align-items: center;
221
+ width: 100%;
222
+ height: layout.$spacing-06;
223
+ }
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import classNames from 'classnames';
3
+ import styles from './monthly-workload.scss';
4
+ import { useLayoutType } from '@openmrs/esm-framework';
5
+ import { isSameMonth } from '../../helpers';
6
+ import dayjs, { type Dayjs } from 'dayjs';
7
+
8
+ interface MonthlyWorkloadComponentProps {
9
+ date: Dayjs;
10
+ count: number;
11
+ isActive: boolean;
12
+ selectedDate?: Dayjs;
13
+ }
14
+
15
+ const MonthlyWorkloadCard: React.FC<MonthlyWorkloadComponentProps> = ({ date, count, isActive, selectedDate }) => {
16
+ const layout = useLayoutType();
17
+ const isToday = date.isSame(dayjs(), 'day');
18
+ return (
19
+ <div
20
+ className={classNames(
21
+ styles['monthly-cell'],
22
+ {
23
+ [styles['monthly-cell-selected']]: isSameMonth(date, dayjs(selectedDate)),
24
+ [styles['monthly-cell-current']]: isSameMonth(date, dayjs(selectedDate)),
25
+ [styles['monthly-cell-current']]: isSameMonth(date, selectedDate),
26
+ [styles['monthly-cell-active']]: isActive,
27
+ },
28
+ {
29
+ [styles.smallDesktop]: layout === 'small-desktop',
30
+ [styles.largeDesktop]: layout !== 'small-desktop',
31
+ },
32
+ )}>
33
+ <p>
34
+ <b className={[styles.calendarDate, isToday ? styles.blue : ''].join(' ')}>{date.format('D')}</b>
35
+ <div className={styles.currentData}>
36
+ <div tabIndex={0} role="button" className={classNames(styles.tileContainer, {})}></div>
37
+ <div className={styles.serviceArea}>
38
+ <span className={isActive ? styles.blue : ''}>{count}</span>
39
+ </div>
40
+ </div>
41
+ </p>
42
+ </div>
43
+ );
44
+ };
45
+ export default MonthlyWorkloadCard;
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import classNames from 'classnames';
3
+ import styles from './workload.scss';
4
+
5
+ interface WorkloadCardProp {
6
+ day: string;
7
+ date: string;
8
+ count: number;
9
+ isActive: boolean;
10
+ }
11
+ const WorkloadCard: React.FC<WorkloadCardProp> = ({ day, date, count, isActive }) => {
12
+ return (
13
+ <div
14
+ tabIndex={0}
15
+ role="button"
16
+ className={classNames(styles.tileContainer, {
17
+ [styles.activeWorkloadCard]: isActive,
18
+ })}>
19
+ <div>
20
+ <label className={styles.dayLabel}>{day}</label>
21
+ </div>
22
+ <div>
23
+ <label className={styles.headerLabel}>{date}</label>
24
+ </div>
25
+ <div>
26
+ <label className={styles.totalsLabel}>{count}</label>
27
+ </div>
28
+ </div>
29
+ );
30
+ };
31
+ export default WorkloadCard;
@@ -0,0 +1,47 @@
1
+ import React, { useState } from 'react';
2
+ import { Tabs, Tab, TabPanel, TabPanels, TabList } from '@carbon/react';
3
+ import WorkloadCard from './workload-card.component';
4
+ import dayjs from 'dayjs';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { useCalendarDistribution, useMonthlyCalendarDistribution } from './workload.resource';
7
+ import styles from './workload.scss';
8
+ import { useAppointmentService } from '../form/appointments-form.resource';
9
+ import MonthlyCalendarView from './monthly-view-workload/monthly-view.component';
10
+
11
+ interface WorkloadProps {
12
+ selectedService: string;
13
+ appointmentDate: Date;
14
+ onWorkloadDateChange: (pickedDate: Date) => void;
15
+ }
16
+
17
+ const Workload: React.FC<WorkloadProps> = ({ selectedService, appointmentDate, onWorkloadDateChange }) => {
18
+ const { t } = useTranslation();
19
+ const [selectedTab, setSelectedTab] = useState(0);
20
+ const { data: services } = useAppointmentService();
21
+ const serviceUuid = services?.find((service) => service.name === selectedService)?.uuid;
22
+ const calendarWorkload = useCalendarDistribution(serviceUuid, selectedTab === 0 ? 'week' : 'month', appointmentDate);
23
+ const monthlyCalendarWorkload = useMonthlyCalendarDistribution(
24
+ serviceUuid,
25
+ selectedTab === 0 ? 'week' : 'month',
26
+ appointmentDate,
27
+ );
28
+ const handleDateClick = (pickedDate: Date) => {
29
+ onWorkloadDateChange(pickedDate);
30
+ };
31
+
32
+ return (
33
+ <div className={styles.workLoadContainer}>
34
+ <div>
35
+ <div>
36
+ <MonthlyCalendarView
37
+ calendarWorkload={monthlyCalendarWorkload}
38
+ dateToDisplay={appointmentDate.toISOString()}
39
+ onDateClick={handleDateClick}
40
+ />
41
+ </div>
42
+ </div>
43
+ </div>
44
+ );
45
+ };
46
+
47
+ export default Workload;
@@ -0,0 +1,78 @@
1
+ import useSWR from 'swr';
2
+ import dayjs from 'dayjs';
3
+ import first from 'lodash-es/first';
4
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
5
+ import { type AppointmentSummary } from '../types';
6
+ import { omrsDateFormat } from '../constants';
7
+ interface AppointmentCount {
8
+ date: string;
9
+ count: number;
10
+ }
11
+
12
+ export const getMonthlyCalendarDistribution = (startDate: Date, appointmentCount: Array<AppointmentCount>) => {
13
+ const distributionHashTable = new Map<string, number>([]);
14
+ for (let i = 0; i <= 35; i++) {
15
+ distributionHashTable.set(dayjs(startDate).add(i, 'day').format('YYYY-MM-DD'), 0);
16
+ }
17
+ appointmentCount.map(({ date, count }) => {
18
+ if (distributionHashTable.has(date)) {
19
+ distributionHashTable.set(date, count);
20
+ }
21
+ });
22
+
23
+ return Array.from(distributionHashTable).flatMap(([date, value]) => ({ date: date, count: value }));
24
+ };
25
+
26
+ export const useCalendarDistribution = (
27
+ serviceUuid: string,
28
+ distributionType: 'month' | 'week',
29
+ appointmentDate: Date,
30
+ ) => {
31
+ const appointmentSummary = useAppointmentSummary(new Date(appointmentDate), serviceUuid);
32
+ const monthlyData = getMonthlyCalendarDistribution(new Date(appointmentDate), appointmentSummary) ?? [];
33
+ return distributionType === 'month' ? monthlyData : monthlyData.slice(0, 6);
34
+ };
35
+
36
+ export const useAppointmentSummary = (fromDate: Date, serviceUuid: string): Array<{ date: string; count: number }> => {
37
+ const startDate = dayjs(fromDate).startOf('week').format(omrsDateFormat);
38
+ const endDate = dayjs(startDate).add(2, 'week').format(omrsDateFormat);
39
+ const url = `${restBaseUrl}/appointment/appointmentSummary?startDate=${startDate}&endDate=${endDate}`;
40
+ const { data } = useSWR<{ data: Array<AppointmentSummary> }>(url, openmrsFetch);
41
+ const results = first(data?.data?.filter(({ appointmentService }) => appointmentService.uuid === serviceUuid));
42
+ const appointmentCountMap = results?.appointmentCountMap;
43
+ return Object.entries(appointmentCountMap ?? [])
44
+ .map(([key, value]) => ({
45
+ date: key,
46
+ count: value.allAppointmentsCount,
47
+ }))
48
+ .sort((dateA, dateB) => new Date(dateA.date).getTime() - new Date(dateB.date).getTime());
49
+ };
50
+ export const useMonthlyCalendarDistribution = (
51
+ serviceUuid: string,
52
+ distributionType: 'month' | 'week',
53
+ appointmentDate: Date,
54
+ ) => {
55
+ const appointmentSummary = useMonthlyAppointmentSummary(appointmentDate, serviceUuid);
56
+
57
+ return distributionType === 'month' ? appointmentSummary : appointmentSummary.slice(0, 6);
58
+ };
59
+
60
+ export const useMonthlyAppointmentSummary = (
61
+ fromDate: Date,
62
+ serviceUuid: string,
63
+ ): Array<{ date: string; count: number }> => {
64
+ const startDate = dayjs(fromDate).startOf('month').format(omrsDateFormat);
65
+ const endDate = dayjs(fromDate).endOf('month').format(omrsDateFormat);
66
+ const url = `${restBaseUrl}/appointment/appointmentSummary?startDate=${startDate}&endDate=${endDate}`;
67
+ const { data } = useSWR<{ data: Array<AppointmentSummary> }>(url, openmrsFetch);
68
+
69
+ const results = first(data?.data?.filter(({ appointmentService }) => appointmentService.uuid === serviceUuid));
70
+ const appointmentCountMap = results?.appointmentCountMap;
71
+
72
+ return Object.entries(appointmentCountMap ?? [])
73
+ .map(([key, value]) => ({
74
+ date: key,
75
+ count: value.allAppointmentsCount,
76
+ }))
77
+ .sort((dateA, dateB) => new Date(dateA.date).getTime() - new Date(dateB.date).getTime());
78
+ };
@@ -0,0 +1,92 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
+ @import '~@openmrs/esm-styleguide/src/vars';
5
+
6
+ .workLoadCard {
7
+ display: flex;
8
+ color: colors.$black;
9
+ }
10
+
11
+ .monthlyWorkLoadCard {
12
+ color: #525252;
13
+ display: flex;
14
+ flex-wrap: wrap;
15
+ }
16
+
17
+ .workLoadContainer {
18
+ display: flex;
19
+ flex-direction: column;
20
+ background-color: white;
21
+ padding-bottom: 1rem;
22
+ }
23
+
24
+ .cardContainer {
25
+ background-color: $ui-02;
26
+ display: flex;
27
+ height: layout.$spacing-12;
28
+ }
29
+
30
+ .tileContainer {
31
+ padding: 0.5rem;
32
+ flex: 1;
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ flex-direction: column;
37
+ cursor: pointer;
38
+ border: 1px solid colors.$blue-30;
39
+
40
+ &:first-child {
41
+ border-left-width: 1px;
42
+ }
43
+
44
+ & label {
45
+ color: colors.$gray-70;
46
+ }
47
+ }
48
+
49
+ .tileHeader {
50
+ display: flex;
51
+ justify-content: space-between;
52
+ padding-bottom: layout.$spacing-05;
53
+ }
54
+ .dayLabel {
55
+ @include type.type-style('heading-compact-01');
56
+ color: colors.$blue-30;
57
+ text-decoration: underline;
58
+ border-bottom: 5px;
59
+ }
60
+
61
+ .headerLabel {
62
+ @include type.type-style('heading-compact-01');
63
+ color: $text-02;
64
+ }
65
+
66
+ .totalsLabel {
67
+ @include type.type-style('label-01');
68
+ color: $text-02;
69
+ }
70
+
71
+ .totalsValue {
72
+ @include type.type-style('heading-04');
73
+ color: $ui-05;
74
+ }
75
+
76
+ .headerLabelContainer {
77
+ display: flex;
78
+ align-items: center;
79
+ height: layout.$spacing-07;
80
+ }
81
+
82
+ .link {
83
+ text-decoration: none;
84
+ }
85
+
86
+ .activeWorkloadCard {
87
+ background-color: colors.$blue-10;
88
+
89
+ & label {
90
+ color: colors.$blue-60;
91
+ }
92
+ }
@@ -0,0 +1,148 @@
1
+ {
2
+ "action": "Action",
3
+ "actions": "Actions",
4
+ "add": "Add",
5
+ "addAppointment": "Add Appointment",
6
+ "addPatientToQueue": "Add patient to queue",
7
+ "age": "Age",
8
+ "all": "All",
9
+ "allDay": "All day",
10
+ "appointmentCancelError": "Error cancelling appointment",
11
+ "appointmentCancelled": "Appointment cancelled",
12
+ "appointmentCancelledSuccessfully": "Appointment cancelled successfully",
13
+ "appointmentColor": "Appointment color",
14
+ "appointmentEdited": "Appointment edited",
15
+ "appointmentEditError": "Error editing appointment",
16
+ "appointmentForm": "Create Appointment",
17
+ "appointmentFormError": "Error scheduling appointment",
18
+ "appointmentHistory": "Appointment History",
19
+ "appointmentMetrics": "Appointment metrics",
20
+ "appointmentMetricsLoadError": "",
21
+ "appointmentNoteLabel": "Write an additional note",
22
+ "appointmentNotePlaceholder": "Write any additional points here",
23
+ "appointmentNotes": "Appointment Notes",
24
+ "appointmentNowVisible": "It is now visible on the Appointments page",
25
+ "appointments": "appointment",
26
+ "appointmentsCalendar": "Appointments Calendar",
27
+ "appointmentScheduled": "Appointment scheduled",
28
+ "appointmentService": "Appointment service",
29
+ "appointmentServiceCreate": "Appointment service created successfully",
30
+ "appointmentServiceName": "Appointment service name",
31
+ "appointmentStatus": "Appointment status",
32
+ "appointmentToFulfill": "Select appointment(s) to fulfill",
33
+ "appointmentType": "Appointment type",
34
+ "appointmentType_title": "Appointment Type",
35
+ "back": "Back",
36
+ "calendar": "Calendar",
37
+ "cameEarly": "Came early",
38
+ "cancel": "Cancel",
39
+ "cancelAppointment": "Cancel Appointment",
40
+ "cancelAppointmentModalConfirmationText": "Are you sure you want to cancel this appointment?",
41
+ "cancelled": "Cancelled",
42
+ "checkedIn": "Checked in",
43
+ "checkedOut": "Checked out",
44
+ "checkIn": "Check In",
45
+ "checkOut": "Check out",
46
+ "chooseAppointmentType": "Choose appointment type",
47
+ "chooseLocation": "Choose a location",
48
+ "chooseProvider": "Choose a provider",
49
+ "chooseService": "Select service",
50
+ "completed": "Completed",
51
+ "createAppointmentService": "Create appointment service",
52
+ "createNewAppointment": "Create new appointment",
53
+ "date": "Date",
54
+ "date&Time": "Date & time",
55
+ "dateAndTimeOfVisit": "Date and time of visit",
56
+ "dateOfBirth": "Date of birth",
57
+ "dateTime": "Date & Time",
58
+ "day": "Day",
59
+ "daysOfWeek": "Days of the week",
60
+ "discard": "Discard",
61
+ "download": "Download",
62
+ "durationInMinutes": "Duration (minutes)",
63
+ "durationMins": "Duration min",
64
+ "edit": "Edit",
65
+ "editAppointment": "Edit Appointment",
66
+ "editAppointments": "Edit Appointment",
67
+ "emptyStateText": "There are no {{displayText}} to display",
68
+ "encounters": "Encounters",
69
+ "encounterType": "Encounter type",
70
+ "endDate": "End date",
71
+ "endTime": "End Time",
72
+ "errorCreatingAppointmentService": "Error creating appointment service",
73
+ "expected": "Expected",
74
+ "gender": "Gender",
75
+ "highestServiceVolume": "Highest volume service: {{time}}",
76
+ "home": "Home",
77
+ "identifier": "Identifier",
78
+ "invalidNumber": "Number is not valid",
79
+ "invalidTime": "Invalid time",
80
+ "isRecurringAppointment": "Is this a recurring appointment?",
81
+ "loading": "Loading",
82
+ "location": "Location",
83
+ "medications": "Medications",
84
+ "missed": "Missed",
85
+ "missingVisitType": "Missing visit type",
86
+ "no": "No",
87
+ "noContent": "No Content",
88
+ "noCurrentAppointments": "There are no appointments scheduled for today to display for this patient",
89
+ "noEncountersFound": "No encounters found",
90
+ "noMatchingVisitTypeFound": "",
91
+ "noPastAppointments": "There are no past appointments to display for this patient",
92
+ "noPreviousVisitFound": "No previous visit found",
93
+ "notArrived": "Not arrived",
94
+ "note": "Note",
95
+ "notes": "Notes",
96
+ "noUpcomingAppointments": "No upcoming appointments found",
97
+ "noUpcomingAppointmentsForPatient": "There are no upcoming appointments to display for this patient",
98
+ "past": "Past",
99
+ "patientDetails": "Patient details",
100
+ "patientName": "Patient name",
101
+ "patients": "Patients",
102
+ "patientSearch": "Patient search",
103
+ "period": "Period",
104
+ "provider": "Provider",
105
+ "providers": "Providers",
106
+ "providersBooked": "Providers booked: {{time}}",
107
+ "queueAddedSuccessfully": "",
108
+ "queueEntryError": "Error adding patient to the queue",
109
+ "recurringAppointment": "Recurring Appointment",
110
+ "repeatEvery": "Repeat every",
111
+ "save": "Save",
112
+ "saveAndClose": "Save and close",
113
+ "scheduled": "Scheduled",
114
+ "scheduledAppointments": "Scheduled appointments",
115
+ "search": "Search",
116
+ "searchForAVisitType": "Search for a visit type",
117
+ "selectAppointmentStatus": "Select status",
118
+ "selectAppointmentType": "Select an appointment type",
119
+ "selectFacility": "Select a facility",
120
+ "selectLocation": "Select location",
121
+ "selectOption": "Select an option",
122
+ "selectProvider": "Select a provider",
123
+ "selectService": "Select a service",
124
+ "selectServiceType": "Select service type",
125
+ "selectVisitType": "Please select a Visit Type",
126
+ "service": "Service",
127
+ "serviceName": "Service name",
128
+ "serviceType": "Service Type",
129
+ "startDate": "Start date",
130
+ "startTime": "Start Time",
131
+ "startVisitError": "Error starting visit",
132
+ "time": "Time",
133
+ "today": "Today",
134
+ "todays": "Today's",
135
+ "total": "Total",
136
+ "unscheduled": "Unscheduled",
137
+ "unscheduledAppointments": "Unscheduled appointments",
138
+ "unscheduledAppointments_lower": "unscheduled appointments",
139
+ "upcoming": "Upcoming",
140
+ "upcomingAppointments": "Upcoming appointments",
141
+ "view": "View",
142
+ "visitLocation": "Visit Location",
143
+ "visitStarted": "Visit started",
144
+ "visitType": "Visit Type",
145
+ "vitals": "Vitals",
146
+ "week": "Week",
147
+ "yes": "Yes"
148
+ }