diff --git a/src/applications/mhv-medical-records/actions/downloads.js b/src/applications/mhv-medical-records/actions/downloads.js
new file mode 100644
index 000000000000..69c791bbb1af
--- /dev/null
+++ b/src/applications/mhv-medical-records/actions/downloads.js
@@ -0,0 +1,15 @@
+import { Actions } from '../util/actionTypes';
+
+export const updateReportDateRange = (fromDate, toDate) => async dispatch => {
+ dispatch({
+ type: Actions.Downloads.SET_DATE_FILTER,
+ response: `${fromDate}<->${toDate}`,
+ });
+};
+
+export const updateReportRecordType = selectedTypes => async dispatch => {
+ dispatch({
+ type: Actions.Downloads.SET_RECORD_FILTER,
+ response: selectedTypes,
+ });
+};
diff --git a/src/applications/mhv-medical-records/components/DownloadRecords/DowloadDateRange.jsx b/src/applications/mhv-medical-records/components/DownloadRecords/DowloadDateRange.jsx
index 27233f70c9a6..ea44d3691e3a 100644
--- a/src/applications/mhv-medical-records/components/DownloadRecords/DowloadDateRange.jsx
+++ b/src/applications/mhv-medical-records/components/DownloadRecords/DowloadDateRange.jsx
@@ -3,13 +3,22 @@ import {
VaDate,
VaSelect,
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useState, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
+import { useDispatch } from 'react-redux';
+import { subMonths, format } from 'date-fns';
import NeedHelpSection from './NeedHelpSection';
+import { updateReportDateRange } from '../../actions/downloads';
const DownloadDateRange = () => {
const history = useHistory();
const [selectedDate, setSelectedDate] = useState('');
+ const [selectionError, setSelectionError] = useState(null);
+ const [customFromDate, setCustomFromDate] = useState('');
+ const [customToDate, setCustomToDate] = useState('');
+ const [customToError, setCustomToError] = useState(null);
+ const [customFromError, setCustomFromError] = useState(null);
+ const dispatch = useDispatch();
const handleDateSelect = useCallback(
e => {
@@ -18,11 +27,30 @@ const DownloadDateRange = () => {
return;
}
+ setSelectionError(null);
setSelectedDate(e.detail.value);
+ if (e.detail.value !== 'custom') {
+ const currentDate = new Date();
+ dispatch(
+ updateReportDateRange(
+ format(subMonths(currentDate, e.detail.value), 'yyyy-MM-dd'),
+ format(currentDate, 'yyyy-MM-dd'),
+ ),
+ );
+ }
},
[setSelectedDate],
);
+ useEffect(
+ () => {
+ if (customFromDate !== '' && customToDate !== '') {
+ dispatch(updateReportDateRange(customFromDate, customToDate));
+ }
+ },
+ [customFromDate, customToDate],
+ );
+
return (
Select records and download report
@@ -39,17 +67,44 @@ const DownloadDateRange = () => {
Select date range
-
-
-
-
+
+
+
+
{selectedDate === 'custom' && (
-
-
+ {
+ const [year, month, day] = e.target.value.split('-');
+ if (parseInt(year, 10) >= 1900 && month && day) {
+ setCustomFromError(null);
+ setCustomFromDate(e.target.value);
+ }
+ }}
+ />
+ {
+ const [year, month, day] = e.target.value.split('-');
+ if (parseInt(year, 10) >= 1900 && month && day) {
+ setCustomToError(null);
+ setCustomToDate(e.target.value);
+ }
+ }}
+ />
)}
{
history.push('/download');
}}
onPrimaryClick={() => {
+ if (selectedDate === '') {
+ setSelectionError('Please select a valid date range.');
+ return;
+ }
+ if (selectedDate === 'custom') {
+ if (customFromDate === '') {
+ setCustomFromError('Please enter a valid start date.');
+ return;
+ }
+ if (customToDate === '') {
+ setCustomToError('Please enter a valid end date.');
+ return;
+ }
+ }
history.push('/download/record-type');
}}
/>
diff --git a/src/applications/mhv-medical-records/components/DownloadRecords/DownloadFileType.jsx b/src/applications/mhv-medical-records/components/DownloadRecords/DownloadFileType.jsx
index 8a1ed4e7acd1..58a47c85e5fd 100644
--- a/src/applications/mhv-medical-records/components/DownloadRecords/DownloadFileType.jsx
+++ b/src/applications/mhv-medical-records/components/DownloadRecords/DownloadFileType.jsx
@@ -1,93 +1,298 @@
-import React, { useState } from 'react';
-import { useSelector } from 'react-redux';
+import React, { useState, useCallback, useEffect, useMemo } from 'react';
import { useHistory } from 'react-router-dom';
+import { useDispatch, useSelector } from 'react-redux';
+import PropTypes from 'prop-types';
+import { formatDateLong } from '@department-of-veterans-affairs/platform-utilities/exports';
import {
generatePdfScaffold,
- crisisLineHeader,
- reportGeneratedBy,
- txtLine,
+ formatName,
} from '@department-of-veterans-affairs/mhv/exports';
-import { formatDateLong } from '@department-of-veterans-affairs/platform-utilities/exports';
-import PropTypes from 'prop-types';
+import { VaRadio } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
+import { isBefore, isAfter } from 'date-fns';
import NeedHelpSection from './NeedHelpSection';
import DownloadingRecordsInfo from '../shared/DownloadingRecordsInfo';
+import DownloadSuccessAlert from '../shared/DownloadSuccessAlert';
import {
getNameDateAndTime,
makePdf,
- processList,
- getLastUpdatedText,
generateTextFile,
- formatNameFirstLast,
} from '../../util/helpers';
-import DownloadSuccessAlert from '../shared/DownloadSuccessAlert';
-import { refreshExtractTypes } from '../../util/constants';
-import {
- generateDownloadIntro,
- generateDownloadContent,
-} from '../../util/pdfHelpers/download';
+import { getTxtContent } from '../../util/txtHelpers/blueButton';
+import { getBlueButtonReportData } from '../../actions/blueButtonReport';
+import { generateBlueButtonData } from '../../util/pdfHelpers/blueButton';
+import { clearAlerts } from '../../actions/alerts';
const DownloadFileType = props => {
+ const { runningUnitTest = false } = props;
const history = useHistory();
- const { runningUnitTest } = props;
+ const [fileType, setFileType] = useState('');
+
+ const dispatch = useDispatch();
const user = useSelector(state => state.user.profile);
- const download = useSelector(state => state.mr.download.downloadList);
- const refresh = useSelector(state => state.mr.refresh);
- const [downloadStarted, setDownloadStarted] = useState(false);
- const [fileType, setFileType] = useState(null);
+ const name = formatName(user.userFullName);
+ const dob = formatDateLong(user.dob);
+ const [blueButtonRequested, setBlueButtonRequested] = useState(false);
+ const [downloadType, setDownloadType] = useState('');
- const lastUpdatedText = getLastUpdatedText(
- refresh.status,
- refreshExtractTypes.VPR,
+ const labsAndTests = useSelector(
+ state => state.mr.labsAndTests.labsAndTestsList,
+ );
+ const notes = useSelector(
+ state => state.mr.careSummariesAndNotes.careSummariesAndNotesList,
+ );
+ const vaccines = useSelector(state => state.mr.vaccines.vaccinesList);
+ const allergies = useSelector(state => state.mr.allergies.allergiesList);
+ const conditions = useSelector(state => state.mr.conditions.conditionsList);
+ const vitals = useSelector(state => state.mr.vitals.vitalsList);
+ const medications = useSelector(state => state.mr.blueButton.medicationsList);
+ const appointments = useSelector(
+ state => state.mr.blueButton.appointmentsList,
+ );
+ const demographics = useSelector(state => state.mr.blueButton.demographics);
+ const militaryService = useSelector(
+ state => state.mr.blueButton.militaryService,
);
+ const accountSummary = useSelector(
+ state => state.mr.blueButton.accountSummary,
+ );
+
+ const recordFilter = useSelector(state => state.mr.downloads?.recordFilter);
+ const dateFilter = useSelector(state => state.mr.downloads?.dateFilter);
+
+ const [downloadStarted, setDownloadStarted] = useState(false);
- const generateDownloadPdf = async () => {
- setDownloadStarted(true);
- const { title, subject, preface } = generateDownloadIntro(
- download,
- lastUpdatedText,
+ const allAreDefined = arrayOfArrays => {
+ return arrayOfArrays.every(
+ data =>
+ (typeof data === 'object' && Object.keys(data)?.length) ||
+ (typeof data === 'string' && data?.length) ||
+ (Array.isArray(data) && !!data?.length),
);
- const scaffold = generatePdfScaffold(user, title, subject, preface);
- const pdfData = { ...scaffold, ...generateDownloadContent(download) };
- const pdfName = `VA-Download-list-${getNameDateAndTime(user)}`;
- makePdf(pdfName, pdfData, 'Download', runningUnitTest);
};
- const generateDownloadListItemTxt = item => {
- setDownloadStarted(true);
- return `
-${txtLine}\n\n
-${item.name}\n
-Date received: ${item.date}\n
-Location: ${item.location}\n
-Reaction: ${processList(item.reactions)}\n`;
- };
+ useEffect(() => {
+ if (!dateFilter) {
+ history.push('/download/date-range');
+ } else if (!recordFilter) {
+ history.push('/download/record-type');
+ }
+ });
+
+ const [filterFromDate, filterToDate] = useMemo(
+ () => {
+ return dateFilter ? dateFilter.split('<->') : [null, null];
+ },
+ [dateFilter],
+ );
- const generateDownloadTxt = async () => {
- const content = `
-${crisisLineHeader}\n\n
-Download\n
-${formatNameFirstLast(user.userFullName)}\n
-Date of birth: ${formatDateLong(user.dob)}\n
-${reportGeneratedBy}\n
-This list includes download you got at VA health facilities and from providers or pharmacies in our community care network. It may not include vaccines you got outside our network.\n
-For complete records of your allergies and reactions to vaccines, review your allergy records.\n
-Showing ${download.length} records from newest to oldest
-${download.map(entry => generateDownloadListItemTxt(entry)).join('')}`;
-
- const fileName = `VA-download-list-${getNameDateAndTime(user)}`;
-
- generateTextFile(content, fileName);
+ const filterByDate = recDate => {
+ return (
+ isBefore(new Date(filterFromDate), new Date(recDate)) &&
+ isAfter(new Date(filterToDate), new Date(recDate))
+ );
};
- const handleDownload = () => {
- if (fileType === 'pdf') {
- // Create and generate the PDF
- generateDownloadPdf();
- } else if (fileType === 'txt') {
- // Create and download a text file
- generateDownloadTxt();
+ const recordData = useMemo(() => {
+ if (
+ !allAreDefined([
+ labsAndTests,
+ notes,
+ vaccines,
+ allergies,
+ conditions,
+ vitals,
+ ])
+ ) {
+ dispatch(getBlueButtonReportData());
+ } else {
+ return {
+ labsAndTests: recordFilter?.includes('labTests')
+ ? labsAndTests.filter(rec => filterByDate(rec.sortDate))
+ : null,
+ notes: recordFilter?.includes('careSummaries')
+ ? notes.filter(rec => filterByDate(rec.sortByDate))
+ : null,
+ vaccines: recordFilter?.includes('vaccines')
+ ? vaccines.filter(rec => filterByDate(rec.date))
+ : null,
+ allergies:
+ recordFilter?.includes('allergies') ||
+ recordFilter?.includes('medications')
+ ? allergies
+ : null,
+ conditions: recordFilter?.includes('conditions') ? conditions : null,
+ vitals: recordFilter?.includes('vitals')
+ ? vitals.filter(rec => filterByDate(rec.date))
+ : null,
+ medications: recordFilter?.includes('medications')
+ ? medications.filter(rec => filterByDate(rec.lastFilledOn))
+ : null,
+ appointments:
+ recordFilter?.includes('upcomingAppts') ||
+ recordFilter?.includes('pastAppts')
+ ? appointments.filter(
+ rec =>
+ filterByDate(rec.date) &&
+ ((recordFilter.includes('upcomingAppts') && rec.isUpcoming) ||
+ (recordFilter.includes('pastAppts') && !rec.isUpcoming)),
+ )
+ : null,
+ demographics: recordFilter?.includes('demographics')
+ ? demographics
+ : null,
+ militaryService: recordFilter?.includes('militaryService')
+ ? militaryService
+ : null,
+ accountSummary,
+ };
}
- };
+ return {};
+ });
+
+ const recordCount = useMemo(() => {
+ let count = 0;
+ count += recordData?.labsAndTests ? recordData?.labsAndTests?.length : 0;
+ count += recordData?.notes ? recordData?.notes?.length : 0;
+ count += recordData?.vaccines ? recordData?.vaccines?.length : 0;
+ count += recordData?.allergies ? recordData?.allergies?.length : 0;
+ count += recordData?.conditions ? recordData?.conditions?.length : 0;
+ count += recordData?.vitals ? recordData?.vitals?.length : 0;
+ count += recordData?.medications ? recordData?.medications?.length : 0;
+ count += recordData?.appointments ? recordData?.appointments?.length : 0;
+ count += recordData?.demographics ? 1 : 0;
+ count += recordData?.militaryService ? 1 : 0;
+
+ return count;
+ });
+
+ const generatePdf = useCallback(
+ async () => {
+ setDownloadStarted(true);
+ setDownloadType('pdf');
+ setBlueButtonRequested(true);
+ dispatch(clearAlerts());
+ const allDefd = allAreDefined([
+ labsAndTests,
+ notes,
+ vaccines,
+ allergies,
+ conditions,
+ vitals,
+ medications,
+ appointments,
+ demographics,
+ militaryService,
+ accountSummary,
+ ]);
+ if (!allDefd) {
+ dispatch(getBlueButtonReportData());
+ } else {
+ setBlueButtonRequested(false);
+ const title = 'Blue Button report';
+ const subject = 'VA Medical Record';
+ const scaffold = generatePdfScaffold(user, title, subject);
+ const pdfName = `VA-Blue-Button-report-${getNameDateAndTime(user)}`;
+ const pdfData = {
+ recordSets: generateBlueButtonData(recordData),
+ ...scaffold,
+ name,
+ dob,
+ };
+ makePdf(pdfName, pdfData, title, runningUnitTest, 'blueButtonReport');
+ }
+ },
+ [
+ accountSummary,
+ allergies,
+ appointments,
+ conditions,
+ demographics,
+ dispatch,
+ dob,
+ labsAndTests,
+ medications,
+ militaryService,
+ name,
+ notes,
+ user,
+ vaccines,
+ vitals,
+ ],
+ );
+
+ /**
+ * Generate text function
+ */
+ const generateTxt = useCallback(
+ async () => {
+ setDownloadStarted(true);
+ setDownloadType('txt');
+ setBlueButtonRequested(true);
+ dispatch(clearAlerts());
+ if (
+ !allAreDefined([
+ labsAndTests,
+ notes,
+ vaccines,
+ allergies,
+ conditions,
+ vitals,
+ ])
+ ) {
+ dispatch(getBlueButtonReportData());
+ } else {
+ setBlueButtonRequested(false);
+ const pdfName = `VA-Blue-Button-report-${getNameDateAndTime(user)}`;
+ const content = getTxtContent(recordData, user);
+
+ generateTextFile(content, pdfName, user);
+ }
+ },
+ [
+ allergies,
+ conditions,
+ dispatch,
+ labsAndTests,
+ notes,
+ user,
+ vaccines,
+ vitals,
+ ],
+ );
+
+ useEffect(
+ () => {
+ if (
+ allAreDefined([
+ labsAndTests,
+ notes,
+ vaccines,
+ allergies,
+ conditions,
+ vitals,
+ ]) &&
+ blueButtonRequested
+ ) {
+ if (downloadType === 'pdf') {
+ generatePdf();
+ } else {
+ generateTxt();
+ }
+ }
+ },
+ [
+ labsAndTests,
+ notes,
+ vaccines,
+ allergies,
+ conditions,
+ vitals,
+ generatePdf,
+ generateTxt,
+ downloadType,
+ blueButtonRequested,
+ ],
+ );
return (
@@ -102,16 +307,16 @@ ${download.map(entry => generateDownloadListItemTxt(entry)).join('')}`;
Select file type
- You’re downloading 2,782 total records
+ You’re downloading {recordCount} total records
-
setFileType(event.detail.value)}
+ onVaValueChange={e => setFileType(e.detail.value)}
>
-
+
{downloadStarted &&
}
@@ -119,7 +324,7 @@ ${download.map(entry => generateDownloadListItemTxt(entry)).join('')}`;