@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.
Files changed (75) hide show
  1. package/.turbo/turbo-build.log +20 -20
  2. package/dist/153.js +1 -1
  3. package/dist/153.js.map +1 -0
  4. package/dist/319.js +1 -1
  5. package/dist/34.js +1 -1
  6. package/dist/34.js.map +1 -0
  7. package/dist/351.js +1 -1
  8. package/dist/351.js.map +1 -0
  9. package/dist/352.js +1 -1
  10. package/dist/352.js.map +1 -0
  11. package/dist/430.js +1 -1
  12. package/dist/430.js.map +1 -0
  13. package/dist/437.js +1 -1
  14. package/dist/437.js.map +1 -0
  15. package/dist/45.js +1 -1
  16. package/dist/45.js.map +1 -0
  17. package/dist/456.js +1 -0
  18. package/dist/456.js.map +1 -0
  19. package/dist/458.js +2 -0
  20. package/dist/458.js.map +1 -0
  21. package/dist/497.js +1 -1
  22. package/dist/497.js.map +1 -0
  23. package/dist/542.js +1 -1
  24. package/dist/542.js.map +1 -0
  25. package/dist/568.js +1 -1
  26. package/dist/568.js.map +1 -0
  27. package/dist/574.js +1 -1
  28. package/dist/647.js +1 -1
  29. package/dist/647.js.map +1 -0
  30. package/dist/685.js +1 -1
  31. package/dist/685.js.map +1 -0
  32. package/dist/692.js +1 -1
  33. package/dist/692.js.map +1 -0
  34. package/dist/757.js +1 -1
  35. package/dist/784.js +1 -1
  36. package/dist/784.js.map +1 -0
  37. package/dist/807.js +1 -1
  38. package/dist/821.js +1 -1
  39. package/dist/821.js.map +1 -0
  40. package/dist/830.js +1 -1
  41. package/dist/830.js.map +1 -0
  42. package/dist/843.js +1 -1
  43. package/dist/843.js.map +1 -0
  44. package/dist/858.js +1 -1
  45. package/dist/858.js.map +1 -0
  46. package/dist/976.js +1 -0
  47. package/dist/976.js.map +1 -0
  48. package/dist/984.js +1 -0
  49. package/dist/984.js.map +1 -0
  50. package/dist/main.js +1 -1
  51. package/dist/main.js.map +1 -0
  52. package/dist/openmrs-esm-appointments-app.js +1 -1
  53. package/dist/openmrs-esm-appointments-app.js.buildmanifest.json +205 -182
  54. package/dist/openmrs-esm-appointments-app.js.map +1 -0
  55. package/dist/openmrs-esm-appointments-app.old +1 -1
  56. package/package.json +2 -2
  57. package/src/appointment-forms/appointment-forms.resource.ts +5 -17
  58. package/src/appointment-forms/appointments-form.component.tsx +102 -234
  59. package/src/appointment-forms/appointments-form.scss +5 -5
  60. package/src/appointment-forms/appointments-forms.test.tsx +6 -16
  61. package/src/appointment-forms/useInitialFormValues.tsx +49 -0
  62. package/src/appointment-forms/workload-helper.ts +13 -19
  63. package/src/appointments/appointment-list.component.tsx +6 -6
  64. package/src/appointments/appointment-list.test.tsx +2 -2
  65. package/src/appointments-tabs/unscheduled-appointments.component.tsx +14 -9
  66. package/src/config-schema.ts +4 -13
  67. package/src/patient-search/patient-search.scss +1 -3
  68. package/translations/en.json +6 -7
  69. package/__mocks__/appointments.mock.ts +0 -411
  70. package/dist/268.js +0 -1
  71. package/dist/285.js +0 -2
  72. package/dist/339.js +0 -1
  73. package/dist/39.js +0 -1
  74. package/dist/842.js +0 -1
  75. /package/dist/{285.js.LICENSE.txt → 458.js.LICENSE.txt} +0 -0
@@ -1,7 +1,6 @@
1
- import React, { useState, useEffect, useMemo } from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import dayjs from 'dayjs';
4
- import isEmpty from 'lodash-es/isEmpty';
5
4
  import {
6
5
  Button,
7
6
  ButtonSet,
@@ -13,7 +12,6 @@ import {
13
12
  Select,
14
13
  SelectItem,
15
14
  Switch,
16
- TextArea,
17
15
  TimePicker,
18
16
  TimePickerSelect,
19
17
  Toggle,
@@ -23,38 +21,34 @@ import {
23
21
  Tabs,
24
22
  TabPanel,
25
23
  TabPanels,
24
+ TextArea,
26
25
  Layer,
27
- TextInput,
28
26
  } from '@carbon/react';
29
27
  import {
30
28
  useLocations,
31
- useSession,
32
- showToast,
33
- showNotification,
34
29
  ExtensionSlot,
35
30
  usePatient,
36
31
  useConfig,
37
- parseDate,
32
+ showNotification,
33
+ showToast,
38
34
  } from '@openmrs/esm-framework';
39
35
  import { AppointmentPayload, MappedAppointment } from '../types';
40
- import { amPm, convertTime12to24 } from '../helpers';
36
+ import { convertTime12to24, useAppointmentDate } from '../helpers';
41
37
  import {
42
- saveAppointment,
43
38
  useServices,
44
39
  useAppointmentSummary,
45
- checkAppointmentConflict,
46
- useMonthlyAppointmentSummary,
40
+ saveAppointment,
41
+ toAppointmentDateTime,
47
42
  } from './appointment-forms.resource';
48
43
  import { ConfigObject } from '../config-schema';
49
44
  import { useProviders } from '../hooks/useProviders';
50
45
  import { closeOverlay } from '../hooks/useOverlay';
51
- import { mockFrequency } from '../../__mocks__/appointments.mock';
52
46
  import WorkloadCard from './workload.component';
53
47
  import first from 'lodash-es/first';
54
48
  import styles from './appointments-form.scss';
55
- import { useSWRConfig } from 'swr';
56
- import { useAppointmentDate } from '../helpers/time';
57
- import { getMonthlyCalendarDistribution, getWeeklyCalendarDistribution } from './workload-helper';
49
+ import { useCalendarDistribution } from './workload-helper';
50
+ import { PatientAppointment, useInitialAppointmentFormValue } from './useInitialFormValues';
51
+ import { mutate } from 'swr';
58
52
 
59
53
  interface AppointmentFormProps {
60
54
  appointment?: MappedAppointment;
@@ -62,135 +56,44 @@ interface AppointmentFormProps {
62
56
  context: string;
63
57
  }
64
58
  const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientUuid, context }) => {
65
- const initialState = {
66
- patientUuid,
67
- dateTime: undefined,
68
- location: '',
69
- serviceUuid: '',
70
- comments: '',
71
- appointmentKind: '',
72
- status: '',
73
- id: undefined,
74
- gender: '',
75
- serviceType: '',
76
- provider: '',
77
- appointmentNumber: undefined,
78
- };
79
- const appointmentState = !isEmpty(appointment) ? appointment : initialState;
80
59
  const { t } = useTranslation();
81
- const { mutate } = useSWRConfig();
82
- const { appointmentTypes } = useConfig() as ConfigObject;
83
- const { daysOfTheWeek } = useConfig() as ConfigObject;
84
- const { appointmentComments } = useConfig() as ConfigObject;
85
- const { appointmentStatuses } = useConfig() as ConfigObject;
86
- const { patient, isLoading } = usePatient(patientUuid ?? appointmentState.patientUuid);
60
+ const { appointmentTypes, appointmentStatuses, hiddenFormFields } = useConfig() as ConfigObject;
61
+ const initialAppointmentFormValues = useInitialAppointmentFormValue(appointment, patientUuid);
62
+ const [patientAppointment, setPatientAppointment] = useState<PatientAppointment>(initialAppointmentFormValues);
63
+ const { patient, isLoading } = usePatient(patientUuid ?? patientAppointment.patientUuid);
87
64
  const locations = useLocations();
88
- const session = useSession();
89
65
  const { providers } = useProviders();
90
66
  const { services } = useServices();
91
- const [startDate, setStartDate] = useState(
92
- dayjs(appointmentState.dateTime).format('hh:mm') || dayjs(new Date()).format('hh:mm'),
93
- );
94
- const [endDate, setEndDate] = useState(
95
- dayjs(appointmentState.dateTime).format('hh:mm') || dayjs(new Date()).format('hh:mm'),
96
- );
97
- const [frequency, setFrequency] = useState('');
98
- const [selectedLocation, setSelectedLocation] = useState(appointmentState.location);
99
- const [selectedService, setSelectedService] = useState(appointmentState.serviceUuid);
100
- const [selectedProvider, setSelectedProvider] = useState(appointmentState.provider);
101
- const [reminder, setReminder] = useState('');
102
- const [appointmentComment, setAppointmentComment] = useState(appointmentState.comments);
103
- const [reason, setReason] = useState('');
104
- const [timeFormat, setTimeFormat] = useState<amPm>(new Date().getHours() >= 12 ? 'PM' : 'AM');
105
- const [visitDate, setVisitDate] = React.useState(
106
- appointmentState.dateTime ? new Date(appointmentState.dateTime) : new Date(),
107
- );
108
- const [isFullDay, setIsFullDay] = useState<boolean>(false);
109
- const [day, setDay] = useState(appointmentState.dateTime);
110
- const [appointmentType, setAppointmentType] = useState(appointmentState.appointmentKind);
111
- const [appointmentStatus, setAppointmentStatus] = useState(appointmentState.status ?? 'Scheduled');
112
67
  const [isSubmitting, setIsSubmitting] = useState(false);
113
- const appointmentStartDate = useAppointmentDate();
114
- const appointmentSummary = useAppointmentSummary(visitDate, selectedService);
115
- const appointmentMonthly = useMonthlyAppointmentSummary(visitDate, selectedService);
68
+ const appointmentSummary = useAppointmentSummary(patientAppointment.visitDate, patientAppointment.serviceUuid);
116
69
  const [selectedTab, setSelectedTab] = useState(0);
117
- const monthlyDistribution = useMemo(
118
- () => getMonthlyCalendarDistribution(new Date(appointmentStartDate), appointmentMonthly) ?? [],
119
- [appointmentStartDate, appointmentMonthly],
120
- );
121
-
122
- const weeklyDistribution = useMemo(
123
- () => getWeeklyCalendarDistribution(new Date(appointmentStartDate), appointmentSummary) ?? [],
124
- [appointmentStartDate, appointmentSummary],
70
+ const calendarWorkload = useCalendarDistribution(
71
+ patientAppointment.serviceUuid,
72
+ selectedTab === 0 ? 'week' : 'month',
125
73
  );
126
- const isMissingRequirements = !selectedService || !appointmentType.length || !selectedProvider;
127
- const appointmentService = services?.find(({ uuid }) => uuid === selectedService);
74
+ const appointmentStartDate = useAppointmentDate();
128
75
 
129
- useEffect(() => {
130
- if (appointmentService) {
131
- const [hours, minutes] = convertTime12to24(startDate, timeFormat);
132
- const startDatetime = new Date(
133
- dayjs(visitDate).year(),
134
- dayjs(visitDate).month(),
135
- dayjs(visitDate).date(),
136
- hours,
137
- minutes,
138
- );
139
- setEndDate(
140
- dayjs(startDatetime)
141
- .add(parseInt(appointmentService?.durationMins ?? '0'), 'minutes')
142
- .format('hh:mm'),
143
- );
144
- }
145
- }, [startDate, timeFormat, appointmentService, visitDate]);
76
+ const appointmentService = services?.find(({ uuid }) => uuid === patientAppointment.serviceUuid);
146
77
 
147
78
  const handleSubmit = async () => {
148
- const [hours, minutes] = convertTime12to24(startDate, timeFormat);
149
- const providerUuid =
150
- providers.find((provider) => provider.display === selectedProvider)?.uuid ?? appointment.providers[0].uuid;
151
- const startDatetime = new Date(
152
- dayjs(visitDate).year(),
153
- dayjs(visitDate).month(),
154
- dayjs(visitDate).date(),
155
- hours,
156
- minutes,
157
- );
158
-
159
- const endDatetime = dayjs(
160
- new Date(dayjs(visitDate).year(), dayjs(visitDate).month(), dayjs(visitDate).date(), hours, minutes),
161
- );
79
+ const [hours, minutes] = convertTime12to24(patientAppointment.startDateTime, patientAppointment.timeFormat);
80
+ const startDatetime = toAppointmentDateTime(patientAppointment.visitDate, hours, minutes);
81
+ const endDatetime = toAppointmentDateTime(patientAppointment.visitDate, hours, minutes);
162
82
  const appointmentPayload: AppointmentPayload = {
163
- appointmentKind: appointmentType,
164
- status: appointmentStatus,
165
- serviceUuid: selectedService,
83
+ appointmentKind: patientAppointment.appointmentKind,
84
+ status: patientAppointment.status,
85
+ serviceUuid: patientAppointment.serviceUuid,
166
86
  startDateTime: dayjs(startDatetime).format(),
167
87
  endDateTime: dayjs(endDatetime).format(),
168
- providerUuid: providerUuid,
169
- providers: [{ uuid: providerUuid }],
170
- comments: appointmentComment,
171
- locationUuid: selectedLocation,
172
- patientUuid: appointmentState.patientUuid,
173
- appointmentNumber: appointmentState.appointmentNumber,
174
- uuid: appointmentState.id,
88
+ providerUuid: patientAppointment.providerUuid,
89
+ providers: [{ uuid: patientAppointment.providerUuid }],
90
+ comments: patientAppointment.comments,
91
+ locationUuid: patientAppointment.locationUuid,
92
+ patientUuid: patientAppointment.patientUuid,
93
+ appointmentNumber: patientAppointment.appointmentNumber,
94
+ uuid: patientAppointment.uuid,
175
95
  };
176
96
 
177
- const { data } = await checkAppointmentConflict(appointmentPayload);
178
- const [bookingStatus] = Object.keys(data);
179
- const isPatientDoubleBooking = 'PATIENT_DOUBLE_BOOKING' === bookingStatus;
180
-
181
- if (isPatientDoubleBooking) {
182
- showToast({
183
- critical: true,
184
- kind: 'warning',
185
- description: t(
186
- 'doublePatientBooking',
187
- 'There exist an appointment on the specified service and appointment date',
188
- ),
189
- title: t('doubleBooking', 'Appointment double booking'),
190
- });
191
- return;
192
- }
193
-
194
97
  const abortController = new AbortController();
195
98
  setIsSubmitting(true);
196
99
  saveAppointment(appointmentPayload, abortController).then(
@@ -231,49 +134,12 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
231
134
  extensionSlotName="patient-header-slot"
232
135
  state={{
233
136
  patient,
234
- patientUuid: appointmentState.patientUuid,
137
+ patientUuid: patientAppointment.patientUuid,
235
138
  }}
236
139
  />
237
140
  </div>
238
141
  )}
239
142
 
240
- <div className={styles.childRow}>
241
- <div className={styles.row}>
242
- <Select
243
- labelText={t('frequency', 'Frequency')}
244
- id="frequency"
245
- className={styles.select}
246
- invalidText="Required"
247
- value={frequency}
248
- onChange={(event) => setFrequency(event.target.value)}
249
- light>
250
- {mockFrequency.data?.length > 0 &&
251
- mockFrequency.data.map((frequency) => (
252
- <SelectItem key={frequency.uuid} text={frequency.display} value={frequency.uuid}>
253
- {frequency.display}
254
- </SelectItem>
255
- ))}
256
- </Select>
257
-
258
- {isFullDay ? (
259
- <Select
260
- labelText={t('day', 'Day')}
261
- id="day"
262
- invalidText="Required"
263
- value={day}
264
- onChange={(event) => setDay(event.target.value)}
265
- light>
266
- {daysOfTheWeek?.length > 0 &&
267
- daysOfTheWeek.map((day) => (
268
- <SelectItem key={day} text={day} value={day}>
269
- {day}
270
- </SelectItem>
271
- ))}
272
- </Select>
273
- ) : null}
274
- </div>
275
- </div>
276
-
277
143
  <div className={styles.inputContainer} id="appointment-place">
278
144
  <p>{t('selectAppointmentLocation', 'Select where the appointment will take place')}</p>
279
145
  <ContentSwitcher className={styles.inputContainer} data-testid="appointment-place">
@@ -290,10 +156,9 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
290
156
  labelText={t('selectLocation', 'Select a location')}
291
157
  id="location"
292
158
  invalidText="Required"
293
- value={selectedLocation}
159
+ value={patientAppointment.locationUuid}
294
160
  className={styles.inputContainer}
295
- onChange={(event) => setSelectedLocation(event.target.value)}
296
- light>
161
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, locationUuid: event.target.value })}>
297
162
  {locations?.length > 0 &&
298
163
  locations.map((location) => (
299
164
  <SelectItem key={location.uuid} text={location.display} value={location.uuid}>
@@ -306,11 +171,10 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
306
171
  id="service"
307
172
  invalidText="Required"
308
173
  labelText={t('selectService', 'Select a service')}
309
- light
310
174
  className={styles.inputContainer}
311
- onChange={(event) => setSelectedService(event.target.value)}
312
- value={selectedService}>
313
- {!selectedService || selectedService == '--' ? (
175
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, serviceUuid: event.target.value })}
176
+ value={patientAppointment.serviceUuid}>
177
+ {!patientAppointment.serviceUuid || patientAppointment.serviceUuid == '--' ? (
314
178
  <SelectItem text={t('chooseService', 'Select service')} value="" />
315
179
  ) : null}
316
180
  {services?.length > 0 &&
@@ -324,16 +188,22 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
324
188
  <p>{t('appointmentDateAndTime', 'Appointments Date and Time')}</p>
325
189
 
326
190
  <div className={styles.row}>
327
- <Toggle onToggle={(value) => setIsFullDay(value)} id="allDay" labelA="Off" labelB="On" labelText="All Day" />
191
+ <Toggle
192
+ onToggle={(value) => setPatientAppointment({ ...patientAppointment, isFullDay: value })}
193
+ id="allDay"
194
+ labelA="Off"
195
+ labelB="On"
196
+ labelText="All Day"
197
+ defaultToggled={patientAppointment.isFullDay}
198
+ />
328
199
  <DatePicker
329
200
  dateFormat="d/m/Y"
330
201
  datePickerType="single"
331
202
  id="visitDate"
332
- light
333
- minDate={visitDate}
203
+ minDate={patientAppointment.visitDate}
334
204
  className={styles.datePickerInput}
335
- onChange={([date]) => setVisitDate(date)}
336
- value={visitDate}>
205
+ onChange={([date]) => setPatientAppointment({ ...patientAppointment, visitDate: date })}
206
+ value={patientAppointment.visitDate}>
337
207
  <DatePickerInput
338
208
  id="visitStartDateInput"
339
209
  labelText={t('date', 'Date')}
@@ -342,22 +212,21 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
342
212
  />
343
213
  </DatePicker>
344
214
  </div>
345
- {!isFullDay ? (
215
+ {!patientAppointment.isFullDay ? (
346
216
  <div className={styles.row}>
347
217
  <TimePicker
348
218
  disabled={!appointmentService}
349
- light
350
219
  className={styles.timePickerInput}
351
220
  pattern="([\d]+:[\d]{2})"
352
- onChange={(event) => setStartDate(event.target.value)}
353
- value={startDate}
221
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, startDateTime: event.target.value })}
222
+ value={patientAppointment.endDateTime}
354
223
  labelText={t('startTime', 'Start Time')}
355
224
  id="start-time-picker">
356
225
  <TimePickerSelect
357
226
  disabled={!appointmentService}
358
227
  id="start-time-picker"
359
- onChange={(event) => setTimeFormat(event.target.value as amPm)}
360
- value={timeFormat}
228
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, timeFormat: event.target.value })}
229
+ value={patientAppointment.timeFormat}
361
230
  labelText={t('time', 'Time')}
362
231
  aria-label={t('time', 'Time')}>
363
232
  <SelectItem value="AM" text="AM" />
@@ -367,18 +236,17 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
367
236
 
368
237
  <TimePicker
369
238
  disabled={!appointmentService}
370
- light
371
239
  className={styles.timePickerInput}
372
240
  pattern="([\d]+:[\d]{2})"
373
- onChange={(event) => setEndDate(event.target.value)}
374
- value={endDate}
241
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, endDateTime: event.target.value })}
242
+ value={patientAppointment.endDateTime}
375
243
  labelText={t('endTime', 'End Time')}
376
244
  id="end-time-picker">
377
245
  <TimePickerSelect
378
246
  disabled={!appointmentService}
379
247
  id="end-time-picker"
380
- onChange={(event) => setTimeFormat(event.target.value as amPm)}
381
- value={timeFormat}
248
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, timeFormat: event.target.value })}
249
+ value={patientAppointment.timeFormat}
382
250
  labelText={t('time', 'Time')}
383
251
  aria-label={t('time', 'Time')}>
384
252
  <SelectItem value="AM" text="AM" />
@@ -388,7 +256,7 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
388
256
  </div>
389
257
  ) : null}
390
258
 
391
- {selectedService && (
259
+ {patientAppointment.serviceUuid && (
392
260
  <div className={styles.workLoadContainer}>
393
261
  <>
394
262
  <p className={styles.workLoadTitle}>
@@ -410,14 +278,17 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
410
278
  <TabPanels>
411
279
  <TabPanel style={{ padding: 0 }}>
412
280
  <div className={styles.workLoadCard}>
413
- {weeklyDistribution?.map(({ date, count }, index) => {
281
+ {calendarWorkload?.map(({ date, count }, index) => {
414
282
  return (
415
283
  <WorkloadCard
416
- onClick={() => setVisitDate(new Date(date))}
284
+ onClick={() => setPatientAppointment({ ...patientAppointment, visitDate: new Date(date) })}
417
285
  key={date}
418
286
  date={dayjs(date).format('DD/MM')}
419
287
  count={count}
420
- isActive={dayjs(date).format('DD-MM-YYYY') === dayjs(visitDate).format('DD-MM-YYYY')}
288
+ isActive={
289
+ dayjs(date).format('DD-MM-YYYY') ===
290
+ dayjs(patientAppointment.visitDate).format('DD-MM-YYYY')
291
+ }
421
292
  />
422
293
  );
423
294
  })}
@@ -425,14 +296,17 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
425
296
  </TabPanel>
426
297
  <TabPanel style={{ padding: 0 }}>
427
298
  <div className={styles.monthlyWorkLoadCard}>
428
- {monthlyDistribution?.map(({ date, count }) => {
299
+ {calendarWorkload?.map(({ date, count }) => {
429
300
  return (
430
301
  <WorkloadCard
431
- onClick={() => setVisitDate(new Date(date))}
302
+ onClick={() => setPatientAppointment({ ...patientAppointment, visitDate: new Date(date) })}
432
303
  key={date}
433
304
  date={dayjs(date).format('DD/MM')}
434
305
  count={count}
435
- isActive={dayjs(date).format('DD-MM-YYYY') === dayjs(visitDate).format('DD-MM-YYYY')}
306
+ isActive={
307
+ dayjs(date).format('DD-MM-YYYY') ===
308
+ dayjs(patientAppointment.visitDate).format('DD-MM-YYYY')
309
+ }
436
310
  />
437
311
  );
438
312
  })}
@@ -448,11 +322,10 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
448
322
  id="appointmentType"
449
323
  invalidText="Required"
450
324
  labelText={t('selectAppointmentType', 'Select an appointment type')}
451
- light
452
325
  className={styles.inputContainer}
453
- onChange={(event) => setAppointmentType(event.target.value)}
454
- value={appointmentType}>
455
- {!appointmentType || appointmentType == '--' ? (
326
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, appointmentKind: event.target.value })}
327
+ value={patientAppointment.appointmentKind}>
328
+ {!patientAppointment.appointmentKind || patientAppointment.appointmentKind == '--' ? (
456
329
  <SelectItem text={t('selectAppointmentType', 'Select an appointment type')} value="" />
457
330
  ) : null}
458
331
  {appointmentTypes?.length > 0 &&
@@ -467,11 +340,10 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
467
340
  id="appointmentStatus"
468
341
  invalidText="Required"
469
342
  labelText={t('selectAppointmentStatus', 'Select status')}
470
- light
471
343
  className={styles.inputContainer}
472
- onChange={(event) => setAppointmentStatus(event.target.value)}
473
- value={appointmentStatus}>
474
- {!appointmentStatus || appointmentStatus == '--' ? (
344
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, status: event.target.value })}
345
+ value={patientAppointment.status}>
346
+ {!patientAppointment.status || patientAppointment.status == '--' ? (
475
347
  <SelectItem text={t('selectAppointmentStatus', 'Select status')} value="" />
476
348
  ) : null}
477
349
  {appointmentStatuses?.length > 0 &&
@@ -487,14 +359,17 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
487
359
  id="providers"
488
360
  invalidText="Required"
489
361
  labelText={t('selectProvider', 'Select a provider')}
490
- light
491
- className={styles.inputContainer}
492
- onChange={(event) => setSelectedProvider(event.target.value)}
493
- value={selectedProvider}>
494
- {!selectedProvider ? <SelectItem text={t('chooseProvider', 'Select Provider')} value="" /> : null}
362
+ className={`${styles.inputContainer} ${hiddenFormFields.includes('providers') && styles.hide}`}
363
+ onChange={(event) => {
364
+ setPatientAppointment({ ...patientAppointment, providerUuid: event.target.value });
365
+ }}
366
+ value={patientAppointment.providerUuid}>
367
+ {!patientAppointment.providerUuid ? (
368
+ <SelectItem text={t('chooseProvider', 'Select Provider')} value="" />
369
+ ) : null}
495
370
  {providers?.length > 0 &&
496
371
  providers.map((provider) => (
497
- <SelectItem key={provider.uuid} text={provider.display} value={provider.display}>
372
+ <SelectItem key={provider.uuid} text={provider.display} value={provider.uuid}>
498
373
  {provider.display}
499
374
  </SelectItem>
500
375
  ))}
@@ -507,33 +382,26 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
507
382
  <RadioButtonGroup
508
383
  defaultSelected="No"
509
384
  orientation="vertical"
510
- onChange={(event) => {
511
- setReminder(event.toString());
512
- }}
385
+ onChange={(event) => {}}
513
386
  name="appointment-reminder-radio-group">
514
387
  <RadioButton className={styles.radioButton} id="Yes" labelText="Yes" value="Yes" />
515
388
  <RadioButton className={styles.radioButton} id="No" labelText="No" value="No" />
516
389
  </RadioButtonGroup>
517
390
  </div>
518
391
 
519
- <Select
520
- id="reason"
521
- invalidText="Required"
522
- labelText={t('reasonForChanges', 'Reason for change')}
523
- light
524
- className={styles.inputContainer}
525
- onChange={(event) => setAppointmentComment(event.target.value)}
526
- value={appointmentComment}>
527
- {!appointmentComment || appointmentComment == '--' ? (
528
- <SelectItem text={t('reasonForChanges', 'Reason for change')} value="" />
529
- ) : null}
530
- {appointmentComments?.length > 0 &&
531
- appointmentComments.map((comments) => (
532
- <SelectItem key={comments} text={comments} value={comments}>
533
- {comments}
534
- </SelectItem>
535
- ))}
536
- </Select>
392
+ <Layer>
393
+ <TextArea
394
+ cols={50}
395
+ id="comment"
396
+ invalidText="A valid value is required"
397
+ labelText={t('comment', 'Comment')}
398
+ placeholder={t('typeInComments', 'Type in appointment comment')}
399
+ rows={4}
400
+ value={patientAppointment.comments}
401
+ onChange={(event) => setPatientAppointment({ ...patientAppointment, comments: event.target.value })}
402
+ />
403
+ </Layer>
404
+
537
405
  <ButtonSet>
538
406
  <Button onClick={closeOverlay} className={styles.button} kind="secondary">
539
407
  {t('discard', 'Discard')}
@@ -541,7 +409,7 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
541
409
  <Button
542
410
  onClick={handleSubmit}
543
411
  className={styles.button}
544
- disabled={isSubmitting || isMissingRequirements}
412
+ disabled={isSubmitting || !patientAppointment.serviceUuid}
545
413
  kind="primary"
546
414
  type="submit">
547
415
  {t('save', 'Save')}
@@ -22,12 +22,8 @@
22
22
  margin-right: 60%;
23
23
  }
24
24
 
25
- .childRow {
26
- margin-left: spacing.$spacing-05;
27
- }
28
-
29
25
  .inputContainer {
30
- margin: spacing.$spacing-05;
26
+ margin: spacing.$spacing-05 0;
31
27
  }
32
28
 
33
29
  .button {
@@ -74,3 +70,7 @@
74
70
  .input {
75
71
  width: 13.5rem;
76
72
  }
73
+
74
+ .hide {
75
+ display: none;
76
+ }
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { render, screen, within, fireEvent } from '@testing-library/react';
3
3
  import userEvent from '@testing-library/user-event';
4
4
  import { useConfig, usePatient } from '@openmrs/esm-framework';
5
- import { mockPatient, mockServices, mockProviders } from '../../__mocks__/appointments.mock';
5
+ import { mockPatient, mockServices, mockProviders } from '../../../../__mocks__/appointments.mock';
6
6
  import { mockLocations } from '../../../../__mocks__/locations.mock';
7
7
  import { mockSession } from '../../../../__mocks__/session.mock';
8
8
  import { MappedAppointment } from '../types';
@@ -39,6 +39,7 @@ let mockOpenmrsConfig = {
39
39
  daysOfTheWeek: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
40
40
  appointmentTypes: ['Scheduled', 'WalkIn', 'Virtual'],
41
41
  appointmentStatuses: ['Requested', 'Scheduled', 'CheckedIn', 'Completed', 'Cancelled', 'Missed'],
42
+ hiddenFormFields: [],
42
43
  };
43
44
 
44
45
  describe('AppointmentForm', () => {
@@ -74,22 +75,15 @@ describe('AppointmentForm', () => {
74
75
  allSelects.forEach((select) => inputAndSelectNamesAndTabValues.push(select?.id));
75
76
  allTabs.forEach((tab) => inputAndSelectNamesAndTabValues.push(tab?.id));
76
77
 
77
- expect(screen.queryByLabelText('Reason For Changes')).not.toBeInTheDocument();
78
78
  expect(inputAndSelectNamesAndTabValues).toEqual([
79
79
  'visitStartDateInput',
80
- 'start-time-picker',
81
- 'end-time-picker',
82
80
  'Yes',
83
81
  'No',
84
82
  '',
85
- 'frequency',
86
83
  'location',
87
84
  'service',
88
- 'start-time-picker',
89
- 'end-time-picker',
90
85
  'appointmentType',
91
86
  'providers',
92
- 'reason',
93
87
  'facility',
94
88
  'community',
95
89
  ]);
@@ -97,20 +91,16 @@ describe('AppointmentForm', () => {
97
91
 
98
92
  it('renders the form with all expected inputs in edit mode', () => {
99
93
  renderAppointmentsForm('editing', mockPatient.uuid);
100
- expect(screen.getByRole('option', { name: /Reason for change/ })).toBeInTheDocument();
101
94
  });
102
95
 
103
96
  it('renders the expected appointment types', () => {
104
97
  renderAppointmentsForm('creating', mockPatient.uuid);
105
98
  const appointmentTypeSelect = screen.getByLabelText('Select an appointment type');
106
99
 
107
- expect((screen.getByRole('option', { name: 'Select an appointment type' }) as HTMLOptionElement).selected).toBe(
108
- true,
109
- );
110
- expect(within(appointmentTypeSelect).getAllByRole('option')).toHaveLength(4);
111
- expect(within(appointmentTypeSelect).getAllByRole('option')[1]).toHaveValue('Scheduled');
112
- expect(within(appointmentTypeSelect).getAllByRole('option')[2]).toHaveValue('WalkIn');
113
- expect(within(appointmentTypeSelect).getAllByRole('option')[3]).toHaveValue('Virtual');
100
+ expect(within(appointmentTypeSelect).getAllByRole('option')).toHaveLength(3);
101
+ expect(within(appointmentTypeSelect).getAllByRole('option')[2]).toHaveValue('Virtual');
102
+ expect(within(appointmentTypeSelect).getAllByRole('option')[1]).toHaveValue('WalkIn');
103
+ expect(within(appointmentTypeSelect).getAllByRole('option')[0]).toHaveValue('Scheduled');
114
104
 
115
105
  // TODO handle onselect an option
116
106
  });