mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 05:00:43 +10:00
Merge pull request #94 from sharetribe/searchpage-fixes
Search page fixes
This commit is contained in:
commit
7ab44d81ae
4 changed files with 58 additions and 29 deletions
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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 = (
|
||||
<p style={{ color: 'red' }}>
|
||||
<FormattedMessage id="SearchPage.searchError" />
|
||||
</p>
|
||||
);
|
||||
const noResultsMessage = intl.formatMessage(
|
||||
{ id: 'SearchPage.noResults' },
|
||||
{
|
||||
address: searchParams && searchParams.address ? searchParams.address : '',
|
||||
}
|
||||
|
||||
const resultsFound = (
|
||||
<p>
|
||||
<FormattedMessage id="SearchPage.foundResults" values={{ count: listings.length }} />
|
||||
</p>
|
||||
);
|
||||
|
||||
const noResults = (
|
||||
<p>
|
||||
<FormattedMessage id="SearchPage.noResults" />
|
||||
</p>
|
||||
);
|
||||
|
||||
const loadingResults = (
|
||||
<p>
|
||||
<FormattedMessage id="SearchPage.loadingResults" />
|
||||
</p>
|
||||
);
|
||||
|
||||
return (
|
||||
<PageLayout title={`Search page: ${tab}`}>
|
||||
{searchListingsError ? <p style={{ color: 'red' }}>{searchErrorMessage}</p> : null}
|
||||
{searchWasDone && listings.length > 0 ? <p>{resultsFoundMessage}</p> : null}
|
||||
{searchWasDone && listings.length === 0 ? <p>{noResultsMessage}</p> : null}
|
||||
{searchListingsError ? searchError : null}
|
||||
{searchWasDone && listings.length > 0 ? resultsFound : null}
|
||||
{searchWasDone && listings.length === 0 ? noResults : null}
|
||||
{searchInProgress ? loadingResults : null}
|
||||
<div className={css.container}>
|
||||
<div className={filtersClassName}>
|
||||
<FilterPanel />
|
||||
|
|
@ -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, {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,12 @@ const { LatLng } = types;
|
|||
describe('SearchPageComponent', () => {
|
||||
it('matches snapshot', () => {
|
||||
const tree = renderShallow(
|
||||
<SearchPageComponent onLoadListings={v => v} dispatch={() => null} intl={fakeIntl} />
|
||||
<SearchPageComponent
|
||||
onLoadListings={v => v}
|
||||
dispatch={() => null}
|
||||
intl={fakeIntl}
|
||||
searchInProgress={false}
|
||||
/>
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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..."
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue