diff --git a/src/applications/vaos/components/calendar/CalendarWidget.jsx b/src/applications/vaos/components/calendar/CalendarWidget.jsx index 045f9e162a91..14b34a77ba96 100644 --- a/src/applications/vaos/components/calendar/CalendarWidget.jsx +++ b/src/applications/vaos/components/calendar/CalendarWidget.jsx @@ -46,16 +46,15 @@ function getFirstDayOfMonth(momentDate) { * @param {string} maxDate YYYY-DD-MM * @returns {string} YYYY-MM */ -export function getMaxMonth(maxDate) { +export function getMaxMonth(maxDate, overrideMaxDays) { const defaultMaxMonth = moment() .add(DEFAULT_MAX_DAYS_AHEAD, 'days') .format('YYYY-MM'); const maxMonth = moment(maxDate).startOf('month'); - if (maxDate && maxMonth.isAfter(defaultMaxMonth)) { + if (maxDate && (maxMonth.isAfter(defaultMaxMonth) || overrideMaxDays)) { return maxMonth.format('YYYY-MM'); } - // If no available dates array provided, set max to default from now return defaultMaxMonth; } @@ -235,6 +234,7 @@ function handleNext(onClickNext, months, setMonths) { * @param {string} props.timezone America/Denver * @param {Array} props.value * @param {boolean} [props.showWeekends=false] Whether to show full weekend slots or not + * @param {boolean} [props.overrideMaxDays=false] Disables the default max days value * @returns {JSX.Element} props.Calendar Calendar Widget */ function CalendarWidget({ @@ -249,6 +249,7 @@ function CalendarWidget({ onChange, onNextMonth, onPreviousMonth, + overrideMaxDays = false, renderOptions, renderIndicator, renderSelectedLabel, @@ -268,7 +269,7 @@ function CalendarWidget({ return null; }); const currentDate = moment(); - const maxMonth = getMaxMonth(maxDate); + const maxMonth = getMaxMonth(maxDate, overrideMaxDays); const [months, setMonths] = useState([moment(startMonth || minDate)]); const exceededMaximumSelections = value.length > maxSelections; const hasError = (required && showValidation) || exceededMaximumSelections; @@ -390,6 +391,7 @@ function CalendarWidget({ } CalendarWidget.propTypes = { + id: PropTypes.string.isRequired, availableSlots: PropTypes.arrayOf( PropTypes.shape({ start: PropTypes.string.isRequired, @@ -398,22 +400,24 @@ CalendarWidget.propTypes = { ), disabled: PropTypes.bool, disabledMessage: PropTypes.object, - minDate: PropTypes.string, maxDate: PropTypes.string, maxSelections: PropTypes.number, maxSelectionsError: PropTypes.string, - startMonth: PropTypes.string, - onChange: PropTypes.func, - onNextMonth: PropTypes.func, - onPreviousMonth: PropTypes.func, + minDate: PropTypes.string, + overrideMaxDays: PropTypes.bool, renderIndicator: PropTypes.func, renderOptions: PropTypes.func, + renderSelectedLabel: PropTypes.func, required: PropTypes.bool, requiredMessage: PropTypes.string, showValidation: PropTypes.bool, - id: PropTypes.string.isRequired, + showWeekends: PropTypes.bool, + startMonth: PropTypes.string, timezone: PropTypes.string, value: PropTypes.array, + onChange: PropTypes.func, + onNextMonth: PropTypes.func, + onPreviousMonth: PropTypes.func, }; export default CalendarWidget; diff --git a/src/applications/vaos/new-appointment/redux/selectors.js b/src/applications/vaos/new-appointment/redux/selectors.js index 8d99553afbb3..85d51fbd42f5 100644 --- a/src/applications/vaos/new-appointment/redux/selectors.js +++ b/src/applications/vaos/new-appointment/redux/selectors.js @@ -400,3 +400,9 @@ export function selectFacilitiesRadioWidget(state) { export function selectAppointmentSlotsStatus(state) { return getNewAppointment(state).appointmentSlotsStatus; } + +export function getSelectedDate(state) { + return getFormData(state).selectedDates?.length + ? getFormData(state).selectedDates[0] + : ''; +} diff --git a/src/applications/vaos/referral-appointments/ChooseCommunityCare.jsx b/src/applications/vaos/referral-appointments/ChooseCommunityCare.jsx index 4ea2e9b62880..7e82ff0c62aa 100644 --- a/src/applications/vaos/referral-appointments/ChooseCommunityCare.jsx +++ b/src/applications/vaos/referral-appointments/ChooseCommunityCare.jsx @@ -118,6 +118,7 @@ export default function ChooseCommunityCare() { aria-label={provider.reviewText} text={provider.reviewText} data-testid="review-available-appointments-link" + href="provider-choose-date-and-time" />
diff --git a/src/applications/vaos/referral-appointments/ChooseDateAndTime.jsx b/src/applications/vaos/referral-appointments/ChooseDateAndTime.jsx index 92920a6dd6a7..144ff2086c9d 100644 --- a/src/applications/vaos/referral-appointments/ChooseDateAndTime.jsx +++ b/src/applications/vaos/referral-appointments/ChooseDateAndTime.jsx @@ -1,86 +1,163 @@ -import React, { useState } from 'react'; -import moment from 'moment'; +import React, { useCallback, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { startOfMonth, format } from 'date-fns'; +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 { useDispatch } from 'react-redux'; +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'; export const ChooseDateAndTime = () => { - // const dispatch = useDispatch(); - const availableSlots = [ - { - end: '2024-07-02T17:00:00Z', - id: '32303', - start: '2024-07-01T10:00:00', - }, - { - end: '2024-07-02T18:00:00Z', - id: '23555', - start: '2024-07-02T11:00:00', - }, - ]; - const selectedDates = ['2024-07-02T11:00:00']; - const timezone = 'America/Denver'; - const preferredDate = '2024-07-02'; - const startMonth = preferredDate - ? moment(preferredDate).format('YYYY-MM') - : null; + const history = useHistory(); + const selectedDates = useSelector(state => getSelectedDate(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 latestAvailableSlot = new Date( + Math.max.apply( + null, + referral.slots.map(slot => { + return new Date(slot.start); + }), + ), + ); + const fullAddress = addressObject => { + let addressString = addressObject.street1; + if (addressObject.street2) { + addressString = `${addressString}, ${addressObject.street2}`; + } + if (addressObject.street3) { + addressString = `${addressString}, ${addressObject.street3}`; + } + addressString = `${addressString}, ${addressObject.city}, ${ + addressObject.state + }, ${addressObject.zip}`; + return addressString; + }; + const onChange = useCallback( + value => { + dispatch(onCalendarChange(value)); + }, + [dispatch], + ); + const onSubmit = () => { + setSubmitted(true); + if (selectedDates) { + history.push('/confirm-approved'); + } + }; + const getTzName = name => { + return new Intl.DateTimeFormat('default', { + timeZone: referral.timezone, + timeZoneName: name, + }) + .formatToParts() + .find(({ type }) => type === 'timeZoneName').value; + }; + const tzLong = getTzName('longGeneric'); + const tzShort = getTzName('shortGeneric'); return ( - -
-

Choose a date and time

-

Physical Therapy

-

GLA Medical Canter - Southwest

- -

Physical Therapy of GLA

-

111 Medical Lane, Suite 300

-

Los Angeles, CA 12345

-

Phone: 555-555-5555

- -

7 minute drive (2 miles)

-
-
- - } - onChange={null} - onNextMonth={null} - onPreviousMonth={null} - minDate={moment() - .add(1, 'days') - .format('YYYY-MM-DD')} - maxDate={moment() - .add(395, 'days') - .format('YYYY-MM-DD')} - required - requiredMessage="Please choose your preferred date and time for your appointment" - startMonth={startMonth} - showValidation={submitted && !selectedDates?.length} - showWeekends + + <> +
+

{pageTitle}

+

+ {referral.providerName} +

+

{referral.typeOfCare}

+

+ {referral.orgName} +

+
+

+ {referral.orgAddress.street1}
+ {referral.orgAddress.street2 && ( + <> + {referral.orgAddress.street2} +
+ + )} + {referral.orgAddress.street3 && ( + <> + {referral.orgAddress.street3} +
+ + )} + {referral.orgAddress.city}, {referral.orgAddress.state},{' '} + {referral.orgAddress.zip} +

+ +
+

Phone: {referral.orgPhone}

+

+ {referral.driveTime} ({referral.driveDistance}) +

+

+ Please select an available date and time from the calendar below. + Appointment times are displayed in {`${tzLong} (${tzShort})`}. +

+
+
+ + } + onChange={onChange} + onNextMonth={null} + onPreviousMonth={null} + 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" + startMonth={startMonth} + showValidation={submitted && !selectedDates?.length} + showWeekends + overrideMaxDays + /> +
+ history.push('/choose-community-care-appointment')} + onSubmit={() => onSubmit()} + // pageChangeInProgress={pageChangeInProgress} + loadingText="Page change in progress" /> -
- {}} - onSubmit={() => setSubmitted(true)} - // pageChangeInProgress={pageChangeInProgress} - loadingText="Page change in progress" - /> +
); }; diff --git a/src/applications/vaos/referral-appointments/temp-data/referral.js b/src/applications/vaos/referral-appointments/temp-data/referral.js new file mode 100644 index 000000000000..afa65968dbfe --- /dev/null +++ b/src/applications/vaos/referral-appointments/temp-data/referral.js @@ -0,0 +1,39 @@ +/* eslint-disable no-plusplus */ +const dateFns = require('date-fns'); + +const getAvailableSlots = (number = 2) => { + const slots = []; + const tomorrow = dateFns.addDays(dateFns.startOfDay(new Date()), 1); + let hourFromNow = 12; + for (let i = 0; i < number; i++) { + const startTime = dateFns.addHours(tomorrow, hourFromNow); + slots.push({ + end: dateFns.addMinutes(startTime, 30).toISOString(), + id: Math.floor(Math.random() * 90000) + 10000, + start: startTime.toISOString(), + }); + hourFromNow++; + } + return slots; +}; +const referral = { + providerName: 'Dr. Face', + typeOfCare: 'Dermatology', + orgName: 'New Skin Technologies', + orgAddress: { + street1: '111 Lori Ln.', + street2: '', + street3: '', + city: 'New York', + state: 'New York', + zip: '10016', + }, + orgPhone: '555-867-5309', + driveTime: '7 minute drive', + driveDistance: '8 miles', + slots: getAvailableSlots(), + preferredDate: new Date(), + timezone: 'America/Denver', +}; + +module.exports = { getAvailableSlots, referral };