diff --git a/src/containers/SearchPage/SearchPage.duck.js b/src/containers/SearchPage/SearchPage.duck.js index fc312014..06154f13 100644 --- a/src/containers/SearchPage/SearchPage.duck.js +++ b/src/containers/SearchPage/SearchPage.duck.js @@ -10,6 +10,7 @@ export const SEARCH_LISTINGS_ERROR = 'app/SearchPage/SEARCH_LISTINGS_ERROR'; const initialState = { searchParams: null, + searchInProgress: false, searchListingsError: null, currentPageResultIds: [], }; @@ -20,13 +21,19 @@ const listingPageReducer = (state = initialState, action = {}) => { const { type, payload } = action; switch (type) { case SEARCH_LISTINGS_REQUEST: - return { ...state, searchParams: payload.searchParams, searchListingsError: null }; + return { + ...state, + searchParams: payload.searchParams, + searchInProgress: true, + currentPageResultIds: [], + searchListingsError: null, + }; case SEARCH_LISTINGS_SUCCESS: - return { ...state, currentPageResultIds: resultIds(payload.data) }; + return { ...state, searchInProgress: false, currentPageResultIds: resultIds(payload.data) }; case SEARCH_LISTINGS_ERROR: // eslint-disable-next-line no-console console.error(payload); - return { ...state, searchListingsError: payload }; + return { ...state, searchInProgress: false, searchListingsError: payload }; default: return state; } @@ -58,8 +65,8 @@ export const searchListings = searchParams => return sdk.listings .search(searchParams) .then(response => { - dispatch(searchListingsSuccess(response)); dispatch(showListingsSuccess(response)); + dispatch(searchListingsSuccess(response)); return response; }) .catch(e => { diff --git a/src/containers/SearchPage/SearchPage.js b/src/containers/SearchPage/SearchPage.js index cde144b3..8ea0c9a5 100644 --- a/src/containers/SearchPage/SearchPage.js +++ b/src/containers/SearchPage/SearchPage.js @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react'; import classNames from 'classnames'; -import { intlShape, injectIntl } from 'react-intl'; +import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import config from '../../config'; import { parse } from '../../util/urlHelpers'; @@ -18,35 +18,45 @@ import { searchListings } from './SearchPage.duck'; import css from './SearchPage.css'; export const SearchPageComponent = props => { - const { tab, listings, searchParams, searchListingsError, intl } = props; + const { tab, listings, searchParams, searchInProgress, searchListingsError } = props; const filtersClassName = classNames(css.filters, { [css.open]: tab === 'filters' }); const listingsClassName = classNames(css.listings, { [css.open]: tab === 'listings' }); const mapClassName = classNames(css.map, { [css.open]: tab === 'map' }); const currencyConfig = config.currencyConfig; - const searchWasDone = searchParams && searchParams.address; + const searchWasDone = !searchInProgress && searchParams && searchParams.address; - const searchErrorMessage = intl.formatMessage({ id: 'SearchPage.searchError' }); - const resultsFoundMessage = intl.formatMessage( - { id: 'SearchPage.foundResults' }, - { - count: listings.length, - address: searchParams && searchParams.address ? searchParams.address : '', - } + const searchError = ( +

+ +

); - const noResultsMessage = intl.formatMessage( - { id: 'SearchPage.noResults' }, - { - address: searchParams && searchParams.address ? searchParams.address : '', - } + + const resultsFound = ( +

+ +

+ ); + + const noResults = ( +

+ +

+ ); + + const loadingResults = ( +

+ +

); return ( - {searchListingsError ?

{searchErrorMessage}

: null} - {searchWasDone && listings.length > 0 ?

{resultsFoundMessage}

: null} - {searchWasDone && listings.length === 0 ?

{noResultsMessage}

: null} + {searchListingsError ? searchError : null} + {searchWasDone && listings.length > 0 ? resultsFound : null} + {searchWasDone && listings.length === 0 ? noResults : null} + {searchInProgress ? loadingResults : null}
@@ -77,26 +87,32 @@ SearchPageComponent.defaultProps = { searchListingsError: null, }; -const { array, oneOf, object, instanceOf } = PropTypes; +const { array, oneOf, object, instanceOf, bool } = PropTypes; SearchPageComponent.propTypes = { tab: oneOf(['filters', 'listings', 'map']).isRequired, listings: array, searchParams: object, + searchInProgress: bool.isRequired, searchListingsError: instanceOf(Error), - intl: intlShape.isRequired, }; const mapStateToProps = state => { - const { searchParams, searchListingsError, currentPageResultIds } = state.SearchPage; + const { + searchParams, + searchInProgress, + searchListingsError, + currentPageResultIds, + } = state.SearchPage; return { listings: getListingsById(state.data, currentPageResultIds), searchParams, + searchInProgress, searchListingsError, }; }; -const SearchPage = connect(mapStateToProps)(injectIntl(SearchPageComponent)); +const SearchPage = connect(mapStateToProps)(SearchPageComponent); SearchPage.loadData = (params, search) => { const queryParams = parse(search, { diff --git a/src/containers/SearchPage/SearchPage.test.js b/src/containers/SearchPage/SearchPage.test.js index a64c1771..6c0e2b04 100644 --- a/src/containers/SearchPage/SearchPage.test.js +++ b/src/containers/SearchPage/SearchPage.test.js @@ -19,7 +19,12 @@ const { LatLng } = types; describe('SearchPageComponent', () => { it('matches snapshot', () => { const tree = renderShallow( - v} dispatch={() => null} intl={fakeIntl} /> + v} + dispatch={() => null} + intl={fakeIntl} + searchInProgress={false} + /> ); expect(tree).toMatchSnapshot(); }); diff --git a/src/translations/en.json b/src/translations/en.json index 59ebcea9..821b5443 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -20,6 +20,7 @@ "PageLayout.authInfoFailed": "Could not get authentication information.", "PageLayout.logoutFailed": "Logout failed. Please try again.", "SearchPage.searchError": "Search failed. Please try again.", - "SearchPage.foundResults": "{count} listings found near {address}.", - "SearchPage.noResults": "Could not find any listings near {address}." + "SearchPage.foundResults": "{count, number} {count, plural, one {listing} other {listings}} found.", + "SearchPage.noResults": "Could not find any listings.", + "SearchPage.loadingResults": "Loading search results..." }