Skip to content

Commit

Permalink
Travel Pay / add content + functionality to question pages (#33979)
Browse files Browse the repository at this point in the history
* add README

* fix cypress test

* bare-bones basics of smoc

* simple it up some more

* fix cypress test for breadcrumb link

* add feature toggle redirect, combine handlers

* destructure props

* add spacing on how to base route page

* wrap explainer page in feature flipper

* remove unneccessary divs and fragments

* update help text content

* add mocked data for appt + user

* add date util fn, add content to intro page

* add appt to submit wrapper

* update cypress test

* tidying after merging main

* add smoc specific cypress test + mock data

* add unit tests + mock appt data; add appt to intro prop types

* update appt start time

* onNext > onStart

* fix linting errors

* update text in unit test to match updated appt date

* update question pages + submit wrapper

* update cypress test

* handle no address

* update address unit test

* pageIndex should be 3

* update mileage page and test

* remove address check from onNext

* update vehicle page and test

* remove preventDefault from cant file page

* update cantFile state

* update cantFile page name

* try moving cy.clock to the before block

* comment out extra show login modal test

* comment out the other cy.clock usage

* fix merge errors

* add focus to va-radio for a11y

* add if statement to handle non-radio h1

* add address to dependency array

* add homeAddress and mailingAddress to props validation

* use actual BTSSS portal URL

* remove additional Login Modal unit test
  • Loading branch information
liztownd authored Jan 21, 2025
1 parent 2f822d9 commit 26aaef5
Show file tree
Hide file tree
Showing 10 changed files with 861 additions and 91 deletions.
167 changes: 157 additions & 10 deletions src/applications/travel-pay/components/submit-flow/pages/AddressPage.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,175 @@
import React from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';

import { VaButtonPair } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import {
VaButtonPair,
VaRadio,
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { focusElement, scrollToTop } from 'platform/utilities/ui';

import { HelpTextGeneral, HelpTextModalities } from '../../HelpText';
import { BTSSS_PORTAL_URL } from '../../../constants';

const AddressPage = ({
address,
pageIndex,
setPageIndex,
yesNo,
setYesNo,
setIsUnsupportedClaimType,
}) => {
useEffect(
() => {
scrollToTop('topScrollElement');
if (!address) {
focusElement('h1');
} else {
focusElement('h1', {}, 'va-radio');
}
},
[address],
);

const [requiredAlert, setRequiredAlert] = useState(false);

const handlers = {
onNext: () => {
if (!yesNo.address) {
setRequiredAlert(true);
} else if (yesNo.address !== 'yes') {
setIsUnsupportedClaimType(true);
} else {
setIsUnsupportedClaimType(false);
setPageIndex(pageIndex + 1);
}
},
onBack: () => {
setPageIndex(pageIndex - 1);
},
};

if (!address) {
return (
<>
<h1 className="vads-u-margin-bottom--2">
Did you travel from your home address?
</h1>
<va-alert
close-btn-aria-label="Close notification"
status="warning"
visible
>
<h2 slot="headline">You don’t have an address on file</h2>
<p className="vads-u-margin-y--0">
We’re sorry, we don’t have an address on file for you and can’t file
a claim in this tool right now.
</p>
</va-alert>
<HelpTextModalities />
<HelpTextGeneral />
<va-button back onClick={handlers.onBack} class="vads-u-margin-y--2" />
</>
);
}

const AddressPage = ({ handlers }) => {
return (
<div>
<h1>Address page</h1>
<VaRadio
use-forms-pattern="single"
form-heading="Did you travel from your home address?"
form-heading-level={1}
id="address"
onVaValueChange={e => {
setYesNo({ ...yesNo, address: e.detail.value });
}}
value={yesNo.address}
data-testid="address-test-id"
error={requiredAlert ? 'You must make a selection to continue.' : null}
header-aria-describedby={null}
hint=""
label=""
label-header-level=""
>
<div slot="form-description">
<p>
Answer “Yes” if you traveled from the address listed here and you
confirm that it’s not a Post Office box.
</p>
<hr className="vads-u-margin-y--0" />
<p className="vads-u-margin-top--2">
<strong>Home address</strong>
<br />
{address.addressLine1}
<br />
{address.addressLine2 && (
<>
{address.addressLine2}
<br />
</>
)}
{address.addressLine3 && (
<>
{address.addressLine3}
<br />
</>
)}
{`${address.city}, ${address.stateCode} ${address.zipCode}`}
<br />
</p>
<hr className="vads-u-margin-y--0" />
</div>
<va-radio-option
label="Yes"
value="yes"
key="address-yes"
name="address"
checked={yesNo.address === 'yes'}
/>
<va-radio-option
key="address-no"
name="address"
checked={yesNo.address === 'no'}
label="No"
value="no"
/>
</VaRadio>

<va-additional-info
class="vads-u-margin-y--3"
trigger="If you didn't travel from your home address"
>
<p>
<strong>
If you traveled from a different address, you can’t file a claim in
this tool right now.
</strong>{' '}
But you can file your claim online, within 30 days, through the
<va-link
external
href={BTSSS_PORTAL_URL}
text="Beneficiary Travel Self Service System (BTSSS)"
/>
. Or you can use VA Form 10-3542 to submit a claim by mail or in
person.
</p>
</va-additional-info>
<VaButtonPair
class="vads-u-margin-y--2"
continue
onPrimaryClick={e => handlers.onNext(e)}
onSecondaryClick={e => handlers.onBack(e)}
onPrimaryClick={handlers.onNext}
onSecondaryClick={handlers.onBack}
/>
</div>
);
};

AddressPage.propTypes = {
handlers: PropTypes.shape({
onBack: PropTypes.func,
onNext: PropTypes.func,
}),
address: PropTypes.object,
pageIndex: PropTypes.number,
setIsUnsupportedClaimType: PropTypes.func,
setPageIndex: PropTypes.func,
setYesNo: PropTypes.func,
yesNo: PropTypes.object,
};

export default AddressPage;
142 changes: 132 additions & 10 deletions src/applications/travel-pay/components/submit-flow/pages/MileagePage.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,150 @@
import React from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';

import { VaButtonPair } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import {
VaButtonPair,
VaRadio,
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { focusElement, scrollToTop } from 'platform/utilities/ui';

const MileagePage = ({ handlers }) => {
import { formatDateTime } from '../../../util/dates';
import { BTSSS_PORTAL_URL } from '../../../constants';

const MileagePage = ({
appointment,
pageIndex,
setPageIndex,
yesNo,
setYesNo,
setIsUnsupportedClaimType,
}) => {
useEffect(() => {
focusElement('h1', {}, 'va-radio');
scrollToTop('topScrollElement');
}, []);

const [formattedDate, formattedTime] = formatDateTime(
appointment.vaos.apiData.start,
);

const [requiredAlert, setRequiredAlert] = useState(false);

const handlers = {
onNext: () => {
if (!yesNo.mileage) {
setRequiredAlert(true);
} else if (yesNo.mileage !== 'yes') {
setIsUnsupportedClaimType(true);
} else {
setIsUnsupportedClaimType(false);
setPageIndex(pageIndex + 1);
}
},
onBack: () => {
setPageIndex(pageIndex - 1);
},
};
return (
<div>
<h1>Mileage page</h1>
<VaRadio
use-forms-pattern="single"
form-heading="Are you claiming only mileage?"
form-heading-level={1}
id="mileage"
onVaValueChange={e => {
setYesNo({ ...yesNo, mileage: e.detail.value });
}}
value={yesNo.mileage}
data-testid="mileage-test-id"
error={requiredAlert ? 'You must make a selection to continue.' : null}
header-aria-describedby={null}
hint=""
label=""
label-header-level=""
>
<div slot="form-description">
<hr className="vads-u-margin-y--0" />
<p>
{' '}
<strong>
{formattedDate} {formattedTime} at{' '}
{appointment.vaos.apiData.location.attributes.name}
</strong>
</p>
<p>{appointment.vaos.apiData.reasonForAppointment}</p>
<hr className="vads-u-margin-y--0" />
</div>
<va-radio-option
label="Yes"
value="yes"
key="mileage-yes"
name="mileage"
checked={yesNo.mileage === 'yes'}
/>
<va-radio-option
key="mileage-no"
name="mileage"
checked={yesNo.mileage === 'no'}
label="No"
value="no"
/>
</VaRadio>

<va-additional-info
class="vads-u-margin-y--3"
trigger="How do we calculate mileage"
>
<ul>
<li>We pay round-trip mileage for your scheduled appointments.</li>
<li>
We may only pay return mileage for unscheduled appointments, like
walk-ins and labs.
</li>
</ul>
<va-link
external
href="https://www.va.gov/resources/reimbursed-va-travel-expenses-and-mileage-rate/#mileage-reimbursement-rate"
text="Check current mileage rates"
/>
</va-additional-info>

<va-additional-info
class="vads-u-margin-bottom--3"
trigger="If you have other expenses to claim"
>
<p>
<strong>
If you need to submit receipts for other expenses like tolls, meals,
or lodging, you can’t file a claim in this tool right now.
</strong>{' '}
But you can file your claim online, within 30 days, through the{' '}
<va-link
external
href={BTSSS_PORTAL_URL}
text="Beneficiary Travel Self Service System (BTSSS)"
/>
. Or you can use VA Form 10-3542 to submit a claim by mail or in
person.
</p>
</va-additional-info>

<VaButtonPair
class="vads-u-margin-y--2"
continue
onPrimaryClick={e => handlers.onNext(e)}
onSecondaryClick={e => handlers.onBack(e)}
onPrimaryClick={handlers.onNext}
onSecondaryClick={handlers.onBack}
/>
</div>
);
};

MileagePage.propTypes = {
handlers: PropTypes.shape({
onBack: PropTypes.func,
onNext: PropTypes.func,
}),
appointment: PropTypes.object,
pageIndex: PropTypes.number,
setIsUnsupportedClaimType: PropTypes.func,
setPageIndex: PropTypes.func,
setYesNo: PropTypes.func,
yesNo: PropTypes.object,
};

export default MileagePage;
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ const UnsupportedClaimTypePage = ({
setIsUnsupportedClaimType,
setPageIndex,
}) => {
const onBack = e => {
e.preventDefault();
const onBack = () => {
setIsUnsupportedClaimType(false);
setPageIndex(pageIndex);
};
Expand All @@ -17,11 +16,7 @@ const UnsupportedClaimTypePage = ({
<h1 tabIndex="-1">
We can’t file this type of travel reimbursement claim
</h1>
<va-button
class="vads-u-margin-y--2"
text="Back"
onClick={e => onBack(e)}
/>
<va-button class="vads-u-margin-y--2" text="Back" onClick={onBack} />
</div>
);
};
Expand Down
Loading

0 comments on commit 26aaef5

Please sign in to comment.