Skip to content

Commit

Permalink
Cc/95263/provider mock (#32994)
Browse files Browse the repository at this point in the history
* added provider generator util.

* added new mock for provider using generator.

* add test

* rename func and add tests.

* provider mock redux stuff

* return error rather than null

* added error provider for testing

* remove try/catch in service since error handing is occurring in other try/catch

* revert test data
  • Loading branch information
brianseek authored Nov 19, 2024
1 parent cf9b71c commit 63e075e
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 18 deletions.
78 changes: 60 additions & 18 deletions src/applications/vaos/referral-appointments/ChooseDateAndTime.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom';
import { startOfMonth, format, addMinutes, isWithinInterval } from 'date-fns';
import { zonedTimeToUtc } from 'date-fns-tz';
Expand All @@ -11,18 +11,21 @@ import { referral } from './temp-data/referral';
import { getSelectedDate } from '../new-appointment/redux/selectors';
import { selectUpcomingAppointments } from '../appointment-list/redux/selectors';
import { routeToNextReferralPage, routeToPreviousReferralPage } from './flow';
import { setFormCurrentPage } from './redux/actions';
import { selectCurrentPage } from './redux/selectors';
import { setFormCurrentPage, fetchProviderDetails } from './redux/actions';
import { selectCurrentPage, getProviderInfo } from './redux/selectors';
import { FETCH_STATUS } from '../utils/constants';
import { scrollAndFocus } from '../utils/scrollAndFocus';

export const ChooseDateAndTime = () => {
const dispatch = useDispatch();

const history = useHistory();
const selectedDate = useSelector(state => getSelectedDate(state));
const upcomingAppointments = useSelector(state =>
selectUpcomingAppointments(state),
);
const location = useLocation();
const currentPage = useSelector(selectCurrentPage);
const dispatch = useDispatch();
const startMonth = format(startOfMonth(referral.preferredDate), 'yyyy-MM');
const [error, setError] = useState('');
const pageTitle = 'Schedule an appointment with your provider';
Expand Down Expand Up @@ -55,6 +58,23 @@ export const ChooseDateAndTime = () => {
[dispatch],
);

const { provider, providerFetchStatus } = useSelector(
state => getProviderInfo(state),
shallowEqual,
);

useEffect(
() => {
if (providerFetchStatus === FETCH_STATUS.notStarted) {
dispatch(fetchProviderDetails(referral.provider));
} else if (providerFetchStatus === FETCH_STATUS.succeeded) {
scrollAndFocus('h1');
} else if (providerFetchStatus === FETCH_STATUS.failed) {
scrollAndFocus('h2');
}
},
[dispatch, providerFetchStatus],
);
useEffect(
() => {
dispatch(setFormCurrentPage('scheduleAppointment'));
Expand Down Expand Up @@ -142,6 +162,28 @@ export const ChooseDateAndTime = () => {
},
[hasConflict, selectedDate, upcomingAppointments],
);
if (
providerFetchStatus === FETCH_STATUS.loading ||
providerFetchStatus === FETCH_STATUS.notStarted
) {
return (
<div className="vads-u-margin-y--8">
<va-loading-indicator message="Loading available appointments times..." />
</div>
);
}

if (providerFetchStatus === FETCH_STATUS.failed) {
return (
<va-alert status="error">
<h2>"We’re sorry. We’ve run into a problem"</h2>
<p>
We’re having trouble getting your upcoming appointments. Please try
again later.
</p>
</va-alert>
);
}
return (
<FormLayout pageTitle={pageTitle}>
<>
Expand All @@ -152,29 +194,29 @@ export const ChooseDateAndTime = () => {
appointment online with this provider:
</p>
<p className="vads-u-font-weight--bold vads-u-margin--0">
{referral.providerName}
{provider.providerName}
</p>
<p className="vads-u-margin-top--0">{referral.typeOfCare}</p>
<p className="vads-u-margin--0 vads-u-font-weight--bold">
{referral.orgName}
{provider.orgName}
</p>
<address>
<p className="vads-u-margin--0">
{referral.orgAddress.street1} <br />
{referral.orgAddress.street2 && (
{provider.orgAddress.street1} <br />
{provider.orgAddress.street2 && (
<>
{referral.orgAddress.street2}
{provider.orgAddress.street2}
<br />
</>
)}
{referral.orgAddress.street3 && (
{provider.orgAddress.street3 && (
<>
{referral.orgAddress.street3}
{provider.orgAddress.street3}
<br />
</>
)}
{referral.orgAddress.city}, {referral.orgAddress.state},{' '}
{referral.orgAddress.zip}
{provider.orgAddress.city}, {provider.orgAddress.state},{' '}
{provider.orgAddress.zip}
</p>
<div
data-testid="directions-link-wrapper"
Expand All @@ -188,19 +230,19 @@ export const ChooseDateAndTime = () => {
<a
data-testid="directions-link"
href={`https://maps.google.com?addr=Current+Location&daddr=${fullAddress(
referral.orgAddress,
provider.orgAddress,
)}`}
aria-label={`directions to ${referral.orgName}`}
aria-label={`directions to ${provider.orgName}`}
target="_blank"
rel="noreferrer"
>
Directions
</a>
</div>
</address>
<p>Phone: {referral.orgPhone}</p>
<p>Phone: {provider.orgPhone}</p>
<p>
{referral.driveTime} ({referral.driveDistance})
{provider.driveTime} ({provider.driveDistance})
</p>
<h2>Choose a date and time</h2>
<p>
Expand All @@ -211,7 +253,7 @@ export const ChooseDateAndTime = () => {
<div>
<CalendarWidget
maxSelections={1}
availableSlots={referral.slots}
availableSlots={provider.slots}
value={[selectedDate]}
id="dateTime"
timezone={referral.timezone}
Expand Down
29 changes: 29 additions & 0 deletions src/applications/vaos/referral-appointments/redux/actions.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { captureError } from '../../utils/error';
import { getProviderById } from '../../services/referral';

export const SET_FACILITY = 'SET_FACILITY';
export const SET_APPOINTMENT_DETAILS = 'SET_APPOINTMENT_DETAILS';
export const SET_SORT_PROVIDER_BY = 'SET_SORT_PROVIDER_BY';
export const SET_SELECTED_PROVIDER = 'SET_SELECTED_PROVIDER';
export const SET_FORM_CURRENT_PAGE = 'SET_FORM_CURRENT_PAGE';
export const FETCH_PROVIDER_DETAILS = 'FETCH_PROVIDER_DETAILS';
export const FETCH_PROVIDER_DETAILS_SUCCEEDED =
'FETCH_PROVIDER_DETAILS_SUCCEEDED';
export const FETCH_PROVIDER_DETAILS_FAILED = 'FETCH_PROVIDER_DETAILS_FAILED';

export function setFacility(facility) {
return {
Expand Down Expand Up @@ -41,3 +48,25 @@ export function setFormCurrentPage(currentPage) {
payload: currentPage,
};
}

export function fetchProviderDetails(id) {
return async dispatch => {
try {
dispatch({
type: FETCH_PROVIDER_DETAILS,
});
const providerDetails = await getProviderById(id);

dispatch({
type: FETCH_PROVIDER_DETAILS_SUCCEEDED,
data: providerDetails,
});
return providerDetails;
} catch (error) {
dispatch({
type: FETCH_PROVIDER_DETAILS_FAILED,
});
return captureError(error);
}
};
}
21 changes: 21 additions & 0 deletions src/applications/vaos/referral-appointments/redux/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import {
SET_SORT_PROVIDER_BY,
SET_SELECTED_PROVIDER,
SET_FORM_CURRENT_PAGE,
FETCH_PROVIDER_DETAILS,
FETCH_PROVIDER_DETAILS_FAILED,
FETCH_PROVIDER_DETAILS_SUCCEEDED,
} from './actions';
import { FETCH_STATUS } from '../../utils/constants';

const initialState = {
facility: null,
sortProviderBy: '',
selectedProvider: '',
currentPage: null,
providerFetchStatus: FETCH_STATUS.notStarted,
};

function ccAppointmentReducer(state = initialState, action) {
Expand Down Expand Up @@ -41,6 +46,22 @@ function ccAppointmentReducer(state = initialState, action) {
...state,
currentPage: action.payload,
};
case FETCH_PROVIDER_DETAILS:
return {
...state,
providerFetchStatus: FETCH_STATUS.loading,
};
case FETCH_PROVIDER_DETAILS_SUCCEEDED:
return {
...state,
providerFetchStatus: FETCH_STATUS.succeeded,
selectedProvider: action.data,
};
case FETCH_PROVIDER_DETAILS_FAILED:
return {
...state,
providerFetchStatus: FETCH_STATUS.failed,
};
default:
return state;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@ export const selectCCAppointment = state => state.ccAppointment;
export const selectProvider = state => state.referral.selectedProvider;
export const selectProviderSortBy = state => state.referral.sortProviderBy;
export const selectCurrentPage = state => state.referral.currentPage;

export function getProviderInfo(state) {
return {
provider: state.referral.selectedProvider,
providerFetchStatus: state.referral.providerFetchStatus,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const getAvailableSlots = (number = 2) => {
const referral = {
id: 123456,
providerName: 'Dr. Face',
provider: '111',
typeOfCare: 'Dermatology',
appointmentCount: 2,
orgName: 'New Skin Technologies',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { addDays, startOfDay, addHours } from 'date-fns';
import { expect } from 'chai';

const providerUtil = require('../../utils/provider');

describe('VAOS provider generator', () => {
const tomorrow = addDays(startOfDay(new Date()), 1);
describe('createProviderDetails', () => {
const providerObjectTwoSlots = providerUtil.createProviderDetails(2);
const providerObjectNoSlots = providerUtil.createProviderDetails(0);
it('Creates a provider with specified number of slots', () => {
expect(providerObjectTwoSlots.slots.length).to.equal(2);
});
it('Creates slots for tomorrow an hour apart starting at 12', () => {
expect(providerObjectTwoSlots.slots[0].start).to.equal(
addHours(tomorrow, 12).toISOString(),
);
expect(providerObjectTwoSlots.slots[1].start).to.equal(
addHours(tomorrow, 13).toISOString(),
);
});
it('Creates empty slots array with 0', () => {
expect(providerObjectNoSlots.slots.length).to.equal(0);
});
});
});
43 changes: 43 additions & 0 deletions src/applications/vaos/referral-appointments/utils/provider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable no-plusplus */
const dateFns = require('date-fns');

/**
* Creates a provider object with a configurable number of slots an hour apart.
*
* @param {Number} numberOfSlots How many slots to create
* @returns {Object} Provider object
*/
const createProviderDetails = numberOfSlots => {
const slots = [];
const tomorrow = dateFns.addDays(dateFns.startOfDay(new Date()), 1);
let hourFromNow = 12;
for (let i = 0; i < numberOfSlots; 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 {
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,
location: 'New skin technologies bldg 2',
};
};

module.exports = { createProviderDetails };
8 changes: 8 additions & 0 deletions src/applications/vaos/services/mocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const providerOrgs = require('./epsApi/providerOrganizations.json');
const providerServices = require('./epsApi/providerServices.json');
const providerSlots = require('./epsApi/providerServicesSlots.json');
const referralUtils = require('../../referral-appointments/utils/referrals');
const providerUtils = require('../../referral-appointments/utils/provider');

// Returns the meta object without any backend service errors
const meta = require('./v2/meta.json');
Expand Down Expand Up @@ -667,6 +668,13 @@ const responses = {
data: getSlot.find(slot => slot?.id === req.params.slotId),
});
},
'GET /vaos/v2/epsApi/providerDetails/:providerId': (req, res) => {
// Provider 3 throws error
if (req.params.providerId === '3') {
return res.status(500).json({ error: true });
}
return res.json({ data: providerUtils.createProviderDetails(5) });
},
'GET /v0/user': {
data: {
attributes: {
Expand Down
10 changes: 10 additions & 0 deletions src/applications/vaos/services/referral/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,13 @@ export async function getPatientReferralById(referralId) {
return null;
}
}

export async function getProviderById(providerId) {
const response = await apiRequestWithUrl(
`/vaos/v2/epsApi/providerDetails/${providerId}`,
{
method: 'GET',
},
);
return response.data;
}

0 comments on commit 63e075e

Please sign in to comment.