@kenyaemr/esm-appointments-app 8.1.1-pre.129 → 8.1.2-pre.152
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 +27 -25
- package/dist/111.js +2 -0
- package/dist/111.js.map +1 -0
- package/dist/123.js +2 -0
- package/dist/{198.js.LICENSE.txt → 123.js.LICENSE.txt} +0 -6
- package/dist/123.js.map +1 -0
- package/dist/130.js +1 -1
- package/dist/130.js.map +1 -1
- package/dist/{787.js → 139.js} +1 -1
- package/dist/139.js.map +1 -0
- package/dist/228.js +1 -0
- package/dist/236.js +1 -0
- package/dist/240.js +1 -0
- package/dist/261.js +1 -0
- package/dist/269.js +1 -1
- package/dist/269.js.map +1 -1
- package/dist/271.js +1 -1
- package/dist/272.js +1 -0
- package/dist/319.js +1 -1
- package/dist/336.js +1 -0
- package/dist/378.js +1 -0
- package/dist/443.js +1 -0
- package/dist/443.js.map +1 -0
- package/dist/460.js +1 -1
- package/dist/529.js +1 -1
- package/dist/529.js.map +1 -1
- package/dist/539.js +1 -0
- package/dist/566.js +1 -0
- package/dist/574.js +1 -1
- package/dist/581.js +1 -1
- package/dist/644.js +1 -1
- package/dist/652.js +1 -0
- package/dist/673.js +1 -0
- package/dist/705.js +1 -0
- package/dist/711.js +1 -1
- package/dist/711.js.map +1 -1
- package/dist/727.js +1 -0
- package/dist/737.js +1 -0
- package/dist/744.js +1 -0
- package/dist/757.js +1 -1
- package/dist/788.js +1 -1
- package/dist/807.js +1 -1
- package/dist/833.js +1 -1
- package/dist/899.js +1 -0
- package/dist/923.js +1 -0
- package/dist/923.js.map +1 -0
- package/dist/kenyaemr-esm-appointments-app.js +1 -1
- package/dist/kenyaemr-esm-appointments-app.js.buildmanifest.json +454 -102
- package/dist/kenyaemr-esm-appointments-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package-lock.json +6416 -0
- package/package.json +5 -5
- package/src/appointments/appointment-tabs.component.tsx +1 -1
- package/src/appointments/common-components/appointments-table.component.tsx +0 -1
- package/src/appointments/common-components/appointments-table.test.tsx +7 -3
- package/src/appointments/common-components/checkin-button.component.tsx +5 -1
- package/src/appointments/common-components/end-appointment.modal.tsx +2 -2
- package/src/appointments/scheduled/scheduled-appointments.component.tsx +1 -1
- package/src/appointments/unscheduled/unscheduled-appointments.component.tsx +6 -6
- package/src/appointments/unscheduled/unscheduled-appointments.test.tsx +19 -4
- package/src/appointments.component.tsx +7 -7
- package/src/appointments.test.tsx +11 -1
- package/src/calendar/appointments-calendar-view.component.tsx +2 -2
- package/src/calendar/monthly/monthly-workload-view.component.tsx +7 -7
- package/src/config-schema.ts +6 -70
- package/src/form/appointments-form.component.tsx +84 -73
- package/src/form/appointments-form.resource.ts +4 -4
- package/src/form/appointments-form.scss +1 -1
- package/src/form/appointments-form.test.tsx +142 -110
- package/src/patient-appointments/patient-appointments-action-menu.component.tsx +2 -4
- package/src/patient-appointments/patient-appointments-base.test.tsx +1 -1
- package/src/patient-appointments/patient-appointments-cancel.modal.tsx +6 -1
- package/src/patient-appointments/patient-appointments-cancel.scss +29 -0
- package/src/patient-appointments/patient-upcoming-appointments-card.component.tsx +64 -8
- package/src/routes.json +1 -1
- package/src/types/index.ts +1 -1
- package/src/workload/monthly-view-workload/monthly-view.component.tsx +8 -6
- package/src/workload/monthly-view-workload/monthlyWorkCard.tsx +3 -2
- package/src/workload/workload-card.component.tsx +5 -3
- package/src/workload/workload.component.tsx +13 -20
- package/src/workload/workload.resource.ts +3 -0
- package/translations/am.json +4 -2
- package/translations/ar.json +24 -22
- package/translations/de.json +168 -0
- package/translations/en.json +3 -1
- package/translations/es.json +58 -56
- package/translations/fr.json +4 -2
- package/translations/he.json +93 -91
- package/translations/hi.json +168 -0
- package/translations/hi_IN.json +168 -0
- package/translations/id.json +168 -0
- package/translations/it.json +168 -0
- package/translations/km.json +4 -2
- package/translations/ne.json +168 -0
- package/translations/pt.json +168 -0
- package/translations/pt_BR.json +168 -0
- package/translations/qu.json +168 -0
- package/translations/si.json +168 -0
- package/translations/sw.json +168 -0
- package/translations/sw_KE.json +168 -0
- package/translations/tr.json +168 -0
- package/translations/tr_TR.json +168 -0
- package/translations/uk.json +168 -0
- package/translations/vi.json +168 -0
- package/translations/zh.json +4 -2
- package/translations/zh_CN.json +4 -2
- package/dist/198.js +0 -2
- package/dist/198.js.map +0 -1
- package/dist/265.js +0 -1
- package/dist/265.js.map +0 -1
- package/dist/440.js +0 -2
- package/dist/440.js.map +0 -1
- package/dist/501.js +0 -1
- package/dist/501.js.map +0 -1
- package/dist/787.js.map +0 -1
- package/src/hooks/useDefaultLocation.ts +0 -14
- /package/dist/{440.js.LICENSE.txt → 111.js.LICENSE.txt} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useContext, useEffect, useState } from 'react';
|
|
2
|
-
import { useTranslation } from 'react-i18next';
|
|
3
2
|
import dayjs from 'dayjs';
|
|
3
|
+
import { Controller, useController, useForm } from 'react-hook-form';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
4
5
|
import {
|
|
5
6
|
Button,
|
|
6
7
|
ButtonSet,
|
|
@@ -20,9 +21,7 @@ import {
|
|
|
20
21
|
TimePickerSelect,
|
|
21
22
|
Toggle,
|
|
22
23
|
} from '@carbon/react';
|
|
23
|
-
import { Controller, useController, useForm } from 'react-hook-form';
|
|
24
24
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
25
|
-
import { z } from 'zod';
|
|
26
25
|
import {
|
|
27
26
|
ExtensionSlot,
|
|
28
27
|
ResponsiveWrapper,
|
|
@@ -33,8 +32,11 @@ import {
|
|
|
33
32
|
useLocations,
|
|
34
33
|
usePatient,
|
|
35
34
|
useSession,
|
|
35
|
+
type DefaultWorkspaceProps,
|
|
36
36
|
type FetchResponse,
|
|
37
37
|
} from '@openmrs/esm-framework';
|
|
38
|
+
import { z } from 'zod';
|
|
39
|
+
import { type ConfigObject } from '../config-schema';
|
|
38
40
|
import {
|
|
39
41
|
checkAppointmentConflict,
|
|
40
42
|
saveAppointment,
|
|
@@ -42,9 +44,6 @@ import {
|
|
|
42
44
|
useAppointmentService,
|
|
43
45
|
useMutateAppointments,
|
|
44
46
|
} from './appointments-form.resource';
|
|
45
|
-
import { useProviders } from '../hooks/useProviders';
|
|
46
|
-
import type { Appointment, AppointmentPayload, RecurringPattern } from '../types';
|
|
47
|
-
import { type ConfigObject } from '../config-schema';
|
|
48
47
|
import {
|
|
49
48
|
appointmentLocationTagName,
|
|
50
49
|
dateFormat,
|
|
@@ -53,30 +52,30 @@ import {
|
|
|
53
52
|
moduleName,
|
|
54
53
|
weekDays,
|
|
55
54
|
} from '../constants';
|
|
55
|
+
import { useProviders } from '../hooks/useProviders';
|
|
56
|
+
import type { Appointment, AppointmentPayload, RecurringPattern } from '../types';
|
|
56
57
|
import SelectedDateContext from '../hooks/selectedDateContext';
|
|
57
58
|
import Workload from '../workload/workload.component';
|
|
58
59
|
import styles from './appointments-form.scss';
|
|
59
60
|
|
|
60
|
-
const time12HourFormatRegexPattern = '^(1[0-2]|0?[1-9]):[0-5][0-9]$';
|
|
61
|
-
|
|
62
|
-
function isValidTime(timeStr) {
|
|
63
|
-
return timeStr.match(new RegExp(time12HourFormatRegexPattern));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
61
|
interface AppointmentsFormProps {
|
|
67
62
|
appointment?: Appointment;
|
|
68
63
|
recurringPattern?: RecurringPattern;
|
|
69
64
|
patientUuid?: string;
|
|
70
65
|
context: string;
|
|
71
|
-
closeWorkspace: () => void;
|
|
72
66
|
}
|
|
73
67
|
|
|
74
|
-
const
|
|
68
|
+
const time12HourFormatRegexPattern = '^(1[0-2]|0?[1-9]):[0-5][0-9]$';
|
|
69
|
+
|
|
70
|
+
const isValidTime = (timeStr: string) => timeStr.match(new RegExp(time12HourFormatRegexPattern));
|
|
71
|
+
|
|
72
|
+
const AppointmentsForm: React.FC<AppointmentsFormProps & DefaultWorkspaceProps> = ({
|
|
75
73
|
appointment,
|
|
76
74
|
recurringPattern,
|
|
77
75
|
patientUuid,
|
|
78
76
|
context,
|
|
79
77
|
closeWorkspace,
|
|
78
|
+
promptBeforeClosing,
|
|
80
79
|
}) => {
|
|
81
80
|
const { patient } = usePatient(patientUuid);
|
|
82
81
|
const { mutateAppointments } = useMutateAppointments();
|
|
@@ -97,11 +96,10 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
97
96
|
|
|
98
97
|
const [isRecurringAppointment, setIsRecurringAppointment] = useState(false);
|
|
99
98
|
const [isAllDayAppointment, setIsAllDayAppointment] = useState(false);
|
|
100
|
-
const [isConflict, setIsConflict] = useState(false);
|
|
101
99
|
const defaultRecurringPatternType = recurringPattern?.type || 'DAY';
|
|
102
100
|
const defaultRecurringPatternPeriod = recurringPattern?.period || 1;
|
|
103
101
|
const defaultRecurringPatternDaysOfWeek = recurringPattern?.daysOfWeek || [];
|
|
104
|
-
|
|
102
|
+
const [isSuccessful, setIsSuccessful] = useState(false);
|
|
105
103
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
106
104
|
|
|
107
105
|
// TODO can we clean this all up to be more consistent between using Date and dayjs?
|
|
@@ -127,7 +125,7 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
127
125
|
const defaultDuration =
|
|
128
126
|
appointment?.startDateTime && appointment?.endDateTime
|
|
129
127
|
? dayjs(appointment.endDateTime).diff(dayjs(appointment.startDateTime), 'minutes')
|
|
130
|
-
:
|
|
128
|
+
: undefined;
|
|
131
129
|
|
|
132
130
|
// t('durationErrorMessage', 'Duration should be greater than zero')
|
|
133
131
|
const appointmentsFormSchema = z
|
|
@@ -156,7 +154,9 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
156
154
|
recurringPatternPeriod: z.number(),
|
|
157
155
|
recurringPatternDaysOfWeek: z.array(z.string()),
|
|
158
156
|
selectedDaysOfWeekText: z.string().optional(),
|
|
159
|
-
startTime: z.string().refine((value) => isValidTime(value)
|
|
157
|
+
startTime: z.string().refine((value) => isValidTime(value), {
|
|
158
|
+
message: translateFrom(moduleName, 'invalidTime', 'Invalid time'),
|
|
159
|
+
}),
|
|
160
160
|
timeFormat: z.enum(['AM', 'PM']),
|
|
161
161
|
appointmentDateTime: z.object({
|
|
162
162
|
startDate: z.date(),
|
|
@@ -219,7 +219,8 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
219
219
|
setValue,
|
|
220
220
|
watch,
|
|
221
221
|
handleSubmit,
|
|
222
|
-
|
|
222
|
+
reset,
|
|
223
|
+
formState: { errors, isDirty },
|
|
223
224
|
} = useForm<AppointmentFormData>({
|
|
224
225
|
mode: 'all',
|
|
225
226
|
resolver: zodResolver(appointmentsFormSchema),
|
|
@@ -250,7 +251,7 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
250
251
|
},
|
|
251
252
|
});
|
|
252
253
|
|
|
253
|
-
useEffect(() => setValue('formIsRecurringAppointment', isRecurringAppointment), [isRecurringAppointment]);
|
|
254
|
+
useEffect(() => setValue('formIsRecurringAppointment', isRecurringAppointment), [isRecurringAppointment, setValue]);
|
|
254
255
|
|
|
255
256
|
// Retrive ref callback for appointmentDateTime (startDate & recurringPatternEndDate)
|
|
256
257
|
const {
|
|
@@ -268,12 +269,22 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
268
269
|
endDateRef(endDateElement);
|
|
269
270
|
}, [startDateRef, endDateRef]);
|
|
270
271
|
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
if (isSuccessful) {
|
|
274
|
+
reset();
|
|
275
|
+
promptBeforeClosing(() => false);
|
|
276
|
+
closeWorkspace();
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
promptBeforeClosing(() => isDirty);
|
|
280
|
+
}, [isDirty, promptBeforeClosing, isSuccessful, reset, closeWorkspace]);
|
|
281
|
+
|
|
271
282
|
const handleWorkloadDateChange = (date: Date) => {
|
|
272
283
|
const appointmentDate = getValues('appointmentDateTime');
|
|
273
284
|
setValue('appointmentDateTime', { ...appointmentDate, startDate: date });
|
|
274
285
|
};
|
|
275
286
|
|
|
276
|
-
const
|
|
287
|
+
const handleSelectChange = (e) => {
|
|
277
288
|
setValue(
|
|
278
289
|
'selectedDaysOfWeekText',
|
|
279
290
|
(() => {
|
|
@@ -338,7 +349,9 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
338
349
|
appointmentRequest: appointmentPayload,
|
|
339
350
|
recurringPattern: constructRecurringPattern(data),
|
|
340
351
|
};
|
|
352
|
+
|
|
341
353
|
const abortController = new AbortController();
|
|
354
|
+
|
|
342
355
|
(isRecurringAppointment
|
|
343
356
|
? saveRecurringAppointments(recurringAppointmentPayload, abortController)
|
|
344
357
|
: saveAppointment(appointmentPayload, abortController)
|
|
@@ -346,7 +359,7 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
346
359
|
({ status }) => {
|
|
347
360
|
if (status === 200) {
|
|
348
361
|
setIsSubmitting(false);
|
|
349
|
-
|
|
362
|
+
setIsSuccessful(true);
|
|
350
363
|
mutateAppointments();
|
|
351
364
|
showSnackbar({
|
|
352
365
|
isLowContrast: true,
|
|
@@ -442,15 +455,13 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
442
455
|
};
|
|
443
456
|
};
|
|
444
457
|
|
|
445
|
-
const onError = (error) => console.error(error);
|
|
446
|
-
|
|
447
458
|
if (isLoading)
|
|
448
459
|
return (
|
|
449
460
|
<InlineLoading className={styles.loader} description={`${t('loading', 'Loading')} ...`} role="progressbar" />
|
|
450
461
|
);
|
|
451
462
|
|
|
452
463
|
return (
|
|
453
|
-
<Form onSubmit={handleSubmit(handleSaveAppointment
|
|
464
|
+
<Form onSubmit={handleSubmit(handleSaveAppointment)}>
|
|
454
465
|
<Stack gap={4}>
|
|
455
466
|
{patient && (
|
|
456
467
|
<ExtensionSlot
|
|
@@ -468,16 +479,16 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
468
479
|
<Controller
|
|
469
480
|
name="location"
|
|
470
481
|
control={control}
|
|
471
|
-
render={({ field: { onChange, value, onBlur, ref }
|
|
482
|
+
render={({ field: { onChange, value, onBlur, ref } }) => (
|
|
472
483
|
<Select
|
|
473
484
|
id="location"
|
|
485
|
+
invalid={!!errors?.location}
|
|
486
|
+
invalidText={errors?.location?.message}
|
|
474
487
|
labelText={t('selectALocation', 'Select a location')}
|
|
475
488
|
onChange={onChange}
|
|
476
489
|
onBlur={onBlur}
|
|
477
|
-
value={value}
|
|
478
490
|
ref={ref}
|
|
479
|
-
|
|
480
|
-
invalidText={fieldState?.error?.message}>
|
|
491
|
+
value={value}>
|
|
481
492
|
<SelectItem text={t('chooseLocation', 'Choose a location')} value="" />
|
|
482
493
|
{locations?.length > 0 &&
|
|
483
494
|
locations.map((location) => (
|
|
@@ -496,10 +507,13 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
496
507
|
<Controller
|
|
497
508
|
name="selectedService"
|
|
498
509
|
control={control}
|
|
499
|
-
render={({ field: { onBlur, onChange, value, ref }
|
|
510
|
+
render={({ field: { onBlur, onChange, value, ref } }) => (
|
|
500
511
|
<Select
|
|
501
512
|
id="service"
|
|
513
|
+
invalid={!!errors?.selectedService}
|
|
514
|
+
invalidText={errors?.selectedService?.message}
|
|
502
515
|
labelText={t('selectService', 'Select a service')}
|
|
516
|
+
onBlur={onBlur}
|
|
503
517
|
onChange={(event) => {
|
|
504
518
|
if (context === 'creating') {
|
|
505
519
|
setValue(
|
|
@@ -518,11 +532,8 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
518
532
|
}
|
|
519
533
|
onChange(event);
|
|
520
534
|
}}
|
|
521
|
-
onBlur={onBlur}
|
|
522
|
-
value={value}
|
|
523
535
|
ref={ref}
|
|
524
|
-
|
|
525
|
-
invalidText={fieldState?.error?.message}>
|
|
536
|
+
value={value}>
|
|
526
537
|
<SelectItem text={t('chooseService', 'Select service')} value="" />
|
|
527
538
|
{services?.length > 0 &&
|
|
528
539
|
services.map((service) => (
|
|
@@ -541,17 +552,17 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
541
552
|
<Controller
|
|
542
553
|
name="appointmentType"
|
|
543
554
|
control={control}
|
|
544
|
-
render={({ field: { onBlur, onChange, value, ref }
|
|
555
|
+
render={({ field: { onBlur, onChange, value, ref } }) => (
|
|
545
556
|
<Select
|
|
546
557
|
disabled={!appointmentTypes?.length}
|
|
547
558
|
id="appointmentType"
|
|
559
|
+
invalid={!!errors?.appointmentType}
|
|
560
|
+
invalidText={errors?.appointmentType?.message}
|
|
548
561
|
labelText={t('selectAppointmentType', 'Select the type of appointment')}
|
|
562
|
+
onBlur={onBlur}
|
|
549
563
|
onChange={onChange}
|
|
550
|
-
value={value}
|
|
551
564
|
ref={ref}
|
|
552
|
-
|
|
553
|
-
invalid={!!fieldState?.error?.message}
|
|
554
|
-
invalidText={fieldState?.error?.message}>
|
|
565
|
+
value={value}>
|
|
555
566
|
<SelectItem text={t('chooseAppointmentType', 'Choose appointment type')} value="" />
|
|
556
567
|
{appointmentTypes?.length > 0 &&
|
|
557
568
|
appointmentTypes.map((appointmentType, index) => (
|
|
@@ -629,7 +640,7 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
629
640
|
</ResponsiveWrapper>
|
|
630
641
|
|
|
631
642
|
{!isAllDayAppointment && (
|
|
632
|
-
<TimeAndDuration
|
|
643
|
+
<TimeAndDuration control={control} errors={errors} services={services} watch={watch} t={t} />
|
|
633
644
|
)}
|
|
634
645
|
|
|
635
646
|
<ResponsiveWrapper>
|
|
@@ -681,21 +692,21 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
681
692
|
render={({ field: { onChange } }) => (
|
|
682
693
|
<MultiSelect
|
|
683
694
|
className={styles.weekSelect}
|
|
684
|
-
label={getValues('selectedDaysOfWeekText')}
|
|
685
695
|
id="daysOfWeek"
|
|
696
|
+
initialSelectedItems={weekDays.filter((i) =>
|
|
697
|
+
getValues('recurringPatternDaysOfWeek').includes(i.id),
|
|
698
|
+
)}
|
|
686
699
|
items={weekDays}
|
|
687
700
|
itemToString={(item) => (item ? t(item.labelCode, item.label) : '')}
|
|
701
|
+
label={getValues('selectedDaysOfWeekText')}
|
|
702
|
+
onChange={(e) => {
|
|
703
|
+
onChange(e);
|
|
704
|
+
handleSelectChange(e);
|
|
705
|
+
}}
|
|
688
706
|
selectionFeedback="top-after-reopen"
|
|
689
707
|
sortItems={(items) => {
|
|
690
708
|
return items.sort((a, b) => a.order > b.order);
|
|
691
709
|
}}
|
|
692
|
-
initialSelectedItems={weekDays.filter((i) => {
|
|
693
|
-
return getValues('recurringPatternDaysOfWeek').includes(i.id);
|
|
694
|
-
})}
|
|
695
|
-
onChange={(e) => {
|
|
696
|
-
onChange(e);
|
|
697
|
-
handleMultiselectChange(e);
|
|
698
|
-
}}
|
|
699
710
|
/>
|
|
700
711
|
)}
|
|
701
712
|
/>
|
|
@@ -743,7 +754,7 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
743
754
|
</ResponsiveWrapper>
|
|
744
755
|
|
|
745
756
|
{!isAllDayAppointment && (
|
|
746
|
-
<TimeAndDuration
|
|
757
|
+
<TimeAndDuration control={control} services={services} watch={watch} t={t} errors={errors} />
|
|
747
758
|
)}
|
|
748
759
|
</div>
|
|
749
760
|
)}
|
|
@@ -754,9 +765,9 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
754
765
|
<section className={styles.formGroup}>
|
|
755
766
|
<ResponsiveWrapper>
|
|
756
767
|
<Workload
|
|
757
|
-
selectedService={watch('selectedService')}
|
|
758
768
|
appointmentDate={watch('appointmentDateTime').startDate}
|
|
759
769
|
onWorkloadDateChange={handleWorkloadDateChange}
|
|
770
|
+
selectedService={watch('selectedService')}
|
|
760
771
|
/>
|
|
761
772
|
</ResponsiveWrapper>
|
|
762
773
|
</section>
|
|
@@ -769,11 +780,11 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
769
780
|
<Controller
|
|
770
781
|
name="appointmentStatus"
|
|
771
782
|
control={control}
|
|
772
|
-
render={({ field: { onBlur, onChange, value, ref }
|
|
783
|
+
render={({ field: { onBlur, onChange, value, ref } }) => (
|
|
773
784
|
<Select
|
|
774
785
|
id="appointmentStatus"
|
|
775
|
-
invalid={!!
|
|
776
|
-
invalidText={
|
|
786
|
+
invalid={!!errors?.appointmentStatus}
|
|
787
|
+
invalidText={errors?.appointmentStatus?.message}
|
|
777
788
|
labelText={t('selectAppointmentStatus', 'Select status')}
|
|
778
789
|
onChange={onChange}
|
|
779
790
|
value={value}
|
|
@@ -826,16 +837,16 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
826
837
|
<Controller
|
|
827
838
|
name="dateAppointmentScheduled"
|
|
828
839
|
control={control}
|
|
829
|
-
render={({ field: { onChange, value, ref }
|
|
840
|
+
render={({ field: { onChange, value, ref } }) => (
|
|
830
841
|
<div style={{ width: '100%' }}>
|
|
831
842
|
<DatePicker
|
|
832
843
|
datePickerType="single"
|
|
833
844
|
dateFormat={datePickerFormat}
|
|
834
|
-
|
|
845
|
+
invalid={!!errors?.dateAppointmentScheduled}
|
|
846
|
+
invalidText={errors?.dateAppointmentScheduled?.message}
|
|
835
847
|
maxDate={new Date().toISOString()}
|
|
836
848
|
onChange={([date]) => onChange(date)}
|
|
837
|
-
|
|
838
|
-
invalidText={fieldState?.error?.message}>
|
|
849
|
+
value={value}>
|
|
839
850
|
<DatePickerInput
|
|
840
851
|
id="dateAppointmentScheduledPickerInput"
|
|
841
852
|
labelText={t('dateScheduledDetail', 'Date appointment issued')}
|
|
@@ -844,7 +855,6 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
844
855
|
ref={ref}
|
|
845
856
|
/>
|
|
846
857
|
</DatePicker>
|
|
847
|
-
{fieldState?.error?.message && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
|
|
848
858
|
</div>
|
|
849
859
|
)}
|
|
850
860
|
/>
|
|
@@ -884,7 +894,7 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
|
|
|
884
894
|
);
|
|
885
895
|
};
|
|
886
896
|
|
|
887
|
-
function TimeAndDuration({
|
|
897
|
+
function TimeAndDuration({ t, watch, control, services, errors }) {
|
|
888
898
|
const defaultDuration = services?.find((service) => service.name === watch('selectedService'))?.durationMins || null;
|
|
889
899
|
|
|
890
900
|
return (
|
|
@@ -897,12 +907,14 @@ function TimeAndDuration({ isTablet, t, watch, control, services }) {
|
|
|
897
907
|
<TimePicker
|
|
898
908
|
id="time-picker"
|
|
899
909
|
pattern={time12HourFormatRegexPattern}
|
|
900
|
-
invalid={
|
|
901
|
-
invalidText={
|
|
902
|
-
|
|
903
|
-
|
|
910
|
+
invalid={!!errors?.startTime}
|
|
911
|
+
invalidText={errors?.startTime?.message}
|
|
912
|
+
labelText={t('time', 'Time')}
|
|
913
|
+
onChange={(event) => {
|
|
914
|
+
onChange(event.target.value);
|
|
915
|
+
}}
|
|
904
916
|
style={{ marginLeft: '0.125rem', flex: 'none' }}
|
|
905
|
-
|
|
917
|
+
value={value}>
|
|
906
918
|
<Controller
|
|
907
919
|
name="timeFormat"
|
|
908
920
|
control={control}
|
|
@@ -925,22 +937,21 @@ function TimeAndDuration({ isTablet, t, watch, control, services }) {
|
|
|
925
937
|
<Controller
|
|
926
938
|
name="duration"
|
|
927
939
|
control={control}
|
|
928
|
-
|
|
929
|
-
render={({ field: { onChange, onBlur, value, ref }, fieldState }) => (
|
|
940
|
+
render={({ field: { onChange, onBlur, value, ref } }) => (
|
|
930
941
|
<NumberInput
|
|
931
|
-
hideSteppers
|
|
932
942
|
disableWheel
|
|
943
|
+
hideSteppers
|
|
933
944
|
id="duration"
|
|
934
|
-
|
|
935
|
-
|
|
945
|
+
invalid={!!errors?.duration}
|
|
946
|
+
invalidText={errors?.duration?.message}
|
|
936
947
|
label={t('durationInMinutes', 'Duration (minutes)')}
|
|
937
|
-
|
|
938
|
-
|
|
948
|
+
max={1440}
|
|
949
|
+
min={0}
|
|
939
950
|
onBlur={onBlur}
|
|
940
951
|
onChange={(event) => onChange(Number(event.target.value))}
|
|
941
|
-
value={value}
|
|
942
952
|
ref={ref}
|
|
943
|
-
|
|
953
|
+
size="md"
|
|
954
|
+
value={value}
|
|
944
955
|
/>
|
|
945
956
|
)}
|
|
946
957
|
/>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
1
2
|
import dayjs from 'dayjs';
|
|
3
|
+
import isToday from 'dayjs/plugin/isToday';
|
|
2
4
|
import useSWR, { useSWRConfig } from 'swr';
|
|
3
5
|
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
4
6
|
import {
|
|
@@ -7,12 +9,10 @@ import {
|
|
|
7
9
|
type AppointmentsFetchResponse,
|
|
8
10
|
type RecurringAppointmentsPayload,
|
|
9
11
|
} from '../types';
|
|
10
|
-
import isToday from 'dayjs/plugin/isToday';
|
|
11
|
-
import { useCallback } from 'react';
|
|
12
12
|
dayjs.extend(isToday);
|
|
13
13
|
|
|
14
|
-
const appointmentUrlMatcher =
|
|
15
|
-
const appointmentsSearchUrl =
|
|
14
|
+
const appointmentUrlMatcher = `${restBaseUrl}/appointment`;
|
|
15
|
+
const appointmentsSearchUrl = `${restBaseUrl}/appointments/search`;
|
|
16
16
|
|
|
17
17
|
export function useMutateAppointments() {
|
|
18
18
|
const { mutate } = useSWRConfig();
|