diff --git a/config/webpack.dev.config.js b/config/webpack.dev.config.js index 838a3ac7f3d0..816b2c90bbd0 100644 --- a/config/webpack.dev.config.js +++ b/config/webpack.dev.config.js @@ -52,7 +52,7 @@ function generateWebpackDevConfig(buildOptions) { }, port: buildOptions.port, host: buildOptions.host, - client: { webSocketURL }, + client: { webSocketURL, overlay: false }, devMiddleware: { publicPath: '/generated/', stats: { diff --git a/src/applications/facility-locator/actions/mapbox/genBBoxFromAddress.js b/src/applications/facility-locator/actions/mapbox/genBBoxFromAddress.js index 20cf128f8f9a..050c518a0095 100644 --- a/src/applications/facility-locator/actions/mapbox/genBBoxFromAddress.js +++ b/src/applications/facility-locator/actions/mapbox/genBBoxFromAddress.js @@ -90,6 +90,7 @@ export const genBBoxFromAddress = (query, expandedRadius = false) => { Math.max(featureBox[3], coordinates[1] + searchBoundingRadius), ]; } + const radius = radiusFromBoundingBox( features?.[0]?.bbox ? features diff --git a/src/applications/facility-locator/api/LocatorApi.js b/src/applications/facility-locator/api/LocatorApi.js index e768fa7341be..66c9b180a60b 100644 --- a/src/applications/facility-locator/api/LocatorApi.js +++ b/src/applications/facility-locator/api/LocatorApi.js @@ -133,7 +133,12 @@ class LocatorApi { fetch(url, api.settings) .then(res => res.json()) .then( - data => resolve(data.data.map(specialty => specialty.attributes)), + data => { + if (data.errors?.length) { + return reject(data.errors[0]); + } + return resolve(data.data.map(specialty => specialty.attributes)); + }, error => reject(error), ); }); diff --git a/src/applications/facility-locator/components/ControlResultsHolder.jsx b/src/applications/facility-locator/components/ControlResultsHolder.jsx new file mode 100644 index 000000000000..2bd534b605d3 --- /dev/null +++ b/src/applications/facility-locator/components/ControlResultsHolder.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +function ControlResultsHolder({ children, isSmallDesktop }) { + // If the screen is smaller than small desktop we just return the children + if (!isSmallDesktop) { + return children; + } + + return
{children}
; +} + +ControlResultsHolder.propTypes = { + children: PropTypes.node.isRequired, + isSmallDesktop: PropTypes.bool.isRequired, +}; + +export default ControlResultsHolder; diff --git a/src/applications/facility-locator/components/EmergencyCareAlert.jsx b/src/applications/facility-locator/components/EmergencyCareAlert.jsx new file mode 100644 index 000000000000..93e9a1f676f0 --- /dev/null +++ b/src/applications/facility-locator/components/EmergencyCareAlert.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +function EmergencyCareAlert({ shouldShow = false }) { + if (!shouldShow) { + return null; + } + return ( + + Note: If you think your life or health is in danger, call{' '} + or go to the nearest emergency department + right away. + + ); +} + +EmergencyCareAlert.propTypes = { + shouldShow: PropTypes.bool, +}; + +export default EmergencyCareAlert; diff --git a/src/applications/facility-locator/components/PpmsServiceError.jsx b/src/applications/facility-locator/components/PpmsServiceError.jsx new file mode 100644 index 000000000000..06f3e5ecbe86 --- /dev/null +++ b/src/applications/facility-locator/components/PpmsServiceError.jsx @@ -0,0 +1,53 @@ +import React, { useEffect, useRef } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { setFocus } from '../utils/helpers'; + +function PpmsServiceError({ currentQuery }) { + const shownAlert = useRef(null); + useEffect( + () => { + if ( + shownAlert.current && + currentQuery?.fetchSvcsError && + !shownAlert.current.hasAttribute('tabindex') + ) { + setTimeout(() => { + // We need the timeout because the alert is rendered after the error is set + // and we need to wait for the alert to be rendered before setting focus + // Also, the required field (facilityType) steals focus immediately no matter how it is set + setFocus(shownAlert.current); + }, 50); + } + }, + [shownAlert, currentQuery], + ); + if (currentQuery?.fetchSvcsError) { + return ( + +

We’ve run into a problem

+

+ Community provider searches aren’t working right now. Try again later. +

+
+ ); + } + return null; +} + +PpmsServiceError.propTypes = { + currentQuery: PropTypes.object, +}; + +const mapStateToProps = state => { + return { + currentQuery: state.searchQuery, + }; +}; + +export default connect(mapStateToProps)(PpmsServiceError); diff --git a/src/applications/facility-locator/components/SearchControls.jsx b/src/applications/facility-locator/components/SearchControls.jsx index fcc3b4aa121c..fe681d416713 100644 --- a/src/applications/facility-locator/components/SearchControls.jsx +++ b/src/applications/facility-locator/components/SearchControls.jsx @@ -8,7 +8,6 @@ import { } from '@department-of-veterans-affairs/component-library/dist/react-bindings'; import { healthServices, - benefitsServices, urgentCareServices, facilityTypesOptions, emergencyCareServices, @@ -18,6 +17,7 @@ import { LocationType } from '../constants'; import ServiceTypeAhead from './ServiceTypeAhead'; import { setFocus } from '../utils/helpers'; import { SearchControlsTypes } from '../types'; +import ServicesLoadingOrShow from './ServicesLoadingOrShow'; const SearchControls = props => { const { @@ -31,6 +31,7 @@ const SearchControls = props => { const [selectedServiceType, setSelectedServiceType] = useState(null); const locationInputFieldRef = useRef(null); + const facilityTypeDropdownRef = useRef(null); const onlySpaces = str => /^\s+$/.test(str); @@ -55,6 +56,8 @@ const SearchControls = props => { onChange({ facilityType: e.target.value, serviceType: null, + // Since the facility type may cause an error (PPMS), reset it if the type is changed + fetchSvcsError: null, }); }; @@ -68,6 +71,7 @@ const SearchControls = props => { const handleSubmit = e => { e.preventDefault(); + e.stopPropagation(); const { facilityType, @@ -77,7 +81,6 @@ const SearchControls = props => { searchString, specialties, } = currentQuery; - let analyticsServiceType = serviceType; const updateReduxState = propName => { @@ -120,7 +123,6 @@ const SearchControls = props => { 'fl-search-svc-type': analyticsServiceType, 'fl-current-zoom-depth': zoomLevel, }); - onSubmit(); }; @@ -158,7 +160,7 @@ const SearchControls = props => { htmlFor="street-city-state-zip" id="street-city-state-zip-label" > - City, state or postal code{' '} + Zip code or city, state{' '} (*Required) {geolocationInProgress ? ( @@ -181,7 +183,7 @@ const SearchControls = props => { {showError && ( Error - Please fill in a city, state, or postal code. + Please fill in a zip code or city, state. )}
@@ -193,11 +195,10 @@ const SearchControls = props => { onChange={handleQueryChange} onBlur={handleLocationBlur} value={searchString} - title="Your location: Street, City, State or Postal code" /> {searchString?.length > 0 && (