diff --git a/src/applications/travel-pay/components/submit-flow/pages/IntroductionPage.jsx b/src/applications/travel-pay/components/submit-flow/pages/IntroductionPage.jsx
index 32fb43b9412f..1beebd92d8de 100644
--- a/src/applications/travel-pay/components/submit-flow/pages/IntroductionPage.jsx
+++ b/src/applications/travel-pay/components/submit-flow/pages/IntroductionPage.jsx
@@ -1,21 +1,100 @@
-import PropTypes from 'prop-types';
import React from 'react';
+import PropTypes from 'prop-types';
+
+import { HelpTextManage } from '../../HelpText';
+import { formatDateTime, getDaysLeft } from '../../../util/dates';
+
+const IntroductionPage = ({ appointment, onStart }) => {
+ const [formattedDate] = formatDateTime(appointment.vaos.apiData.start);
+ const daysLeft = getDaysLeft(appointment.vaos.apiData.start);
-const IntroductionPage = ({ onNext }) => {
return (
);
};
IntroductionPage.propTypes = {
- onNext: PropTypes.func,
+ appointment: PropTypes.object,
+ onStart: PropTypes.func,
};
export default IntroductionPage;
diff --git a/src/applications/travel-pay/components/submit-flow/pages/MileagePage.jsx b/src/applications/travel-pay/components/submit-flow/pages/MileagePage.jsx
index 470312acd8ab..bf35c01b0c99 100644
--- a/src/applications/travel-pay/components/submit-flow/pages/MileagePage.jsx
+++ b/src/applications/travel-pay/components/submit-flow/pages/MileagePage.jsx
@@ -1,7 +1,8 @@
import React from 'react';
-import { VaButtonPair } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import PropTypes from 'prop-types';
+import { VaButtonPair } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
+
const MileagePage = ({ handlers }) => {
return (
diff --git a/src/applications/travel-pay/components/submit-flow/pages/CantFilePage.jsx b/src/applications/travel-pay/components/submit-flow/pages/UnsupportedClaimTypePage.jsx
similarity index 63%
rename from src/applications/travel-pay/components/submit-flow/pages/CantFilePage.jsx
rename to src/applications/travel-pay/components/submit-flow/pages/UnsupportedClaimTypePage.jsx
index f73c2a49cbd0..5ff42a7a90b0 100644
--- a/src/applications/travel-pay/components/submit-flow/pages/CantFilePage.jsx
+++ b/src/applications/travel-pay/components/submit-flow/pages/UnsupportedClaimTypePage.jsx
@@ -1,10 +1,14 @@
-import PropTypes from 'prop-types';
import React from 'react';
+import PropTypes from 'prop-types';
-const CantFilePage = ({ pageIndex, setCantFile, setPageIndex }) => {
+const UnsupportedClaimTypePage = ({
+ pageIndex,
+ setIsUnsupportedClaimType,
+ setPageIndex,
+}) => {
const onBack = e => {
e.preventDefault();
- setCantFile(false);
+ setIsUnsupportedClaimType(false);
setPageIndex(pageIndex);
};
@@ -22,10 +26,10 @@ const CantFilePage = ({ pageIndex, setCantFile, setPageIndex }) => {
);
};
-CantFilePage.propTypes = {
+UnsupportedClaimTypePage.propTypes = {
pageIndex: PropTypes.number,
- setCantFile: PropTypes.func,
+ setIsUnsupportedClaimType: PropTypes.func,
setPageIndex: PropTypes.func,
};
-export default CantFilePage;
+export default UnsupportedClaimTypePage;
diff --git a/src/applications/travel-pay/components/submit-flow/pages/VehiclePage.jsx b/src/applications/travel-pay/components/submit-flow/pages/VehiclePage.jsx
index d097aab9ab4f..4d343d901ccf 100644
--- a/src/applications/travel-pay/components/submit-flow/pages/VehiclePage.jsx
+++ b/src/applications/travel-pay/components/submit-flow/pages/VehiclePage.jsx
@@ -1,7 +1,8 @@
import React from 'react';
-import { VaButtonPair } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import PropTypes from 'prop-types';
+import { VaButtonPair } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
+
const VehiclePage = ({ handlers }) => {
return (
diff --git a/src/applications/travel-pay/constants.js b/src/applications/travel-pay/constants.js
index 9ea53d560494..fd2eadec8c25 100644
--- a/src/applications/travel-pay/constants.js
+++ b/src/applications/travel-pay/constants.js
@@ -1,3 +1,8 @@
+export const BTSSS_PORTAL_URL = 'https://dvagov-btsss.dynamics365portals.us/';
+export const FORM_103542_LINK = '/find-forms/about-form-10-3542/';
+export const FIND_FACILITY_TP_CONTACT_LINK =
+ '/HEALTHBENEFITS/vtp/beneficiary_travel_pocs.asp';
+
export const STATUS_GROUPINGS = [
{
name: 'Saved or Incomplete',
diff --git a/src/applications/travel-pay/containers/SubmitFlowWrapper.jsx b/src/applications/travel-pay/containers/SubmitFlowWrapper.jsx
index 590bc085085c..6acd19411afb 100644
--- a/src/applications/travel-pay/containers/SubmitFlowWrapper.jsx
+++ b/src/applications/travel-pay/containers/SubmitFlowWrapper.jsx
@@ -11,21 +11,23 @@ import ReviewPage from '../components/submit-flow/pages/ReviewPage';
import ConfirmationPage from '../components/submit-flow/pages/ConfirmationPage';
import BreadCrumbs from '../components/Breadcrumbs';
-import CantFilePage from '../components/submit-flow/pages/CantFilePage';
+import UnsupportedClaimTypePage from '../components/submit-flow/pages/UnsupportedClaimTypePage';
import SubmissionErrorPage from '../components/submit-flow/pages/SubmissionErrorPage';
+import { appointment1 } from '../services/mocks/appointments';
const SubmitFlowWrapper = () => {
- const [cantFile, setCantFile] = useState(false);
-
+ // TODO: Placeholders until backend integration is complete
+ // API call based on the URL Params, but for now is hard coded
+ const appointment = appointment1;
// This will actually be handled by the redux action, but for now it lives here
const [isSubmissionError, setIsSubmissionError] = useState(false);
const [pageIndex, setPageIndex] = useState(0);
+ const [isUnsupportedClaimType, setIsUnsupportedClaimType] = useState(false);
const handlers = {
onNext: e => {
e.preventDefault();
-
setPageIndex(pageIndex + 1);
},
onBack: e => {
@@ -49,7 +51,8 @@ const SubmitFlowWrapper = () => {
page: 'intro',
component: (
{
+ appointment={appointment}
+ onStart={e => {
e.preventDefault();
setPageIndex(pageIndex + 1);
}}
@@ -111,15 +114,17 @@ const SubmitFlowWrapper = () => {
- {cantFile && (
-
)}
{isSubmissionError && }
- {!cantFile && !isSubmissionError && pageList[pageIndex].component}
+ {!isUnsupportedClaimType &&
+ !isSubmissionError &&
+ pageList[pageIndex].component}
diff --git a/src/applications/travel-pay/containers/TravelPayStatusApp.jsx b/src/applications/travel-pay/containers/TravelPayStatusApp.jsx
index 3d477d802567..8967813fc8d3 100644
--- a/src/applications/travel-pay/containers/TravelPayStatusApp.jsx
+++ b/src/applications/travel-pay/containers/TravelPayStatusApp.jsx
@@ -21,7 +21,7 @@ import { toggleLoginModal } from 'platform/site-wide/user-nav/actions';
import BreadCrumbs from '../components/Breadcrumbs';
import TravelClaimCard from '../components/TravelClaimCard';
import TravelPayClaimFilters from '../components/TravelPayClaimFilters';
-import HelpTextContent from '../components/HelpText';
+import { HelpTextManage } from '../components/HelpText';
import { getTravelClaims } from '../redux/actions';
import { getDateFilters } from '../util/dates';
@@ -283,8 +283,18 @@ export default function App({ children }) {
You can use this tool to check the status of your VA travel claims.
-
-
+
+ <>
+
+
+ >
{isLoading && (
diff --git a/src/applications/travel-pay/services/mocks/appointments.js b/src/applications/travel-pay/services/mocks/appointments.js
new file mode 100644
index 000000000000..15948a1b0bfe
--- /dev/null
+++ b/src/applications/travel-pay/services/mocks/appointments.js
@@ -0,0 +1,417 @@
+export const appointment1 = {
+ resourceType: 'Appointment',
+ id: 'aa6bb54b5f8ba22a82720a30abdfa3efe0805cc0dc1b6b248815e942ad61847e',
+ status: 'booked',
+ cancelationReason: null,
+ avsPath: null,
+ start: '2024-12-30T08:00:00-06:00',
+ patientComments: null,
+ timezone: 'America/Denver',
+ description: 'VAOS_UNKNOWN',
+ minutesDuration: 15,
+ location: {
+ vistaId: '983',
+ clinicId: '1038',
+ stationId: '983',
+ clinicName: 'COVID VACCINE CLIN1',
+ clinicPhysicalLocation: 'MHC',
+ clinicPhone: null,
+ clinicPhoneExtension: null,
+ },
+ videoData: {
+ isVideo: false,
+ },
+ communityCareProvider: null,
+ preferredProviderName: null,
+ practitioners: [
+ {
+ identifier: [
+ {
+ system: 'https://veteran.apps.va.gov/terminology/fhir/sid/secid',
+ value: null,
+ },
+ ],
+ name: {
+ family: 'BERNARDO',
+ given: ['KENNETH J'],
+ },
+ },
+ ],
+ vaos: {
+ isPendingAppointment: false,
+ isUpcomingAppointment: true,
+ isVideo: false,
+ isPastAppointment: false,
+ isCompAndPenAppointment: false,
+ isCancellable: false,
+ appointmentType: 'vaAppointment',
+ isCommunityCare: false,
+ isExpressCare: false,
+ isPhoneAppointment: false,
+ isCOVIDVaccine: true,
+ apiData: {
+ id: 'aa6bb54b5f8ba22a82720a30abdfa3efe0805cc0dc1b6b248815e942ad61847e',
+ identifier: [
+ {
+ system: 'Appointment/',
+ value: '413938333133353533',
+ },
+ {
+ system: 'http://www.va.gov/Terminology/VistADefinedTerms/409_84',
+ value: '983:13553',
+ },
+ ],
+ kind: 'clinic',
+ status: 'booked',
+ serviceType: 'covid',
+ serviceTypes: [
+ {
+ coding: [
+ {
+ system:
+ 'http://veteran.apps.va.gov/terminologies/fhir/CodeSystem/vats-service-type',
+ code: 'covid',
+ },
+ ],
+ },
+ ],
+ serviceCategory: [
+ {
+ coding: [
+ {
+ system: 'http://www.va.gov/Terminology/VistADefinedTerms/409_1',
+ code: 'REGULAR',
+ display: 'REGULAR',
+ },
+ ],
+ text: 'REGULAR',
+ },
+ ],
+ patientIcn: '1012846043V576341',
+ locationId: '983',
+ clinic: '1038',
+ practitioners: [
+ {
+ identifier: [
+ {
+ system: 'https://veteran.apps.va.gov/terminology/fhir/sid/secid',
+ value: null,
+ },
+ ],
+ name: {
+ family: 'BERNARDO',
+ given: ['KENNETH J'],
+ },
+ },
+ ],
+ start: '2024-12-30T14:00:00Z',
+ end: '2024-08-01T14:15:00Z',
+ minutesDuration: 15,
+ slot: {
+ id: '3230323430383031313430303A323032343038303131343135',
+ start: '2024-12-01T14:00:00Z',
+ end: '2024-12-01T14:15:00Z',
+ },
+ created: '2024-12-09T00:00:00Z',
+ cancellable: false,
+ extension: {
+ ccLocation: {
+ address: {},
+ },
+ vistaStatus: ['FUTURE'],
+ preCheckinAllowed: true,
+ eCheckinAllowed: true,
+ clinic: {
+ physicalLocation: 'MHC',
+ },
+ },
+ localStartTime: '2024-12-01T08:00:00.000-06:00',
+ serviceName: 'COVID VACCINE CLIN1',
+ friendlyName: 'COVID VACCINE CLIN1',
+ physicalLocation: 'MHC',
+ location: {
+ id: '983',
+ type: 'appointments',
+ attributes: {
+ id: '983',
+ vistaSite: '983',
+ vastParent: '983',
+ type: 'va_facilities',
+ name: 'Cheyenne VA Medical Center',
+ classification: 'VA Medical Center (VAMC)',
+ timezone: {
+ timeZoneId: 'America/Denver',
+ },
+ lat: 39.744507,
+ long: -104.830956,
+ website: 'https://www.denver.va.gov/locations/directions.asp',
+ phone: {
+ main: '307-778-7550',
+ fax: '307-778-7381',
+ pharmacy: '866-420-6337',
+ afterHours: '307-778-7550',
+ patientAdvocate: '307-778-7550 x7517',
+ mentalHealthClinic: '307-778-7349',
+ enrollmentCoordinator: '307-778-7550 x7579',
+ },
+ physicalAddress: {
+ type: 'physical',
+ line: ['2360 East Pershing Boulevard'],
+ city: 'Cheyenne',
+ state: 'WY',
+ postalCode: '82001-5356',
+ },
+ mobile: false,
+ healthService: [
+ 'Audiology',
+ 'Cardiology',
+ 'DentalServices',
+ 'EmergencyCare',
+ 'Gastroenterology',
+ 'Gynecology',
+ 'MentalHealthCare',
+ 'Nutrition',
+ 'Ophthalmology',
+ 'Optometry',
+ 'Orthopedics',
+ 'Podiatry',
+ 'PrimaryCare',
+ 'SpecialtyCare',
+ 'UrgentCare',
+ 'Urology',
+ 'WomensHealth',
+ ],
+ operatingStatus: {
+ code: 'NORMAL',
+ },
+ },
+ },
+ },
+ timeZone: 'America/Denver',
+ facilityData: {
+ resourceType: 'Location',
+ id: '983',
+ vistaId: '983',
+ name: 'Cheyenne VA Medical Center',
+ identifier: [
+ {
+ system: 'http://med.va.gov/fhir/urn',
+ value: 'urn:va:division:983:983',
+ },
+ {
+ system: 'urn:oid:2.16.840.1.113883.6.233',
+ value: '983',
+ },
+ ],
+ telecom: [
+ {
+ system: 'phone',
+ value: '307-778-7550',
+ },
+ ],
+ position: {
+ longitude: -104.830956,
+ latitude: 39.744507,
+ },
+ address: {
+ line: ['2360 East Pershing Boulevard'],
+ city: 'Cheyenne',
+ state: 'WY',
+ postalCode: '82001-5356',
+ },
+ },
+ },
+ version: 2,
+};
+
+export const appointment = {
+ resourceType: 'Appointment',
+ id: 'aa6bb54b5f8ba22a82720a30abdfa3efe0805cc0dc1b6b248815e942ad61847e',
+ status: 'booked',
+ cancelationReason: null,
+ start: '2024-11-20T10:30:00-05:00',
+ patientComments: null,
+ reasonForAppointment: 'Medication concern',
+ timezone: 'Asia/Manila',
+ description: 'VAOS_UNKNOWN',
+ minutesDuration: 60,
+ practitioners: [
+ {
+ identifier: [
+ {
+ system: 'https://veteran.apps.va.gov/terminology/fhir/sid/secid',
+ value: null,
+ },
+ ],
+ name: {
+ family: 'BERNARDO',
+ given: ['KENNETH J'],
+ },
+ },
+ ],
+ location: {
+ vistaId: '983',
+ clinicId: '945',
+ stationId: '983GC',
+ clinicName: 'C&P BEV AUDIO FTC',
+ clinicPhysicalLocation: 'FORT COLLINS AUDIO',
+ clinicPhone: null,
+ clinicPhoneExtension: null,
+ },
+ videoData: {
+ isVideo: false,
+ },
+ communityCareProvider: null,
+ preferredProviderName: null,
+ vaos: {
+ isPendingAppointment: false,
+ isUpcomingAppointment: false,
+ isVideo: false,
+ isPastAppointment: true,
+ isCompAndPenAppointment: true,
+ isCancellable: false,
+ appointmentType: 'vaAppointment',
+ isCommunityCare: false,
+ isExpressCare: false,
+ isPhoneAppointment: false,
+ isCOVIDVaccine: false,
+ apiData: {
+ id: '167322',
+ identifier: [
+ {
+ system: 'Appointment/',
+ value: '4139383339353233',
+ },
+ ],
+ kind: 'clinic',
+ status: 'booked',
+ serviceType: 'audiology',
+ serviceTypes: [
+ {
+ coding: [
+ {
+ system:
+ 'http://veteran.apps.va.gov/terminologies/fhir/CodeSystem/vats-service-type',
+ code: 'audiology',
+ },
+ ],
+ },
+ ],
+ serviceCategory: [
+ {
+ coding: [
+ {
+ system: 'http://www.va.gov/Terminology/VistADefinedTerms/409_1',
+ code: 'COMPENSATION & PENSION',
+ display: 'COMPENSATION & PENSION',
+ },
+ ],
+ text: 'COMPENSATION & PENSION',
+ },
+ ],
+ patientIcn: '1013120826V646496',
+ locationId: '983GC',
+ localStartTime: '2024-11-20T10:30:00.000+08:00',
+ clinic: '945',
+ start: '2024-11-20T09:30:00Z',
+ end: '2024-11-20T10:00:00Z',
+ created: '2024-03-17T00:00:00Z',
+ cancellable: false,
+ extension: {
+ ccLocation: {
+ address: {},
+ },
+ vistaStatus: ['NO ACTION TAKEN'],
+ },
+ serviceName: 'FTC C&P AUDIO BEV',
+ physicalLocation: 'FORT COLLINS AUDIO',
+ friendlyName: 'C&P BEV AUDIO FTC',
+ practitioners: [
+ {
+ identifier: [
+ {
+ system: 'https://veteran.apps.va.gov/terminology/fhir/sid/secid',
+ value: null,
+ },
+ ],
+ name: {
+ family: 'BERNARDO',
+ given: ['KENNETH J'],
+ },
+ },
+ ],
+ location: {
+ id: '983GC',
+ type: 'appointments',
+ attributes: {
+ id: '983GC',
+ vistaSite: '983',
+ vastParent: '983',
+ type: 'va_facilities',
+ name: 'Fort Collins VA Clinic',
+ classification: 'Multi-Specialty CBOC',
+ timezone: {
+ timeZoneId: 'Asia/Manila',
+ },
+ lat: 40.553875,
+ long: -105.08795,
+ website:
+ 'https://www.cheyenne.va.gov/locations/Fort_Collins_VA_CBOC.asp',
+ phone: {
+ main: '970-224-1550',
+ },
+ physicalAddress: {
+ line: ['2509 Research Boulevard'],
+ city: 'Fort Collins',
+ state: 'CO',
+ postalCode: '80526-8108',
+ },
+ healthService: [
+ 'Audiology',
+ 'EmergencyCare',
+ 'MentalHealthCare',
+ 'PrimaryCare',
+ 'SpecialtyCare',
+ ],
+ },
+ },
+ claim: {
+ message: 'No claim for this appointment',
+ },
+ },
+ timeZone: 'Asia/Manila',
+ facilityData: {
+ resourceType: 'Location',
+ id: '983GC',
+ vistaId: '983',
+ name: 'Fort Collins VA Clinic',
+ identifier: [
+ {
+ system: 'http://med.va.gov/fhir/urn',
+ value: 'urn:va:division:983:983GC',
+ },
+ {
+ system: 'urn:oid:2.16.840.1.113883.6.233',
+ value: '983GC',
+ },
+ ],
+ telecom: [
+ {
+ system: 'phone',
+ value: '970-224-1550',
+ },
+ ],
+ position: {
+ longitude: -105.08795,
+ latitude: 40.553875,
+ },
+ address: {
+ line: ['2509 Research Boulevard'],
+ city: 'Fort Collins',
+ state: 'CO',
+ postalCode: '80526-8108',
+ },
+ },
+ },
+ version: 2,
+};
diff --git a/src/applications/travel-pay/services/mocks/index.js b/src/applications/travel-pay/services/mocks/index.js
index 70a4ec6029d8..eb23a3c3f872 100644
--- a/src/applications/travel-pay/services/mocks/index.js
+++ b/src/applications/travel-pay/services/mocks/index.js
@@ -1,11 +1,11 @@
const delay = require('mocker-api/lib/delay');
const TOGGLE_NAMES = require('../../../../platform/utilities/feature-toggles/featureFlagNames.json');
-const commonResponses = require('../../../../platform/testing/local-dev-mock-api/common');
const travelClaims = require('./travel-claims-31.json');
+const user = require('./user.json');
const responses = {
- ...commonResponses,
+ 'GET /v0/user': user,
'GET /v0/feature_toggles': {
data: {
type: 'feature_toggles',
diff --git a/src/applications/travel-pay/services/mocks/user.json b/src/applications/travel-pay/services/mocks/user.json
new file mode 100644
index 000000000000..e957ddb2ade2
--- /dev/null
+++ b/src/applications/travel-pay/services/mocks/user.json
@@ -0,0 +1,224 @@
+{
+ "data": {
+ "id": "",
+ "type": "users_scaffolds",
+ "attributes": {
+ "services": [
+ "facilities",
+ "hca",
+ "edu-benefits",
+ "form-save-in-progress",
+ "form-prefill",
+ "form526",
+ "user-profile",
+ "appeals-status",
+ "id-card",
+ "identity-proofed",
+ "vet360",
+ "lighthouse"
+ ],
+ "account": {
+ "accountUuid": "7d9e2bfb-13ae-45c8-8764-ea3c87cd8af3"
+ },
+ "profile": {
+ "email": "vets.gov.user+75@gmail.com",
+ "firstName": "MITCHELL",
+ "middleName": "G",
+ "lastName": "JENKINS",
+ "birthDate": "1949-03-04",
+ "gender": "M",
+ "zip": "97063",
+ "lastSignedIn": "2022-03-24T18:15:06.566Z",
+ "loa": {
+ "current": 3,
+ "highest": 3
+ },
+ "multifactor": true,
+ "verified": true,
+ "signIn": {
+ "serviceName": "idme",
+ "accountType": "N/A"
+ },
+ "authnContext": "http://idmanagement.gov/ns/assurance/loa/3",
+ "claims": {
+ "ch33BankAccounts": true,
+ "communicationPreferences": true,
+ "connectedApps": true,
+ "militaryHistory": true,
+ "paymentHistory": true,
+ "personalInformation": true,
+ "ratingInfo": true,
+ "appeals": true,
+ "medicalCopays": true
+ },
+ "edipi": 3332224445
+ },
+ "vaProfile": {
+ "status": "OK",
+ "birthDate": "19490304",
+ "familyName": "Jenkins",
+ "gender": "M",
+ "givenNames": ["Mitchell", "G"],
+ "isCernerPatient": false,
+ "facilities": [
+ {
+ "facilityId": "989",
+ "isCerner": false
+ },
+ {
+ "facilityId": "987",
+ "isCerner": false
+ },
+ {
+ "facilityId": "983",
+ "isCerner": false
+ }
+ ],
+ "vaPatient": true,
+ "mhvAccountState": "NONE"
+ },
+ "veteranStatus": {
+ "status": "OK",
+ "isVeteran": true,
+ "servedInMilitary": true
+ },
+ "inProgressForms": [],
+ "prefillsAvailable": ["21-686C", "mock-form-ae-design-patterns"],
+ "vet360ContactInformation": {
+ "email": {
+ "createdAt": "2018-04-20T17:24:13.000Z",
+ "emailAddress": "myemail72585885@unattended.com",
+ "effectiveEndDate": null,
+ "effectiveStartDate": "2019-03-07T22:32:40.000Z",
+ "id": 20648,
+ "sourceDate": "2019-03-07T22:32:40.000Z",
+ "sourceSystemUser": null,
+ "transactionId": "44a0858b-3dd1-4de2-903d-38b147981a9c",
+ "updatedAt": "2019-03-08T05:09:58.000Z",
+ "vet360Id": "1273766"
+ },
+ "residentialAddress": {
+ "addressLine1": "345 Home Address St.",
+ "addressLine2": null,
+ "addressLine3": null,
+ "addressPou": "RESIDENCE/CHOICE",
+ "addressType": "DOMESTIC",
+ "city": "San Francisco",
+ "countryName": "United States",
+ "countryCodeIso2": "US",
+ "countryCodeIso3": "USA",
+ "countryCodeFips": null,
+ "countyCode": null,
+ "countyName": null,
+ "createdAt": "2022-03-21T21:26:35.000Z",
+ "effectiveEndDate": null,
+ "effectiveStartDate": "2022-03-23T19:11:51.000Z",
+ "geocodeDate": "2022-03-23T19:11:51.000Z",
+ "geocodePrecision": null,
+ "id": 312003,
+ "internationalPostalCode": null,
+ "latitude": 37.781,
+ "longitude": -122.4605,
+ "province": null,
+ "sourceDate": "2022-03-23T19:11:51.000Z",
+ "sourceSystemUser": null,
+ "stateCode": "CA",
+ "transactionId": "c5adb989-3b87-47b6-afe3-dc18800cedc3",
+ "updatedAt": "2022-03-23T19:11:52.000Z",
+ "validationKey": null,
+ "vet360Id": "1273766",
+ "zipCode": "94118",
+ "zipCodeSuffix": null,
+ "badAddress": null
+ },
+ "mailingAddress": {
+ "addressLine1": "123 Mailing Address St.",
+ "addressLine2": "Apt 1",
+ "addressLine3": null,
+ "addressPou": "CORRESPONDENCE",
+ "addressType": "DOMESTIC",
+ "city": "Fulton",
+ "countryName": "United States",
+ "countryCodeIso2": "US",
+ "countryCodeIso3": "USA",
+ "countryCodeFips": null,
+ "countyCode": null,
+ "countyName": null,
+ "createdAt": "2022-03-21T21:06:15.000Z",
+ "effectiveEndDate": null,
+ "effectiveStartDate": "2022-03-23T19:14:59.000Z",
+ "geocodeDate": "2022-03-23T19:15:00.000Z",
+ "geocodePrecision": null,
+ "id": 311999,
+ "internationalPostalCode": null,
+ "latitude": 45.2248,
+ "longitude": -121.3595,
+ "province": null,
+ "sourceDate": "2022-03-23T19:14:59.000Z",
+ "sourceSystemUser": null,
+ "stateCode": "NY",
+ "transactionId": "3ea3ecf8-3ddf-46d9-8a4b-b5554385b3fb",
+ "updatedAt": "2022-03-23T19:15:01.000Z",
+ "validationKey": null,
+ "vet360Id": "1273766",
+ "zipCode": "97063",
+ "zipCodeSuffix": null,
+ "badAddress": null
+ },
+ "mobilePhone": {
+ "areaCode": "619",
+ "countryCode": "1",
+ "createdAt": "2022-01-12T16:22:03.000Z",
+ "extension": null,
+ "effectiveEndDate": null,
+ "effectiveStartDate": "2022-02-17T20:15:44.000Z",
+ "id": 269804,
+ "isInternational": false,
+ "isTextable": null,
+ "isTextPermitted": null,
+ "isTty": null,
+ "isVoicemailable": null,
+ "phoneNumber": "5551234",
+ "phoneType": "MOBILE",
+ "sourceDate": "2022-02-17T20:15:44.000Z",
+ "sourceSystemUser": null,
+ "transactionId": "fdb13953-f670-4bd3-a3bb-8881eb9165dd",
+ "updatedAt": "2022-02-17T20:15:45.000Z",
+ "vet360Id": "1273766"
+ },
+ "homePhone": {
+ "areaCode": "989",
+ "countryCode": "1",
+ "createdAt": "2018-04-20T17:22:56.000Z",
+ "extension": null,
+ "effectiveEndDate": null,
+ "effectiveStartDate": "2022-03-11T16:31:55.000Z",
+ "id": 2272982,
+ "isInternational": false,
+ "isTextable": null,
+ "isTextPermitted": null,
+ "isTty": null,
+ "isVoicemailable": null,
+ "phoneNumber": "8981233",
+ "phoneType": "HOME",
+ "sourceDate": "2022-03-11T16:31:55.000Z",
+ "sourceSystemUser": null,
+ "transactionId": "2814cdf6-7f2c-431b-95f3-d37f3837215d",
+ "updatedAt": "2022-03-11T16:31:56.000Z",
+ "vet360Id": "1273766"
+ },
+ "workPhone": null,
+ "temporaryPhone": null,
+ "faxNumber": null,
+ "textPermission": null
+ },
+ "session": {
+ "ssoe": true,
+ "transactionid": "YEI6t8W3ANsvCT04oB+iXh/UP03PXSFg3Y36L2QaxLE="
+ }
+ }
+ },
+ "meta": {
+ "errors": null
+ }
+}
diff --git a/src/applications/travel-pay/tests/components/submit-flow/pages/AddressPage.unit.spec.jsx b/src/applications/travel-pay/tests/components/submit-flow/pages/AddressPage.unit.spec.jsx
new file mode 100644
index 000000000000..4248b256763b
--- /dev/null
+++ b/src/applications/travel-pay/tests/components/submit-flow/pages/AddressPage.unit.spec.jsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { expect } from 'chai';
+import { render } from '@testing-library/react';
+import { $ } from 'platform/forms-system/src/js/utilities/ui';
+
+import AddressPage from '../../../../components/submit-flow/pages/AddressPage';
+
+it('should render with back and continue buttons', () => {
+ const props = {
+ handlers: {
+ onBack: () => {},
+ onNext: () => {},
+ },
+ };
+ const screen = render();
+
+ expect(screen.getByText('Address page')).to.exist;
+ expect($('va-button-pair')).to.exist;
+});
diff --git a/src/applications/travel-pay/tests/components/submit-flow/pages/ConfirmationPage.unit.spec.jsx b/src/applications/travel-pay/tests/components/submit-flow/pages/ConfirmationPage.unit.spec.jsx
new file mode 100644
index 000000000000..9842e0216c6d
--- /dev/null
+++ b/src/applications/travel-pay/tests/components/submit-flow/pages/ConfirmationPage.unit.spec.jsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import { expect } from 'chai';
+import { render } from '@testing-library/react';
+
+import ConfirmationPage from '../../../../components/submit-flow/pages/ConfirmationPage';
+
+it('should render', () => {
+ const screen = render();
+
+ expect(screen.getByText('We’re processing your travel reimbursement claim'))
+ .to.exist;
+});
diff --git a/src/applications/travel-pay/tests/components/submit-flow/pages/IntroductionPage.unit.spec.jsx b/src/applications/travel-pay/tests/components/submit-flow/pages/IntroductionPage.unit.spec.jsx
new file mode 100644
index 000000000000..c34d52411bde
--- /dev/null
+++ b/src/applications/travel-pay/tests/components/submit-flow/pages/IntroductionPage.unit.spec.jsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { expect } from 'chai';
+import { render } from '@testing-library/react';
+import { $ } from 'platform/forms-system/src/js/utilities/ui';
+
+import IntroductionPage from '../../../../components/submit-flow/pages/IntroductionPage';
+
+const appointment = require('../../../fixtures/appointment.json');
+
+it('should render with link to file a claim', () => {
+ const props = {
+ appointment,
+ onNext: () => {},
+ };
+ const screen = render();
+
+ expect(screen.getByText('File a travel reimbursement claim')).to.exist;
+ expect(
+ screen.getByText(
+ /Monday, December 30, 2024 at Cheyenne VA Medical Center/i,
+ ),
+ ).to.exist;
+ expect($('va-link-action[text="File a mileage only claim"]')).to.exist;
+});
diff --git a/src/applications/travel-pay/tests/components/submit-flow/pages/MileagePage.unit.spec.jsx b/src/applications/travel-pay/tests/components/submit-flow/pages/MileagePage.unit.spec.jsx
new file mode 100644
index 000000000000..9edccecc810c
--- /dev/null
+++ b/src/applications/travel-pay/tests/components/submit-flow/pages/MileagePage.unit.spec.jsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { expect } from 'chai';
+import { render } from '@testing-library/react';
+import { $ } from 'platform/forms-system/src/js/utilities/ui';
+
+import MileagePage from '../../../../components/submit-flow/pages/MileagePage';
+
+it('should render with back and continue buttons', () => {
+ const props = {
+ handlers: {
+ onBack: () => {},
+ onNext: () => {},
+ },
+ };
+ const screen = render();
+
+ expect(screen.getByText('Mileage page')).to.exist;
+ expect($('va-button-pair')).to.exist;
+});
diff --git a/src/applications/travel-pay/tests/components/submit-flow/pages/ReviewPage.unit.spec.jsx b/src/applications/travel-pay/tests/components/submit-flow/pages/ReviewPage.unit.spec.jsx
new file mode 100644
index 000000000000..c46b4ffdcb60
--- /dev/null
+++ b/src/applications/travel-pay/tests/components/submit-flow/pages/ReviewPage.unit.spec.jsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { expect } from 'chai';
+import { render } from '@testing-library/react';
+import { $ } from 'platform/forms-system/src/js/utilities/ui';
+
+import ReviewPage from '../../../../components/submit-flow/pages/ReviewPage';
+
+it('should render with back and submit buttons', () => {
+ const props = {
+ handlers: {
+ onBack: () => {},
+ onSubmit: () => {},
+ },
+ };
+ const screen = render();
+
+ expect(screen.getByText('Review your travel claim')).to.exist;
+ expect($('va-button[text="Back"')).to.exist;
+ expect($('va-button[text="Submit"')).to.exist;
+});
diff --git a/src/applications/travel-pay/tests/components/submit-flow/pages/SubmissionErrorPage.unit.spec.jsx b/src/applications/travel-pay/tests/components/submit-flow/pages/SubmissionErrorPage.unit.spec.jsx
new file mode 100644
index 000000000000..113115f944e9
--- /dev/null
+++ b/src/applications/travel-pay/tests/components/submit-flow/pages/SubmissionErrorPage.unit.spec.jsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import { expect } from 'chai';
+import { render } from '@testing-library/react';
+
+import SubmissionErrorPage from '../../../../components/submit-flow/pages/SubmissionErrorPage';
+
+it('should render with back button', () => {
+ const screen = render();
+
+ expect(screen.getByText('We couldn’t file your claim')).to.exist;
+});
diff --git a/src/applications/travel-pay/tests/components/submit-flow/pages/UnsupportedClaimTypePage.unit.spec.jsx b/src/applications/travel-pay/tests/components/submit-flow/pages/UnsupportedClaimTypePage.unit.spec.jsx
new file mode 100644
index 000000000000..af5afdbb0471
--- /dev/null
+++ b/src/applications/travel-pay/tests/components/submit-flow/pages/UnsupportedClaimTypePage.unit.spec.jsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { expect } from 'chai';
+import { render } from '@testing-library/react';
+import { $ } from 'platform/forms-system/src/js/utilities/ui';
+
+import UnsupportedClaimTypePage from '../../../../components/submit-flow/pages/UnsupportedClaimTypePage';
+
+it('should render with back button', () => {
+ const props = {
+ pageIndex: 2,
+ setIsUnsupportedClaimType: () => {},
+ setPageIndex: () => {},
+ };
+ const screen = render();
+
+ expect(
+ screen.getByText('We can’t file this type of travel reimbursement claim'),
+ ).to.exist;
+ expect($('va-button[text="Back"]')).to.exist;
+});
diff --git a/src/applications/travel-pay/tests/components/submit-flow/pages/VehiclePage.unit.spec.jsx b/src/applications/travel-pay/tests/components/submit-flow/pages/VehiclePage.unit.spec.jsx
new file mode 100644
index 000000000000..45c4fbabd4b5
--- /dev/null
+++ b/src/applications/travel-pay/tests/components/submit-flow/pages/VehiclePage.unit.spec.jsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { expect } from 'chai';
+import { render } from '@testing-library/react';
+import { $ } from 'platform/forms-system/src/js/utilities/ui';
+
+import VehiclePage from '../../../../components/submit-flow/pages/VehiclePage';
+
+it('should render with back and continue buttons', () => {
+ const props = {
+ handlers: {
+ onBack: () => {},
+ onNext: () => {},
+ },
+ };
+ const screen = render();
+
+ expect(screen.getByText('Vehicle page')).to.exist;
+ expect($('va-button-pair')).to.exist;
+});
diff --git a/src/applications/travel-pay/tests/e2e/submit-claim.cypress.spec.js b/src/applications/travel-pay/tests/e2e/submit-claim.cypress.spec.js
new file mode 100644
index 000000000000..be74185704eb
--- /dev/null
+++ b/src/applications/travel-pay/tests/e2e/submit-claim.cypress.spec.js
@@ -0,0 +1,53 @@
+/* eslint-disable @department-of-veterans-affairs/axe-check-required */
+import { rootUrl } from '../../manifest.json';
+import user from '../fixtures/user.json';
+import ApiInitializer from './utilities/ApiInitializer';
+
+describe('Submit Mileage Only Claims', () => {
+ beforeEach(() => {
+ cy.intercept('/data/cms/vamc-ehr.json', {});
+ ApiInitializer.initializeFeatureToggle.withAllFeatures();
+ cy.login(user);
+ cy.visit(`${rootUrl}/file-new-claim/12345`);
+ cy.injectAxeThenAxeCheck();
+ });
+
+ it('defaults to the Introduction page', () => {
+ cy.get('h1').should('include.text', 'File a travel reimbursement claim');
+ });
+
+ it('should navigate through the flow', () => {
+ cy.get('va-link-action[text="File a mileage only claim"]')
+ .first()
+ .click();
+
+ // Mileage question should be first
+ cy.get('h1').should('include.text', 'Mileage page');
+
+ // Click the "Continue" button
+ cy.selectVaButtonPairPrimary();
+
+ // Then navigate to the Vehicle question
+ cy.get('h1').should('include.text', 'Vehicle page');
+
+ // Click the "Continue" button
+ cy.selectVaButtonPairPrimary();
+
+ // Then navigate to the Address question
+ cy.get('h1').should('include.text', 'Address page');
+
+ // Click the "Continue" button
+ cy.selectVaButtonPairPrimary();
+
+ // Then navigate to the Review page
+ cy.get('h1').should('include.text', 'Review your travel claim');
+
+ // Click the "Submit" button
+ cy.get('va-button[text="Submit"]')
+ .first()
+ .click();
+
+ // Submission Error page is currently the hard-coded default behavior
+ cy.get('h1').should('include.text', 'We couldn’t file your claim');
+ });
+});
diff --git a/src/applications/travel-pay/tests/e2e/travel-pay.cypress.spec.js b/src/applications/travel-pay/tests/e2e/travel-pay.cypress.spec.js
index bee9f711e032..400b19b69c05 100644
--- a/src/applications/travel-pay/tests/e2e/travel-pay.cypress.spec.js
+++ b/src/applications/travel-pay/tests/e2e/travel-pay.cypress.spec.js
@@ -81,7 +81,7 @@ describe(`${appName} -- Status Page`, () => {
.first()
.click();
- cy.get('a[data-testid="status-explainer-link"]')
+ cy.get('va-link[data-testid="status-explainer-link"]')
.first()
.click();
diff --git a/src/applications/travel-pay/tests/e2e/utilities/ApiInitializer.js b/src/applications/travel-pay/tests/e2e/utilities/ApiInitializer.js
index eb5b5abaa910..e9c920c783bf 100644
--- a/src/applications/travel-pay/tests/e2e/utilities/ApiInitializer.js
+++ b/src/applications/travel-pay/tests/e2e/utilities/ApiInitializer.js
@@ -9,6 +9,7 @@ class ApiInitializer {
features: [
{ name: 'travel_pay_power_switch', value: true },
{ name: 'travel_pay_view_claim_details', value: true },
+ { name: 'travel_pay_submit_mileage_expense', value: true },
],
},
}).as('featureToggles');
diff --git a/src/applications/travel-pay/tests/fixtures/appointment.json b/src/applications/travel-pay/tests/fixtures/appointment.json
new file mode 100644
index 000000000000..3c61dd33a308
--- /dev/null
+++ b/src/applications/travel-pay/tests/fixtures/appointment.json
@@ -0,0 +1,98 @@
+{
+ "vaos": {
+ "apiData": {
+ "practitioners": [
+ {
+ "identifier": [
+ {
+ "system": "https://veteran.apps.va.gov/terminology/fhir/sid/secid",
+ "value": null
+ }
+ ],
+ "name": {
+ "family": "BERNARDO",
+ "given": ["KENNETH J"]
+ }
+ }
+ ],
+ "start": "2024-12-30T14:00:00Z",
+ "localStartTime": "2024-12-01T08:00:00.000-06:00",
+ "serviceName": "COVID VACCINE CLIN1",
+ "friendlyName": "COVID VACCINE CLIN1",
+ "physicalLocation": "MHC",
+ "location": {
+ "id": "983",
+ "type": "appointments",
+ "attributes": {
+ "id": "983",
+ "vistaSite": "983",
+ "vastParent": "983",
+ "type": "va_facilities",
+ "name": "Cheyenne VA Medical Center",
+ "classification": "VA Medical Center (VAMC)",
+ "timezone": {
+ "timeZoneId": "America/Denver"
+ },
+ "lat": 39.744507,
+ "long": -104.830956,
+ "website": "https://www.denver.va.gov/locations/directions.asp",
+ "phone": {
+ "main": "307-778-7550",
+ "fax": "307-778-7381",
+ "pharmacy": "866-420-6337",
+ "afterHours": "307-778-7550",
+ "patientAdvocate": "307-778-7550 x7517",
+ "mentalHealthClinic": "307-778-7349",
+ "enrollmentCoordinator": "307-778-7550 x7579"
+ },
+ "physicalAddress": {
+ "type": "physical",
+ "line": ["2360 East Pershing Boulevard"],
+ "city": "Cheyenne",
+ "state": "WY",
+ "postalCode": "82001-5356"
+ },
+ "mobile": false,
+ "healthService": [],
+ "operatingStatus": {
+ "code": "NORMAL"
+ }
+ }
+ },
+ "timeZone": "America/Denver",
+ "facilityData": {
+ "resourceType": "Location",
+ "id": "983",
+ "vistaId": "983",
+ "name": "Cheyenne VA Medical Center",
+ "identifier": [
+ {
+ "system": "http://med.va.gov/fhir/urn",
+ "value": "urn:va:division:983:983"
+ },
+ {
+ "system": "urn:oid:2.16.840.1.113883.6.233",
+ "value": "983"
+ }
+ ],
+ "telecom": [
+ {
+ "system": "phone",
+ "value": "307-778-7550"
+ }
+ ],
+ "position": {
+ "longitude": -104.830956,
+ "latitude": 39.744507
+ },
+ "address": {
+ "line": ["2360 East Pershing Boulevard"],
+ "city": "Cheyenne",
+ "state": "WY",
+ "postalCode": "82001-5356"
+ }
+ }
+ },
+ "version": 2
+ }
+}
diff --git a/src/applications/travel-pay/tests/fixtures/user.json b/src/applications/travel-pay/tests/fixtures/user.json
index e0fedaff4cf7..e73a34a8c501 100644
--- a/src/applications/travel-pay/tests/fixtures/user.json
+++ b/src/applications/travel-pay/tests/fixtures/user.json
@@ -40,9 +40,7 @@
"birthDate": "19320205",
"familyName": "Allen",
"gender": "M",
- "givenNames": [
- "Hector"
- ],
+ "givenNames": ["Hector"],
"isCernerPatient": false,
"facilities": [
{
@@ -94,7 +92,40 @@
],
"vet360ContactInformation": {
"email": null,
- "residentialAddress": null,
+ "residentialAddress": {
+ "addressLine1": "345 Home Address St.",
+ "addressLine2": null,
+ "addressLine3": null,
+ "addressPou": "RESIDENCE/CHOICE",
+ "addressType": "DOMESTIC",
+ "city": "San Francisco",
+ "countryName": "United States",
+ "countryCodeIso2": "US",
+ "countryCodeIso3": "USA",
+ "countryCodeFips": null,
+ "countyCode": null,
+ "countyName": null,
+ "createdAt": "2022-03-21T21:26:35.000Z",
+ "effectiveEndDate": null,
+ "effectiveStartDate": "2022-03-23T19:11:51.000Z",
+ "geocodeDate": "2022-03-23T19:11:51.000Z",
+ "geocodePrecision": null,
+ "id": 312003,
+ "internationalPostalCode": null,
+ "latitude": 37.781,
+ "longitude": -122.4605,
+ "province": null,
+ "sourceDate": "2022-03-23T19:11:51.000Z",
+ "sourceSystemUser": null,
+ "stateCode": "CA",
+ "transactionId": "c5adb989-3b87-47b6-afe3-dc18800cedc3",
+ "updatedAt": "2022-03-23T19:11:52.000Z",
+ "validationKey": null,
+ "vet360Id": "1273766",
+ "zipCode": "94118",
+ "zipCodeSuffix": null,
+ "badAddress": null
+ },
"mailingAddress": null,
"mobilePhone": null,
"homePhone": {
diff --git a/src/applications/travel-pay/tests/util/dates.spec.js b/src/applications/travel-pay/tests/util/dates.spec.js
index de714c51139c..2c6a9ba3c150 100644
--- a/src/applications/travel-pay/tests/util/dates.spec.js
+++ b/src/applications/travel-pay/tests/util/dates.spec.js
@@ -1,6 +1,6 @@
import MockDate from 'mockdate';
import { expect } from 'chai';
-import { getDateFilters, formatDateTime } from '../../util/dates';
+import { getDateFilters, formatDateTime, getDaysLeft } from '../../util/dates';
function formatDateRange(dateRange) {
const [startDay, startTime] = formatDateTime(dateRange.start);
@@ -205,3 +205,27 @@ describe('getDateFilters', () => {
expect(dateRanges.length).to.eq(6);
});
});
+
+describe('getDaysLeft', () => {
+ afterEach(() => {
+ MockDate.reset();
+ });
+
+ it('returns 10 for a date 20 days ago', () => {
+ MockDate.set('2024-06-25T15:00:00Z');
+ const actual = getDaysLeft('2024-06-05T14:00:00Z');
+ expect(actual).to.eq(10);
+ });
+
+ it('returns 30 for an appointment on the day filed', () => {
+ MockDate.set('2024-06-25T15:00:00Z');
+ const actual = getDaysLeft('2024-06-25T14:00:00Z');
+ expect(actual).to.eq(30);
+ });
+
+ it('returns 0 for a date more than 30 days ago', () => {
+ MockDate.set('2024-06-25T14:00:00Z');
+ const actual = getDaysLeft('2024-05-05T14:00:00Z');
+ expect(actual).to.eq(0);
+ });
+});
diff --git a/src/applications/travel-pay/util/dates.js b/src/applications/travel-pay/util/dates.js
index e2c325aca36b..c6496fd9462a 100644
--- a/src/applications/travel-pay/util/dates.js
+++ b/src/applications/travel-pay/util/dates.js
@@ -1,4 +1,5 @@
import {
+ differenceInCalendarDays,
endOfQuarter,
endOfYear,
format,
@@ -74,3 +75,10 @@ export function getDateFilters() {
return dateRanges;
}
+
+export function getDaysLeft(datetimeString) {
+ const apptDate = new Date(datetimeString);
+ const daysSinceAppt = differenceInCalendarDays(new Date(), apptDate);
+
+ return daysSinceAppt > 30 ? 0 : 30 - daysSinceAppt;
+}