mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 20:53:24 +10:00
SearchPage: react to onBoundschanged event, fetching map listings when props are known.
This commit is contained in:
parent
f835365860
commit
38173dafbb
1 changed files with 66 additions and 29 deletions
|
|
@ -3,8 +3,11 @@ import { FormattedMessage } from 'react-intl';
|
|||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { unionWith } from 'lodash';
|
||||
import { debounce, isEqual, unionWith } from 'lodash';
|
||||
import config from '../../config';
|
||||
import { withFlattenedRoutes } from '../../util/contextHelpers';
|
||||
import { googleLatLngToSDKLatLng, googleBoundsToSDKBounds } from '../../util/googleMaps';
|
||||
import { createResourceLocatorString } from '../../util/routes';
|
||||
import { parse, stringify } from '../../util/urlHelpers';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { getListingsById } from '../../ducks/marketplaceData.duck';
|
||||
|
|
@ -14,11 +17,13 @@ import { SearchMap, ModalInMobile, PageLayout, SearchResultsPanel, Topbar } from
|
|||
import { searchListings, searchMapListings } from './SearchPage.duck';
|
||||
import css from './SearchPage.css';
|
||||
|
||||
// TODO Pagination page size might need to be dynamic on responsive page layouts
|
||||
// Pagination page size might need to be dynamic on responsive page layouts
|
||||
// Current design has max 3 columns 12 is divisible by 2 and 3
|
||||
// So, there's enough cards to fill all columns on full pagination pages
|
||||
const RESULT_PAGE_SIZE = 12;
|
||||
const SHARETRIBE_API_MAX_PAGE_SIZE = 100;
|
||||
const MAX_SEARCH_RESULT_PAGES_ON_MAP = 5;
|
||||
// 100 * 5 = 500 listings are shown on a map.
|
||||
const MAX_SEARCH_RESULT_PAGES_ON_MAP = 5; // 100 * 5 = 500 listings are shown on a map.
|
||||
const DEBOUNCE_MAP_BOUNDS_CHANGE = 500; // bounds_change event is fired too often while dragging
|
||||
|
||||
const pickSearchParamsOnly = params => {
|
||||
const { address, origin, bounds } = params || {};
|
||||
|
|
@ -26,30 +31,52 @@ const pickSearchParamsOnly = params => {
|
|||
};
|
||||
|
||||
export class SearchPageComponent extends Component {
|
||||
componentDidMount() {
|
||||
const { location, onSearchMapListings } = this.props;
|
||||
const searchInURL = parse(location.search, {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onBoundsChanged = debounce(this.onBoundsChanged.bind(this), DEBOUNCE_MAP_BOUNDS_CHANGE);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!isEqual(this.props.location, nextProps.location)) {
|
||||
const { onSearchMapListings } = this.props;
|
||||
const searchInURL = parse(nextProps.location.search, {
|
||||
latlng: ['origin'],
|
||||
latlngBounds: ['bounds'],
|
||||
});
|
||||
const perPage = SHARETRIBE_API_MAX_PAGE_SIZE;
|
||||
const page = 1;
|
||||
const searchParamsForMapResults = { ...searchInURL, page, perPage };
|
||||
|
||||
// Search more listings for map
|
||||
onSearchMapListings(searchParamsForMapResults)
|
||||
.then(response => {
|
||||
const hasNextPage = page < response.data.meta.totalPages &&
|
||||
page < MAX_SEARCH_RESULT_PAGES_ON_MAP;
|
||||
if (hasNextPage) {
|
||||
onSearchMapListings({ ...searchParamsForMapResults, page: page + 1 });
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// In case of error, stop recursive loop and report error.
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`An error (${error} occured while trying to retrieve map listings`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onBoundsChanged(googleMap) {
|
||||
const { flattenedRoutes, history, location } = this.props;
|
||||
const { address, country } = parse(location.search, {
|
||||
latlng: ['origin'],
|
||||
latlngBounds: ['bounds'],
|
||||
});
|
||||
const perPage = SHARETRIBE_API_MAX_PAGE_SIZE;
|
||||
const page = 1;
|
||||
const searchParamsForMapResults = { ...searchInURL, page, perPage };
|
||||
|
||||
// Search more listings
|
||||
onSearchMapListings(searchParamsForMapResults)
|
||||
.then(response => {
|
||||
const hasNextPage = page < response.data.meta.totalPages &&
|
||||
page < MAX_SEARCH_RESULT_PAGES_ON_MAP;
|
||||
if (hasNextPage) {
|
||||
onSearchMapListings({ ...searchParamsForMapResults, page: page + 1 });
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// In case of error, stop recursive loop and report error.
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`An error (${error} occured while trying to retrieve map listings`);
|
||||
});
|
||||
const viewportBounds = googleMap.getBounds();
|
||||
const bounds = googleBoundsToSDKBounds(viewportBounds);
|
||||
const origin = googleLatLngToSDKLatLng(viewportBounds.getCenter());
|
||||
|
||||
const searchParams = { address, origin, bounds, country };
|
||||
history.push(createResourceLocatorString('SearchPage', flattenedRoutes, {}, searchParams));
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
@ -174,7 +201,12 @@ export class SearchPageComponent extends Component {
|
|||
onManageDisableScrolling={onManageDisableScrolling}
|
||||
>
|
||||
<div className={css.map}>
|
||||
<SearchMap bounds={bounds} center={origin} listings={mapListings || []} />
|
||||
<SearchMap
|
||||
bounds={bounds}
|
||||
center={origin}
|
||||
listings={mapListings || []}
|
||||
onBoundsChanged={this.onBoundsChanged}
|
||||
/>
|
||||
</div>
|
||||
</ModalInMobile>
|
||||
</div>
|
||||
|
|
@ -196,7 +228,7 @@ SearchPageComponent.defaultProps = {
|
|||
tab: 'listings',
|
||||
};
|
||||
|
||||
const { array, bool, func, instanceOf, number, oneOf, object, shape, string } = PropTypes;
|
||||
const { array, arrayOf, bool, func, instanceOf, number, oneOf, object, shape, string } = PropTypes;
|
||||
|
||||
SearchPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
|
|
@ -218,6 +250,9 @@ SearchPageComponent.propTypes = {
|
|||
searchParams: object,
|
||||
tab: oneOf(['filters', 'listings', 'map']).isRequired,
|
||||
|
||||
// from withFlattenedRoutes
|
||||
flattenedRoutes: arrayOf(propTypes.route).isRequired,
|
||||
|
||||
// from withRouter
|
||||
history: shape({
|
||||
push: func.isRequired,
|
||||
|
|
@ -273,9 +308,11 @@ const mapDispatchToProps = dispatch => ({
|
|||
onSearchMapListings: searchParams => dispatch(searchMapListings(searchParams)),
|
||||
});
|
||||
|
||||
const SearchPage = compose(connect(mapStateToProps, mapDispatchToProps), withRouter)(
|
||||
SearchPageComponent
|
||||
);
|
||||
const SearchPage = compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withFlattenedRoutes,
|
||||
withRouter
|
||||
)(SearchPageComponent);
|
||||
|
||||
SearchPage.loadData = (params, search) => {
|
||||
const queryParams = parse(search, {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue