Skip to content

Commit

Permalink
(feat) O3-3404: Validate date appointment issued in the appointment…
Browse files Browse the repository at this point in the history
…s form (#1283)
  • Loading branch information
lucyjemutai authored Aug 26, 2024
1 parent fd9f27d commit 0d8c01e
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 32 deletions.
2 changes: 1 addition & 1 deletion e2e/core/test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { APIRequestContext, Page, test as base } from '@playwright/test';
import { type APIRequestContext, type Page, test as base } from '@playwright/test';
import { api } from '../fixtures';

// This file sets up our custom test harness using the custom fixtures.
Expand Down
3 changes: 3 additions & 0 deletions e2e/specs/appointments.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ test('Add, edit and cancel an appointment', async ({ page, api }) => {
await page.getByLabel('Duration (minutes)').fill('80');
});

await test.step('I set the Date appointment issued', async () => {
await page.getByLabel('Date appointment issued').fill('20/08/2024');
});
await test.step('And I change the note', async () => {
await page
.getByPlaceholder('Write any additional points here')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,25 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
},
{
path: ['appointmentDateTime.recurringPatternEndDate'],
message: 'A recurring appointment should have an end date',
message: t('recurringAppointmentShouldHaveEndDate', 'A recurring appointment should have an end date'),
},
);
)
.refine(
(formValues) => {
const appointmentDate = formValues.appointmentDateTime?.startDate;
const dateAppointmentScheduled = formValues.dateAppointmentScheduled;

if (!appointmentDate || !dateAppointmentScheduled) return true;
return dateAppointmentScheduled < appointmentDate;
},
{
path: ['dateAppointmentScheduled'],
message: t(
'dateAppointmentIssuedCannotBeAfterAppointmentDate',
'Date appointment issued cannot be after the appointment date',
),
},
);
type AppointmentFormData = z.infer<typeof appointmentsFormSchema>;

const defaultDateAppointmentScheduled = appointment?.dateAppointmentScheduled
Expand Down Expand Up @@ -468,33 +483,6 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
/>
</ResponsiveWrapper>
</section>
<section className={styles.formGroup}>
<span className={styles.heading}>{t('dateScheduled', 'Date appointment issued')}</span>
<ResponsiveWrapper>
<Controller
name="dateAppointmentScheduled"
control={control}
render={({ field: { onChange, value, ref }, fieldState }) => (
<DatePicker
datePickerType="single"
dateFormat={datePickerFormat}
value={value}
maxDate={new Date()}
onChange={([date]) => onChange(date)}
invalid={!!fieldState?.error?.message}
invalidText={fieldState?.error?.message}>
<DatePickerInput
id="dateAppointmentScheduledPickerInput"
labelText={t('dateScheduledDetail', 'Date appointment issued')}
style={{ width: '100%' }}
placeholder={datePickerPlaceHolder}
ref={ref}
/>
</DatePicker>
)}
/>
</ResponsiveWrapper>
</section>
<section className={styles.formGroup}>
<span className={styles.heading}>{t('service', 'Service')}</span>
<ResponsiveWrapper>
Expand Down Expand Up @@ -540,7 +528,6 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
/>
</ResponsiveWrapper>
</section>

<section className={styles.formGroup}>
<span className={styles.heading}>{t('appointmentType_title', 'Appointment Type')}</span>
<ResponsiveWrapper>
Expand Down Expand Up @@ -730,7 +717,7 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
<DatePicker
datePickerType="single"
dateFormat={datePickerFormat}
value={value.startDate}
value={value?.startDate}
onChange={([date]) => {
if (date) {
onChange({ ...value, startDate: date });
Expand Down Expand Up @@ -826,6 +813,36 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
/>
</ResponsiveWrapper>
</section>
<section className={styles.formGroup}>
<span className={styles.heading}>{t('dateScheduled', 'Date appointment issued')}</span>
<ResponsiveWrapper>
<Controller
name="dateAppointmentScheduled"
control={control}
render={({ field: { onChange, value, ref }, fieldState }) => (
<div style={{ width: '100%' }}>
<DatePicker
datePickerType="single"
dateFormat={datePickerFormat}
value={value}
maxDate={new Date()}
onChange={([date]) => onChange(date)}
invalid={!!fieldState?.error?.message}
invalidText={fieldState?.error?.message}>
<DatePickerInput
id="dateAppointmentScheduledPickerInput"
labelText={t('dateScheduledDetail', 'Date appointment issued')}
style={{ width: '100%' }}
placeholder={datePickerPlaceHolder}
ref={ref}
/>
</DatePicker>
{fieldState?.error?.message && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
</div>
)}
/>
</ResponsiveWrapper>
</section>

<section className={styles.formGroup}>
<span className={styles.heading}>{t('note', 'Note')}</span>
Expand Down
9 changes: 9 additions & 0 deletions packages/esm-appointments-app/src/form/appointments-form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,12 @@ $openmrs-background-grey: #ededed;
max-inline-size: fit-content;
padding-top: layout.$spacing-03;
}

.errorMessage {
color: red;
font-size: 0.75rem;
margin-top: 0.25rem;
word-wrap: break-word;
white-space: pre-wrap;
text-align: left;
}

0 comments on commit 0d8c01e

Please sign in to comment.