Skip to content

Commit

Permalink
Feature-mhv-medical-records-accelerated-vitals (#32794)
Browse files Browse the repository at this point in the history
* (mocks) added some mocks for vitals toggle

* Add feature flag for MHV accelerated delivery of vital signs

* (refactor) renamed allergies and added vitals toggle

* (refactor) moved landing page to using new hook and allow for independent toggle

* (test) added a test before doing the dev work to show vitals

* (feature) fixed gated logic for vitals

* (test) moved accelerated tests to own folder; added test for all domains enabled

* (feature) added using the oh param

* (tests) added tests gate disabled, added test for vitals list with some vital LH data

* fix login method

* Fix defaults

* Add datepicker to vitals page

* Add more vitals mocks and ability to filter by date

* Fix date range in getAcceleratedVitals and add validation for date updates in Vitals component

* Refactor vital types and display logic to handle multiple record types and improve no-records handling

* Add feature flag for accelerated delivery and update related logic in useAcceleratedData hook

* Fix missing record type names

* Fix linting issue

* (mocks) added some mocks and fixed date filter

* (feature) added constant for pain_severity

* (mocks) fixed test data

* (feature) added redirect)

* (bug) fixed the API call not using the latest date

* (mocks) fixed mocks?

* (bug) fixed the resize oberserver bug

* (fix) fixed the vitals from changing back

* (mock) added some more test data

* (feature) added the submit button and loading indicator

* (feature) hiding new record box

* (feature) adding viewing records message

* (mock) updated mock data

* (feature) updated to match design

* (feature) removed time from vital

* (e2e) added blood pressue e2e test

* (feautre) added default value to show on date rage

* (test) updated test ids to me more dynamic

* (test) added test for blood pressure and heart rate

* (test) updated test values

* (mock) user

* (mocks) updated time

* (test) fixed e2e tests

---------

Co-authored-by: Adrian Rollett <acrollet@gmail.com>
Co-authored-by: mdewey <1793923+mdewey@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 27, 2024
1 parent b61747b commit ea64469
Show file tree
Hide file tree
Showing 35 changed files with 12,475 additions and 796 deletions.
4 changes: 2 additions & 2 deletions src/applications/mhv-medical-records/actions/allergies.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import { addAlert } from './alerts';
import { dispatchDetails } from '../util/helpers';
import { getListWithRetry } from './common';

export const getAllergiesList = ({
export const getAllergiesList = (
isCurrent = false,
isAccelerating = false,
} = {}) => async dispatch => {
) => async dispatch => {
dispatch({
type: Actions.Allergies.UPDATE_LIST_STATE,
payload: Constants.loadStates.FETCHING,
Expand Down
15 changes: 12 additions & 3 deletions src/applications/mhv-medical-records/actions/vitals.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import { Actions } from '../util/actionTypes';
import { getVitalsList } from '../api/MrApi';
import { getVitalsList, getAcceleratedVitals } from '../api/MrApi';
import * as Constants from '../util/constants';
import { addAlert } from './alerts';
import { isArrayAndHasItems } from '../util/helpers';
import { getListWithRetry } from './common';

export const getVitals = (isCurrent = false) => async dispatch => {
export const getVitals = (
isCurrent = false,
isAccelerating = false,
vitalsDate = '',
) => async dispatch => {
dispatch({
type: Actions.Vitals.UPDATE_LIST_STATE,
payload: Constants.loadStates.FETCHING,
});
try {
const response = await getListWithRetry(dispatch, getVitalsList);
let response;
if (isAccelerating) {
response = await getAcceleratedVitals(vitalsDate);
} else {
response = await getListWithRetry(dispatch, getVitalsList);
}
dispatch({
type: Actions.Vitals.GET_LIST,
response,
Expand Down
11 changes: 11 additions & 0 deletions src/applications/mhv-medical-records/api/MrApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,17 @@ export const getVitalsList = () => {
});
};

export const getAcceleratedVitals = async vitalsDate => {
const from = `&from=${vitalsDate}`;
const to = `&to=${vitalsDate}`;
return apiRequest(
`${apiBasePath}/medical_records/vitals?use_oh_data_path=1${from}${to}`,
{
headers,
},
);
};

export const getConditions = async () => {
return apiRequest(`${apiBasePath}/medical_records/conditions`, {
headers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { getParamValue } from '../../util/helpers';
// This value dictates how many pages are displayed in a pagination component
const MAX_PAGE_LIST_LENGTH = 5;
const RecordList = props => {
const { records, type, perPage = 10, hidePagination } = props;
const { records, type, perPage = 10, hidePagination, domainOptions } = props;
const totalEntries = records?.length;

const history = useHistory();
Expand Down Expand Up @@ -53,7 +53,7 @@ const RecordList = props => {
setCurrentRecords(paginatedRecords.current[currentPage - 1]);
}
},
[records, perPage],
[records, perPage, currentPage],
);

useEffect(
Expand Down Expand Up @@ -88,7 +88,12 @@ const RecordList = props => {
<div className="no-print">
{currentRecords?.length > 0 &&
currentRecords.map((record, idx) => (
<RecordListItem key={idx} record={record} type={type} />
<RecordListItem
key={idx}
record={record}
type={type}
domainOptions={domainOptions}
/>
))}
</div>
<div className="print-only">
Expand Down Expand Up @@ -119,6 +124,7 @@ const RecordList = props => {
export default RecordList;

RecordList.propTypes = {
domainOptions: PropTypes.object,
hidePagination: PropTypes.bool,
perPage: PropTypes.number,
records: PropTypes.array,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { recordType } from '../../util/constants';
import AllergyListItem from './AllergyListItem';

const RecordListItem = props => {
const { record, type } = props;
const { record, type, domainOptions } = props;

switch (type) {
case recordType.LABS_AND_TESTS:
Expand All @@ -19,7 +19,7 @@ const RecordListItem = props => {
case recordType.VACCINES:
return <VaccinesListItem record={record} />;
case recordType.VITALS:
return <VitalListItem record={record} />;
return <VitalListItem record={record} options={domainOptions} />;
case recordType.HEALTH_CONDITIONS:
return <ConditionListItem record={record} />;
case recordType.ALLERGIES:
Expand All @@ -32,6 +32,7 @@ const RecordListItem = props => {
export default RecordListItem;

RecordListItem.propTypes = {
domainOptions: PropTypes.object,
record: PropTypes.object,
type: PropTypes.string,
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import _ from 'lodash';
import { vitalTypeDisplayNames } from '../../util/constants';
import { dateFormatWithoutTimezone } from '../../util/helpers';

const VitalListItem = props => {
const { record } = props;
const { record, options = {} } = props;
const { isAccelerating } = options;
const displayName = vitalTypeDisplayNames[record.type];

const updatedRecordType = useMemo(
Expand All @@ -20,21 +22,58 @@ const VitalListItem = props => {
[record.type],
);

const dataTestIds = useMemo(
() => {
if (isAccelerating) {
return {
displayName: `vital-${_.kebabCase(updatedRecordType)}-display-name`,
noRecordMessage: `vital-${_.kebabCase(
updatedRecordType,
)}-no-record-message`,
measurement: `vital-${_.kebabCase(updatedRecordType)}-measurement`,
date: `vital-${_.kebabCase(updatedRecordType)}-date`,
dateTimestamp: `vital-${_.kebabCase(
updatedRecordType,
)}-date-timestamp`,
reviewLink: `vital-${_.kebabCase(
updatedRecordType,
)}-review-over-time`,
};
}
return {
displayName: 'vital-li-display-name',
noRecordMessage: 'vital-li-no-record-message',
measurement: 'vital-li-measurement',
date: 'vital-li-date',
dateTimestamp: 'vital-li-date-timestamp',
reviewLink: 'vital-li-review-over-time',
};
},
[updatedRecordType, isAccelerating],
);

return (
<va-card
class="record-list-item vads-u-border--0 vads-u-padding-left--0 vads-u-padding-top--1 mobile-lg:vads-u-padding-top--2"
data-testid="record-list-item"
>
<h2
className="vads-u-font-size--h3 vads-u-line-height--4 vads-u-margin-top--0 vads-u-margin-bottom--1"
data-testid="vital-li-display-name"
data-testid={dataTestIds.displayName}
>
{displayName}
</h2>

{record.noRecords && (
<p className="vads-u-margin--0">
{`There are no ${displayName.toLowerCase()} results in your VA medical records.`}
<p
className="vads-u-margin--0"
data-testid={dataTestIds.noRecordMessage}
>
{`There are no ${displayName.toLowerCase()} results ${
isAccelerating
? `from the current time frame.`
: 'in your VA medical records.'
}`}
</p>
)}

Expand All @@ -47,24 +86,31 @@ const VitalListItem = props => {
<span
className="vads-u-display--inline"
data-dd-privacy="mask"
data-testid="vital-li-measurement"
data-testid={dataTestIds.measurement}
>
{record.measurement}
</span>
</div>
<div
className="vads-u-line-height--4 vads-u-margin-bottom--1"
data-dd-privacy="mask"
data-testid="vital-li-date"
data-testid={dataTestIds.date}
>
<span className="vads-u-font-weight--bold">Date: </span>
<span>{record.date}</span>
<span data-testid={dataTestIds.dateTimestamp}>
{isAccelerating
? dateFormatWithoutTimezone(
record.effectiveDateTime,
'MMMM d, yyyy',
)
: record.date}
</span>
</div>

<Link
to={`/vitals/${_.kebabCase(updatedRecordType)}-history`}
className="vads-u-line-height--4"
data-testid="vital-li-review-over-time"
data-testid={dataTestIds.reviewLink}
>
<strong>
Review your{' '}
Expand All @@ -90,5 +136,6 @@ const VitalListItem = props => {
export default VitalListItem;

VitalListItem.propTypes = {
options: PropTypes.object,
record: PropTypes.object,
};
15 changes: 9 additions & 6 deletions src/applications/mhv-medical-records/containers/Allergies.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,21 @@ const Allergies = props => {
);

const user = useSelector(state => state.user.profile);
const { isAccelerating } = useAcceleratedData();
const { isAcceleratingAllergies } = useAcceleratedData();

const activeAlert = useAlerts(dispatch);
const [downloadStarted, setDownloadStarted] = useState(false);

const dispatchAction = isCurrent => {
return getAllergiesList(isCurrent, isAcceleratingAllergies);
};

useListRefresh({
listState,
listCurrentAsOf: allergiesCurrentAsOf,
refreshStatus: refresh.status,
extractType: refreshExtractTypes.ALLERGY,
dispatchAction: isCurrent =>
getAllergiesList({ isCurrent, isAccelerating }),
dispatchAction,
dispatch,
});

Expand Down Expand Up @@ -120,15 +123,15 @@ const Allergies = props => {
const scaffold = generatePdfScaffold(user, title, value, subject, preface);
const pdfData = {
...scaffold,
...generateAllergiesContent(allergies, isAccelerating),
...generateAllergiesContent(allergies, isAcceleratingAllergies),
};
const pdfName = `VA-allergies-list-${getNameDateAndTime(user)}`;
makePdf(pdfName, pdfData, 'Allergies', runningUnitTest);
};

const generateAllergyListItemTxt = item => {
setDownloadStarted(true);
if (isAccelerating) {
if (isAcceleratingAllergies) {
return `
${txtLine}\n\n
${item.name}\n
Expand Down Expand Up @@ -214,7 +217,7 @@ ${allergies.map(entry => generateAllergyListItemTxt(entry)).join('')}`;
<RecordList
records={allergies?.map(allergy => ({
...allergy,
isOracleHealthData: isAccelerating,
isOracleHealthData: isAcceleratingAllergies,
}))}
type={recordType.ALLERGIES}
/>
Expand Down
20 changes: 14 additions & 6 deletions src/applications/mhv-medical-records/containers/AllergyDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const AllergyDetails = props => {

const { vamcEhrData } = useSelector(selectDrupalStaticData);

const { isAccelerating } = useAcceleratedData();
const { isAcceleratingAllergies } = useAcceleratedData();

const { allergyId } = useParams();
const activeAlert = useAlerts(dispatch);
Expand All @@ -66,19 +66,27 @@ const AllergyDetails = props => {
}
return {
...allergy,
isOracleHealthData: isAccelerating,
isOracleHealthData: isAcceleratingAllergies,
};
},
[allergy, isAccelerating],
[allergy, isAcceleratingAllergies],
);

useEffect(
() => {
if (allergyId && !vamcEhrData?.loading) {
dispatch(getAllergyDetails(allergyId, allergyList, isAccelerating));
dispatch(
getAllergyDetails(allergyId, allergyList, isAcceleratingAllergies),
);
}
},
[allergyId, allergyList, dispatch, isAccelerating, vamcEhrData?.loading],
[
allergyId,
allergyList,
dispatch,
isAcceleratingAllergies,
vamcEhrData?.loading,
],
);

useEffect(
Expand Down Expand Up @@ -120,7 +128,7 @@ const AllergyDetails = props => {
};

const generateAllergyTextContent = () => {
if (isAccelerating) {
if (isAcceleratingAllergies) {
return `
${crisisLineHeader}\n\n
${allergyData.name}\n
Expand Down
8 changes: 7 additions & 1 deletion src/applications/mhv-medical-records/containers/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,17 @@ const App = ({ children }) => {

useEffect(
() => {
if (!current) return;
if (!current) return () => {};
const resizeObserver = new ResizeObserver(() => {
setHeight(current.offsetHeight);
});
resizeObserver.observe(current);
return () => {
if (current) {
resizeObserver.unobserve(current);
}
resizeObserver.disconnect();
};
},
[current],
);
Expand Down
Loading

0 comments on commit ea64469

Please sign in to comment.