Skip to content

Commit

Permalink
Edm 493 521 finalize lacs UI (#34130)
Browse files Browse the repository at this point in the history
* update capitalizeFirstLetter function, update word casing where needed

* change UI for result details based on lac type, fix element spacing

* refactor capitalizeFirstLetter function

* scroll to top of each lac page when mounted

* Fix table width issue and add pagination

* make FAQs single select, change React bindings to web-components

* change react bindings to web components

* focus correctly on faqs | cleanup markup styles

---------

Co-authored-by: Nick Hibbits <[email protected]>
  • Loading branch information
nicholashibbits and nicholashibbits authored Jan 17, 2025
1 parent 0d62115 commit c0e9012
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 83 deletions.
52 changes: 32 additions & 20 deletions src/applications/gi/components/LicenseCertificationAdminInfo.jsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,51 @@
import {
VaIcon,
VaLink,
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import React from 'react';
import { capitalizeFirstLetter } from '../utils/helpers';

function LicenseCertificationAdminInfo({ institution }) {
function LicenseCertificationAdminInfo({ institution, type }) {
const { name, mailingAddress } = institution;

return (
<div>
<h3 className="vads-u-margin-top--1p5">Admin Info</h3>
<h3 className="vads-u-margin-top--1p5 vads-u-margin-bottom--2">
Admin info
</h3>
<div className="name-wrapper vads-u-display--flex vads-u-align-items--center">
<VaIcon
className="vads-u-padding-right--1"
<va-icon
class="vads-u-padding-right--1"
icon="location_city"
size={3}
/>
<p>{name}</p>
<p className="vads-u-margin-y--0">{capitalizeFirstLetter(name)}</p>
</div>
<p>The following is the headquarters address.</p>
{type === 'Certification' ? (
<p>
Certification tests are available to be taken nationally, search for a
testing site near you.
</p>
) : (
<>
<p>The following is the headquarters address.</p>

<p className="va-address-block">
{mailingAddress.address1}
<br />
{mailingAddress.city}, {mailingAddress.state} {mailingAddress.zip}
<br />
</p>
<p className="va-address-block">
{capitalizeFirstLetter(mailingAddress.address1)}
<br />
{capitalizeFirstLetter(mailingAddress.city)}, {mailingAddress.state}{' '}
{mailingAddress.zip}
<br />
</p>
</>
)}
<p className="vads-u-padding-top--1p5 vads-u-margin-bottom--1">
Print and fill out form Request for Reimbursement of Licensing or
Certification Test Fees. Send the completed application to the Regional
Processing Office for your region listed in the form.
</p>
<VaLink
text="Get VA Form22-0803 to download"
href="../../../find-forms/about-form-22-0803/"
/>
<p>
<va-link
text="Get VA Form22-0803 to download"
href="../../../find-forms/about-form-22-0803/"
/>
</p>
</div>
);
}
Expand Down
61 changes: 58 additions & 3 deletions src/applications/gi/components/LicenseCertificationTestInfo.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,64 @@
import React from 'react';
import React, { useLayoutEffect, useState } from 'react';
import { VaPagination } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { formatCurrency } from '../utils/helpers';

function LcTestInfo({ tests }) {
const [currentPage, setCurrentPage] = useState(1);

useLayoutEffect(
// eslint-disable-next-line consistent-return
() => {
const observer = new MutationObserver(() => {
const vaTableInner = document.querySelector(
'.table-wrapper va-table-inner',
);
if (vaTableInner?.shadowRoot) {
const { shadowRoot } = vaTableInner;
const usaTable = shadowRoot.querySelector('.usa-table');
if (usaTable) {
usaTable.style.width = '100%';
}
}
});
const vaTable = document.querySelector('.table-wrapper va-table');
if (vaTable) {
observer.observe(vaTable, {
attributes: true,
childList: true,
subtree: true,
});
}
return () => observer.disconnect();
},
[tests],
);

const itemsPerPage = 10;

const totalPages = Math.ceil(tests.length / itemsPerPage);
const currentResults =
tests.length > itemsPerPage
? tests.slice(
(currentPage - 1) * itemsPerPage,
currentPage * itemsPerPage,
)
: tests;

const handlePageChange = page => {
setCurrentPage(page);
};

return (
<>
<h3>Test info</h3>
<div className="table-wrapper">
<va-table table-type="borderless" stacked>
<va-table-row slot="headers">
<span>Test Name</span>
<span>Fees</span>
</va-table-row>
{tests &&
tests.map((test, index) => {
{currentResults &&
currentResults.map((test, index) => {
return (
<va-table-row key={index}>
<span>{test.name}</span>
Expand All @@ -20,6 +67,14 @@ function LcTestInfo({ tests }) {
);
})}
</va-table>
{tests.length > itemsPerPage && (
<VaPagination
onPageSelect={e => handlePageChange(e.detail.page)}
page={currentPage}
pages={totalPages}
maxPageListLength={itemsPerPage}
/>
)}
</div>
</>
);
Expand Down
71 changes: 41 additions & 30 deletions src/applications/gi/containers/LicenseCertificationSearchPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ import React, { useEffect, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import {
VaAccordion,
VaAccordionItem,
VaLink,
VaLoadingIndicator,
VaModal,
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { VaModal } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import LicenseCertificationSearchForm from '../components/LicenseCertificationSearchForm';
import { handleLcResultsSearch, updateQueryParam } from '../utils/helpers';
import { fetchLicenseCertificationResults } from '../actions';
Expand Down Expand Up @@ -39,7 +33,7 @@ const faqs = [
'How do I get reimbursed for the licenses, certifications, and prep courses?',
answer: (
<>
<VaLink
<va-link
text="Find out how to get reimbursed for licenses, certifications and prep courses"
href="../about-gi-bill-benefits/how-to-use-benefits/licensing-and-certification-tests/"
/>
Expand All @@ -52,7 +46,7 @@ const faqs = [
</p>
<br />
<br />
<VaLink
<va-link
text="Get VA Form22-0803 to download"
href="../find-forms/about-form-22-0803/"
/>
Expand Down Expand Up @@ -94,12 +88,9 @@ function LicenseCertificationSearchPage({
message: '',
});

const handleUpdateQueryParam = () => updateQueryParam(history, location);

const handleReset = callback => {
history.replace('/lc-search');
callback?.();
};
useEffect(() => {
window.scrollTo(0, 0);
}, []);

useEffect(
() => {
Expand All @@ -110,6 +101,27 @@ function LicenseCertificationSearchPage({
[hasFetchedOnce, dispatchFetchLicenseCertificationResults],
);

const handleFaqClick = index => {
const element = document.getElementById(`faq-${index}`);
element?.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
};

const handleKeyDown = (event, index) => {
if (event.key === 'Enter' || event.key === ' ') {
handleFaqClick(index);
}
};

const handleUpdateQueryParam = () => updateQueryParam(history, location);

const handleReset = callback => {
history.replace('/lc-search');
callback?.();
};

const handleShowModal = (changedField, message, callback) => {
return setModal({
visible: true,
Expand All @@ -136,12 +148,7 @@ function LicenseCertificationSearchPage({

return (
<div className="lc-page-wrapper">
{fetchingLc && (
<VaLoadingIndicator
// data-testid="loading-indicator"
message="Loading..."
/>
)}
{fetchingLc && <va-loading-indicator message="Loading..." />}
{!fetchingLc &&
hasFetchedOnce &&
lcResults.length !== 0 && (
Expand Down Expand Up @@ -175,16 +182,24 @@ function LicenseCertificationSearchPage({
/>
</div>
<div className="row">
<h2 className="vads-u-margin-y--0">FAQs</h2>
<VaAccordion>
<h2 className="vads-u-margin-y--0 vads-u-padding-bottom--2">
FAQs
</h2>
<va-accordion open-single>
{faqs.map((faq, index) => {
return (
<VaAccordionItem header={faq.question} key={index}>
<va-accordion-item
id={`faq-${index}`}
header={faq.question}
key={index}
onClick={() => handleFaqClick(index)}
onKeyDown={e => handleKeyDown(e, index)}
>
{faq.answer}
</VaAccordionItem>
</va-accordion-item>
);
})}
</VaAccordion>
</va-accordion>
</div>
<VaModal
forcedModal={false}
Expand All @@ -194,7 +209,6 @@ function LicenseCertificationSearchPage({
modalTitle={`Are you sure you want to change the ${
modal.changedField
} field?`}
// initialFocusSelector={initialFocusSelector}
onCloseEvent={toggleModal}
onPrimaryButtonClick={() => {
modal.callback();
Expand All @@ -203,7 +217,6 @@ function LicenseCertificationSearchPage({
primaryButtonText="Continue to change"
onSecondaryButtonClick={toggleModal}
secondaryButtonText="Go Back"
// status={status}
visible={modal.visible}
>
<p>{modal.message}</p>
Expand All @@ -219,14 +232,12 @@ LicenseCertificationSearchPage.propTypes = {
fetchingLc: PropTypes.bool.isRequired,
hasFetchedOnce: PropTypes.bool.isRequired,
lcResults: PropTypes.array,
// error: Proptypes // verify error Proptypes
};

const mapStateToProps = state => ({
lcResults: state.licenseCertificationSearch.lcResults,
fetchingLc: state.licenseCertificationSearch.fetchingLc,
hasFetchedOnce: state.licenseCertificationSearch.hasFetchedOnce,
// error: // create error state in redux store
});

const mapDispatchToProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { useParams } from 'react-router-dom';
import { VaLoadingIndicator } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { fetchLcResult } from '../actions';
import LicenseCertificationAdminInfo from '../components/LicenseCertificationAdminInfo';
import LicenseCertificationTestInfo from '../components/LicenseCertificationTestInfo';
Expand All @@ -16,6 +15,8 @@ function LicenseCertificationSearchResult({
const { id } = useParams();

useEffect(() => {
window.scrollTo(0, 0);

if (!hasFetchedResult) {
dispatchFetchLcResult(id);
}
Expand All @@ -25,22 +26,20 @@ function LicenseCertificationSearchResult({

return (
<div>
{fetchingLcResult && (
<VaLoadingIndicator
// data-testid="loading-indicator"
message="Loading..."
/>
)}
{fetchingLcResult && <va-loading-indicator message="Loading..." />}
{!fetchingLcResult &&
institution &&
tests && ( // better check for empty resultInfo
institution &&
tests && (
<section className="lc-result-details vads-u-display--flex vads-u-flex-direction--column vads-u-padding-x--2p5 mobile-lg:vads-u-padding-x--2">
<div className="row">
<h1 className="mobile-lg:vads-u-text-align--left">{lacNm}</h1>
<h2 className="vads-u-margin-top--0">{eduLacTypeNm}</h2>
</div>
<div className="row">
<LicenseCertificationAdminInfo institution={institution} />
<LicenseCertificationAdminInfo
institution={institution}
type={eduLacTypeNm}
/>
</div>
<div className="row">
<LicenseCertificationTestInfo tests={tests} />
Expand Down
Loading

0 comments on commit c0e9012

Please sign in to comment.