Skip to content

Commit

Permalink
some content tweaks and added validation for existing upcoming appoin…
Browse files Browse the repository at this point in the history
…tments
  • Loading branch information
brianseek committed Oct 4, 2024
1 parent da33270 commit fc88255
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 13 deletions.
85 changes: 73 additions & 12 deletions src/applications/vaos/referral-appointments/ChooseDateAndTime.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { startOfMonth, format } from 'date-fns';
import { startOfMonth, format, addMinutes, isWithinInterval } from 'date-fns';
import { zonedTimeToUtc } from 'date-fns-tz';
import { useHistory } from 'react-router-dom';
import CalendarWidget from '../components/calendar/CalendarWidget';
import FormLayout from '../new-appointment/components/FormLayout';
import { onCalendarChange } from '../new-appointment/redux/actions';
import FormButtons from '../components/FormButtons';
import { referral } from './temp-data/referral';
import { getSelectedDate } from '../new-appointment/redux/selectors';
import { selectUpcomingAppointments } from '../appointment-list/redux/selectors';

export const ChooseDateAndTime = () => {
const history = useHistory();
const selectedDates = useSelector(state => getSelectedDate(state));
const selectedDate = useSelector(state => getSelectedDate(state));
const upcomingAppointments = useSelector(state =>
selectUpcomingAppointments(state),
);
const dispatch = useDispatch();
const startMonth = format(startOfMonth(referral.preferredDate), 'yyyy-MM');
const [submitted, setSubmitted] = useState(false);
const pageTitle = 'Choose a date and time';
const [error, setError] = useState('');
const pageTitle = 'Schedule an appointment with your provider';
const latestAvailableSlot = new Date(
Math.max.apply(
null,
Expand All @@ -39,14 +44,18 @@ export const ChooseDateAndTime = () => {
};
const onChange = useCallback(
value => {
setError('');
dispatch(onCalendarChange(value));
},
[dispatch],
);
const onSubmit = () => {
setSubmitted(true);
if (selectedDates) {
if (selectedDate && !error) {
history.push('/confirm-approved');
} else if (!selectedDate) {
setError(
'Please choose your preferred date and time for your appointment',
);
}
};
const getTzName = name => {
Expand All @@ -59,12 +68,63 @@ export const ChooseDateAndTime = () => {
};
const tzLong = getTzName('longGeneric');
const tzShort = getTzName('shortGeneric');
useEffect(
() => {
if (selectedDate && upcomingAppointments) {
const selectedMonth = format(new Date(selectedDate), 'yyyy-MM');
if (selectedMonth in upcomingAppointments) {
const selectedDay = format(new Date(selectedDate), 'dd');
const monthOfApts = upcomingAppointments[selectedMonth];
const daysWithApts = monthOfApts.map(apt => {
return format(new Date(apt.start), 'dd');
});
if (daysWithApts.includes(selectedDay)) {
const unavailableTimes = monthOfApts.map(upcomingAppointment => {
return {
start: zonedTimeToUtc(
new Date(upcomingAppointment.start),
upcomingAppointment.timezone,
),
end: zonedTimeToUtc(
addMinutes(
new Date(upcomingAppointment.start),
upcomingAppointment.minutesDuration,
),
upcomingAppointment.timezone,
),
};
});
unavailableTimes.forEach(range => {
if (
isWithinInterval(
zonedTimeToUtc(new Date(selectedDate), referral.timezone),
{
start: range.start,
end: range.end,
},
)
) {
setError(
'You already have an appointment at this time. Please select another day or time.',
);
}
});
}
}
}
},
[selectedDate, upcomingAppointments],
);
return (
<FormLayout pageTitle={pageTitle}>
<>
<div>
<h1>{pageTitle}</h1>
<p className="vads-u-font-weight--bold vads-u-font-size--lg vads-u-margin--0">
<p>
You or your referring VA facility selected to schedule an
appointment online with this provider:
</p>
<p className="vads-u-font-weight--bold vads-u-margin--0">
{referral.providerName}
</p>
<p className="vads-u-margin-top--0">{referral.typeOfCare}</p>
Expand Down Expand Up @@ -115,16 +175,17 @@ export const ChooseDateAndTime = () => {
<p>
{referral.driveTime} ({referral.driveDistance})
</p>
<h2>Choose a date and time</h2>
<p>
Please select an available date and time from the calendar below.
Select an available date and time from the calendar below.
Appointment times are displayed in {`${tzLong} (${tzShort})`}.
</p>
</div>
<div>
<CalendarWidget
maxSelections={1}
availableSlots={referral.slots}
value={[selectedDates]}
value={[selectedDate]}
id="dateTime"
timezone={referral.timezone}
additionalOptions={{
Expand All @@ -144,9 +205,9 @@ export const ChooseDateAndTime = () => {
minDate={format(new Date(), 'yyyy-MM-dd')}
maxDate={format(latestAvailableSlot, 'yyyy-MM-dd')}
required
requiredMessage="Please choose your preferred date and time for your appointment"
requiredMessage={error}
startMonth={startMonth}
showValidation={submitted && !selectedDates?.length}
showValidation={error.length > 0}
showWeekends
overrideMaxDays
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,9 @@ const referral = {
preferredDate: new Date(),
timezone: 'America/Denver',
};

referral.slots.push({
end: '2024-11-22T16:30:00.000Z',
id: 35145,
start: '2024-11-22T16:00:00.000Z',
});
module.exports = { getAvailableSlots, referral };
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { expect } from 'chai';
// import sinon from 'sinon';
import userEvent from '@testing-library/user-event';
import { createTestStore, renderWithStoreAndRouter } from '../mocks/setup';
import ChooseDateAndTime from '../../referral-appointments/ChooseDateAndTime';

// Tests skipped for now since there are issues with displaying TZ and redux/data in flux.
describe('VAOS referral-appointments', () => {
const store = createTestStore();
// it.skip('should store the selected date', async () => {
// const screen = renderWithStoreAndRouter(<ChooseDateAndTime />, {
// store,
// });
// });
it.skip('should validate on submit', async () => {
const screen = renderWithStoreAndRouter(<ChooseDateAndTime />, {
store,
});
const button = await screen.findByText(/^Continue/);

userEvent.click(button);
expect(
screen.findByText(
'Please choose your preferred date and time for your appointment',
),
).to.be.ok;
});
// it('should display the timezone in the correct format', async () => {

// });
});

0 comments on commit fc88255

Please sign in to comment.