Skip to content

Commit

Permalink
edm-433 national exams ui update (#34016)
Browse files Browse the repository at this point in the history
  • Loading branch information
flex2016 authored Jan 9, 2025
1 parent bd090bf commit 6e0efb2
Show file tree
Hide file tree
Showing 9 changed files with 604 additions and 257 deletions.
42 changes: 37 additions & 5 deletions src/applications/gi/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,51 @@ export const FETCH_INSTITUTION_PROGRAMS_SUCCEEDED =
export const FETCH_NATIONAL_EXAMS_FAILED = 'FETCH_NATIONAL_EXAMS_FAILED ';
export const FETCH_NATIONAL_EXAMS_STARTED = 'FETCH_NATIONAL_EXAMS_STARTED';
export const FETCH_NATIONAL_EXAMS_SUCCEEDED = 'FETCH_NATIONAL_EXAMS_SUCCEEDED';
export const FETCH_NATIONAL_EXAM_DETAILS_FAILED =
'FETCH_NATIONAL_EXAM_DETAILS_FAILED ';
export const FETCH_NATIONAL_EXAM_DETAILS_STARTED =
'FETCH_NATIONAL_EXAM_DETAILS_STARTED';
export const FETCH_NATIONAL_EXAM_DETAILS_SUCCEEDED =
'FETCH_NATIONAL_EXAM_DETAILS_SUCCEEDED';

export const fetchNationalExamDetails = id => {
const url = `http://localhost:3000/v1/gi/lcpe/exams/${id}`;
// const url = `${api.url}/lce?type=${type}`;
return async dispatch => {
dispatch({ type: FETCH_NATIONAL_EXAM_DETAILS_STARTED });

try {
const res = await fetch(url, apiV0.settings);
if (!res.ok) {
throw new Error(res.statusText);
}
const { exam } = await res.json();
dispatch({
type: FETCH_NATIONAL_EXAM_DETAILS_SUCCEEDED,
payload: exam,
});
} catch (err) {
dispatch({
type: FETCH_NATIONAL_EXAM_DETAILS_FAILED,
payload: err.message,
});
}
};
};

export const fetchNationalExams = type => {
const url = `${api.url}/lce?type=${type}`;
export const fetchNationalExams = () => {
const url = `http://localhost:3000/v1/gi/lcpe/exams`;
// const url = `${api.url}/lce?type=${type}`;
return async dispatch => {
dispatch({ type: FETCH_NATIONAL_EXAMS_STARTED });

try {
const res = await fetch(url, api.settings);
const res = await fetch(url, apiV0.settings);
if (!res.ok) {
throw new Error(res.statusText);
}
const { data } = await res.json();
dispatch({ type: FETCH_NATIONAL_EXAMS_SUCCEEDED, payload: data });
const { exams } = await res.json();
dispatch({ type: FETCH_NATIONAL_EXAMS_SUCCEEDED, payload: exams });
} catch (err) {
dispatch({
type: FETCH_NATIONAL_EXAMS_FAILED,
Expand Down
211 changes: 211 additions & 0 deletions src/applications/gi/containers/NationalExamDetails.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import React, { useEffect, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { useParams } from 'react-router-dom';
import {
VaIcon,
VaLink,
VaAlert,
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { fetchNationalExamDetails } from '../actions';

const NationalExamDetails = () => {
const dispatch = useDispatch();
const { examId } = useParams();
const [isMobile, setIsMobile] = useState(false);

const { examDetails, loadingDetails, error } = useSelector(
state => state.nationalExams,
);

useEffect(
() => {
window.scrollTo(0, 0);
dispatch(fetchNationalExamDetails(examId));
},
[examId, dispatch],
);

useEffect(() => {
function handleResize() {
const isNowMobile = window.innerWidth < 481;

setIsMobile(isNowMobile);

const vaTableInner = document.querySelector(
'.exams-table va-table-inner',
);
if (vaTableInner?.shadowRoot) {
const { shadowRoot } = vaTableInner;
const usaTable = shadowRoot.querySelector('.usa-table');
if (usaTable) {
if (isNowMobile) {
usaTable.classList.add('usa-table--bordered');
usaTable.classList.remove('usa-table--borderless');
} else {
usaTable.classList.remove('usa-table--bordered');
usaTable.classList.add('usa-table--borderless');
}
}
}
}
window.addEventListener('resize', handleResize);
handleResize();

return () => window.removeEventListener('resize', handleResize);
}, []);

// Remove this once the table width is updated in the component
useEffect(
() => {
setTimeout(() => {
const vaTableInner = document.querySelector(
'.exams-table va-table-inner',
);
if (vaTableInner?.shadowRoot) {
const { shadowRoot } = vaTableInner;
const usaTable = shadowRoot.querySelector('.usa-table');
if (usaTable) {
usaTable.style.width = '100%';
}
}
}, 0);

const observer = new MutationObserver(() => {
const vaTableInner = document.querySelector(
'.exams-table 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('.exams-table va-table');
if (vaTable) {
observer.observe(vaTable, {
attributes: true,
childList: true,
subtree: true,
});
}

return () => observer.disconnect();
},
[examDetails],
);

if (loadingDetails || !examDetails) {
return (
<div className="row vads-u-margin-bottom--8 vads-u-padding--1p5 mobile-lg:vads-u-padding--0">
<va-loading-indicator
label="Loading"
message="Loading your National Exam Details..."
/>
</div>
);
}

if (error) {
return (
<div className="row vads-u-padding--1p5 mobile-lg:vads-u-padding--0">
<VaAlert
style={{ marginTop: '8px', marginBottom: '32px' }}
status="error"
data-e2e-id="alert-box"
>
<h2 slot="headline">
We can’t load the National Exam Details right now
</h2>
<p>
We’re sorry. There’s a problem with our system. Try again later.
</p>
</VaAlert>
</div>
);
}

const { name, tests, institution } = examDetails;

return (
<div className="exam-details-container row vads-u-margin-bottom--8 vads-u-padding--1p5 mobile-lg:vads-u-padding--0">
<h1 className="vads-u-margin-bottom--3">{name}</h1>
<h3 className="vads-u-margin-bottom--2 vads-u-margin-top--0">
Admin Info
</h3>
<div className="provider-info-container vads-u-margin-top--0p5 vads-u-margin-bottom--3">
<span className="vads-u-display--flex vads-u-align-items--center vads-u-margin-bottom--1">
<VaIcon icon="location_city" size={3} />

<span>{institution?.name}</span>
</span>
<span className="vads-u-display--flex vads-u-align-items--center">
<VaIcon icon="public" size={3} />
{/* If your API includes a "web_address", display it */}
{/* <span>{institution?.web_address}</span> */}
</span>
</div>

<div className="address-container vads-u-margin-bottom--3">
The following is the headquarters address.
<p className="va-address-block vads-u-margin-top--1">
{institution?.physicalAddress?.address1}
<br />
{institution.physicalAddress?.city},
{institution.physicalAddress?.state}
{institution.physicalAddress?.zip}
<br />
{institution.physicalAddress?.country}
</p>
</div>

<div>
<p className="vads-u-margin-bottom--0p5">
Print and fill out form Request for Reimbursement of National Exam
Fee. Send the completed application to the Regional Processing Office
for your region listed in the form.
</p>
<div className="vads-u-margin-bottom--4">
<VaLink
href="https://www.va.gov/find-forms/about-form-22-0810/"
text="Get link to VA Form 22-0810 to print"
/>
</div>
</div>
<div className="exams-table">
<h3 className="vads-u-margin-y--0">Test Info</h3>
<va-table table-type={isMobile ? 'bordered' : undefined}>
<va-table-row slot="headers">
<span className="table-header">Fee Description</span>
<span className="table-header">Dates</span>
<span className="table-header">Amount</span>
</va-table-row>
{tests?.map((test, i) => {
if (test.name === 'Blank') {
return null;
}
return (
<va-table-row key={i}>
<span>{test.name}</span>
<span>
{test.beginDate} - {test.endDate}
</span>
<span>
{Number(test.fee).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
})}
</span>
</va-table-row>
);
})}
</va-table>
</div>
</div>
);
};

export default NationalExamDetails;
Loading

0 comments on commit 6e0efb2

Please sign in to comment.