src/applications/gi/containers/SearchPage.jsx
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable react/prop-types */
/* eslint-disable react/jsx-no-bind */
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { useHistory } from 'react-router-dom';
import classNames from 'classnames';
import recordEvent from 'platform/monitoring/record-event';
import SearchTabs from '../components/search/SearchTabs';
import { TABS } from '../constants';
import NameSearchResults from './search/NameSearchResults';
import LocationSearchResults from './search/LocationSearchResults';
import {
isSearchByLocationPage,
isSearchByNamePage,
isSmallScreen,
setDocumentTitle,
} from '../utils/helpers';
import NameSearchForm from './search/NameSearchForm';
import LocationSearchForm from './search/LocationSearchForm';
import AccordionItem from '../components/AccordionItem';
import { getSearchQueryChanged, updateUrlParams } from '../selectors/search';
import GIBillHeaderInfo from '../components/GIBillHeaderInfo';
import { changeSearchTab, setError } from '../actions';
export function SearchPage({
dispatchChangeSearchTab,
search,
preview,
filters,
dispatchError,
}) {
const isLandscape = () => {
const islandscape = matchMedia('(orientation: landscape)');
const mobileDevice = matchMedia(
'(min-device-width: 320px) and (max-device-width: 844px) and (-webkit-min-device-pixel-ratio: 2)',
);
if (islandscape.matches === true && mobileDevice.matches === true)
return true;
return false;
};
const history = useHistory();
const { tab, error, query } = search;
const [smallScreen, setSmallScreen] = useState(isSmallScreen());
const [landscape, setLandscape] = useState(isLandscape());
const [accordions, setAccordions] = useState({
[TABS.name]: tab === TABS.name,
[TABS.location]: tab === TABS.location,
});
const { version } = preview;
const tabChange = selectedTab => {
recordEvent({
event: 'nav-tab-click',
'tab-text': `Search by ${selectedTab}`,
});
dispatchChangeSearchTab(selectedTab);
updateUrlParams(history, selectedTab, search.query, filters, version);
};
const initializeTab = newTab => {
if (isSearchByNamePage() && newTab !== TABS.name) {
dispatchChangeSearchTab(TABS.name);
} else if (isSearchByLocationPage() && newTab !== TABS.location) {
dispatchChangeSearchTab(TABS.location);
}
};
const deriveTabName = () => {
if (isSearchByNamePage()) {
return TABS.name.toUpperCase();
}
if (isSearchByLocationPage()) {
return TABS.location.toUpperCase();
}
return 'Not-Yet-Implemented-deriveTabName';
};
const handleBrowserButtonClick = () => {
const tabName = deriveTabName();
window.addEventListener('popstate', e => {
e?.preventDefault();
recordEvent({
event: 'back-button-click',
'tab-text': `Search by ${tabName}`,
});
if (isSearchByNamePage()) {
dispatchChangeSearchTab(TABS.name);
} else if (isSearchByLocationPage()) {
dispatchChangeSearchTab(TABS.location);
}
});
};
useEffect(() => {
setDocumentTitle();
const checkSize = () => {
setSmallScreen(isSmallScreen());
setLandscape(isLandscape());
};
window.addEventListener('resize', checkSize);
if (getSearchQueryChanged(search.query)) {
updateUrlParams(history, search.tab, search.query, filters, version);
}
initializeTab(search.tab);
handleBrowserButtonClick();
return () => window.removeEventListener('resize', checkSize);
}, []);
const tabbedResults = {
[TABS.name]: <NameSearchResults smallScreen={smallScreen} />,
[TABS.location]: (
<LocationSearchResults smallScreen={smallScreen} landscape={landscape} />
),
};
const accordionChange = (selectedAccordion, expanded) => {
let updated = {
...accordions,
[selectedAccordion]: expanded,
};
if (selectedAccordion === TABS.name && expanded) {
updated = { ...updated, [TABS.location]: false };
} else if (selectedAccordion === TABS.location && expanded) {
updated = { ...updated, [TABS.name]: false };
}
setAccordions(updated);
tabChange(selectedAccordion);
};
const searchPageClasses = classNames('row', {
'no-name-results':
tab === TABS.name && (query.name === '' || query.name === null),
});
return (
<>
<GIBillHeaderInfo />
<span className="search-page">
<div className={searchPageClasses}>
<div className="column medium-screen:vads-u-padding-bottom--2 mobile-lg:vads-u-padding-bottom--0 vads-u-padding-x--0">
{!smallScreen && (
<SearchTabs
onChange={tabChange}
search={search}
dispatchError={dispatchError}
/>
)}
{error && (
<div className="vads-u-padding-top--2">
<va-alert onClose={function noRefCheck() {}} status="warning">
<h3 slot="headline">
The GI Bill Comparison Tool isn’t working right now
</h3>
<div>
We’re sorry. Something went wrong on our end. Please refresh
this page or try searching again.
</div>
</va-alert>
</div>
)}
{!error && !smallScreen && tabbedResults[tab]}
{!error &&
smallScreen && (
<div>
<AccordionItem
button="Search by name"
expanded={accordions[TABS.name]}
onClick={expanded => {
accordionChange(TABS.name, expanded);
}}
>
<NameSearchForm smallScreen />
</AccordionItem>
<AccordionItem
button="Search by location"
expanded={accordions[TABS.location]}
onClick={expanded => {
accordionChange(TABS.location, expanded);
}}
>
<LocationSearchForm smallScreen />
</AccordionItem>
{!error && smallScreen && tabbedResults[tab]}
</div>
)}
</div>
</div>
</span>
</>
);
}
const mapStateToProps = state => ({
autocomplete: state.autocomplete,
eligibility: state.eligibility,
search: state.search,
preview: state.preview,
filters: state.filters,
});
const mapDispatchToProps = {
dispatchChangeSearchTab: changeSearchTab,
dispatchError: setError,
};
export default connect(
mapStateToProps,
mapDispatchToProps,
)(SearchPage);