homeflowjs 0.13.12 → 0.13.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/hooks/index.js +2 -0
- package/hooks/use-property-inifinite-scroll.js +45 -0
- package/package.json +1 -1
- package/properties/properties-display/properties-display.component.jsx +20 -17
- package/properties/properties-map/draggable-map.js +1 -0
- package/properties/properties-map/geonames-map.js +20 -1
- package/properties/property-results/property-results.component.jsx +8 -0
package/hooks/index.js
CHANGED
@@ -2,10 +2,12 @@ import useDefaultSort from './use-default-sort.hook';
|
|
2
2
|
import useGeolocate from './use-geolocate';
|
3
3
|
import useOutsideClick from './use-outside-click';
|
4
4
|
import { useOnScreen } from './use-on-screen';
|
5
|
+
import usePropertyInfiniteScroll from './use-property-inifinite-scroll';
|
5
6
|
|
6
7
|
export {
|
7
8
|
useDefaultSort,
|
8
9
|
useGeolocate,
|
9
10
|
useOutsideClick,
|
10
11
|
useOnScreen,
|
12
|
+
usePropertyInfiniteScroll,
|
11
13
|
};
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import { useEffect } from 'react';
|
2
|
+
import { useSelector, useDispatch } from 'react-redux';
|
3
|
+
|
4
|
+
import { loadNext } from '../actions/properties.actions';
|
5
|
+
import { addSearchToLocalStorage } from '../app/user-history';
|
6
|
+
|
7
|
+
const usePropertyInfiniteScroll = (targetRef, options = {}) => {
|
8
|
+
const pagination = useSelector((state) => state.properties?.pagination);
|
9
|
+
const loadingProperties = useSelector((state) => state.app.loading?.properties);
|
10
|
+
const currentSearch = useSelector((state) => state.search?.currentSearch);
|
11
|
+
const dispatch = useDispatch();
|
12
|
+
|
13
|
+
useEffect(() => {
|
14
|
+
let observer;
|
15
|
+
|
16
|
+
if (pagination.has_next_page) {
|
17
|
+
observer = new IntersectionObserver(
|
18
|
+
(entries) => {
|
19
|
+
if (entries[0].isIntersecting) {
|
20
|
+
dispatch(loadNext())
|
21
|
+
.then(() => {
|
22
|
+
addSearchToLocalStorage(currentSearch);
|
23
|
+
});
|
24
|
+
}
|
25
|
+
},
|
26
|
+
options,
|
27
|
+
);
|
28
|
+
|
29
|
+
if (targetRef.current) {
|
30
|
+
observer.observe(targetRef.current);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
return () => {
|
36
|
+
if (targetRef.current) {
|
37
|
+
observer.unobserve(targetRef.current);
|
38
|
+
}
|
39
|
+
};
|
40
|
+
}, [targetRef]);
|
41
|
+
|
42
|
+
return { loadingProperties, hasNextPage: pagination.has_next_page };
|
43
|
+
};
|
44
|
+
|
45
|
+
export default usePropertyInfiniteScroll;
|
package/package.json
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
import React, { useEffect } from 'react';
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
2
2
|
import { connect } from 'react-redux';
|
3
3
|
import PropTypes from 'prop-types';
|
4
4
|
|
5
|
-
import {
|
5
|
+
import { propertiesByPage, updatePageInURL } from '../property-utils/property-utils';
|
6
|
+
import { usePropertyInfiniteScroll } from '../../hooks';
|
6
7
|
|
7
8
|
const ConditionalWrapper = ({ condition, wrapper, children }) => (
|
8
9
|
condition ? wrapper(children) : children
|
@@ -13,21 +14,13 @@ const PropertiesDisplay = ({
|
|
13
14
|
Item,
|
14
15
|
displayType,
|
15
16
|
infiniteScroll,
|
17
|
+
InfiniteScrollLoader,
|
16
18
|
inserts,
|
17
19
|
noResultsMessage,
|
18
20
|
...other
|
19
21
|
}) => {
|
20
|
-
const
|
21
|
-
|
22
|
-
};
|
23
|
-
|
24
|
-
useEffect(() => {
|
25
|
-
window.addEventListener('scroll', onScroll);
|
26
|
-
|
27
|
-
return function cleanUp() {
|
28
|
-
window.removeEventListener('scroll', onScroll);
|
29
|
-
};
|
30
|
-
}, []);
|
22
|
+
const infiniteScrollRef = useRef();
|
23
|
+
const { loadingProperties, hasNextPage } = usePropertyInfiniteScroll(infiniteScrollRef);
|
31
24
|
|
32
25
|
useEffect(() => {
|
33
26
|
const pageMarkers = document.querySelectorAll('[data-page-marker]');
|
@@ -49,7 +42,7 @@ const PropertiesDisplay = ({
|
|
49
42
|
};
|
50
43
|
}, [properties]);
|
51
44
|
|
52
|
-
if (!properties
|
45
|
+
if (!properties?.length) {
|
53
46
|
return noResultsMessage;
|
54
47
|
}
|
55
48
|
|
@@ -94,9 +87,17 @@ const PropertiesDisplay = ({
|
|
94
87
|
));
|
95
88
|
|
96
89
|
return (
|
97
|
-
|
98
|
-
{
|
99
|
-
|
90
|
+
<>
|
91
|
+
<div className={`hf-property-results hf-property-results__${displayType}`}>
|
92
|
+
{items}
|
93
|
+
</div>
|
94
|
+
{infiniteScroll && hasNextPage && (
|
95
|
+
<div ref={infiniteScrollRef} />
|
96
|
+
)}
|
97
|
+
{infiniteScroll && InfiniteScrollLoader && hasNextPage && loadingProperties && (
|
98
|
+
<InfiniteScrollLoader />
|
99
|
+
)}
|
100
|
+
</>
|
100
101
|
);
|
101
102
|
};
|
102
103
|
|
@@ -105,12 +106,14 @@ PropertiesDisplay.propTypes = {
|
|
105
106
|
Item: PropTypes.elementType.isRequired,
|
106
107
|
displayType: PropTypes.string.isRequired,
|
107
108
|
infiniteScroll: PropTypes.bool.isRequired,
|
109
|
+
InfiniteScrollLoader: PropTypes.func,
|
108
110
|
inserts: PropTypes.array,
|
109
111
|
noResultsMessage: PropTypes.node,
|
110
112
|
};
|
111
113
|
|
112
114
|
PropertiesDisplay.defaultProps = {
|
113
115
|
inserts: null,
|
116
|
+
InfiniteScrollLoader: null,
|
114
117
|
noResultsMessage: <p>There were no properties matching your search.</p>,
|
115
118
|
};
|
116
119
|
|
@@ -52,6 +52,7 @@ export default class DraggableMap {
|
|
52
52
|
}
|
53
53
|
|
54
54
|
init() {
|
55
|
+
store.dispatch(setSearchField({ page: null }));
|
55
56
|
//@setElement( $(Homeflow.get('small_map_element')))
|
56
57
|
if (Homeflow.get('draggable_map_view') != null) {
|
57
58
|
this.element = Homeflow.get('draggable_map_view');
|
@@ -48,6 +48,13 @@ export default class GeonamesMap extends DraggableMap {
|
|
48
48
|
const prevProperties = store.getState().properties.properties;
|
49
49
|
|
50
50
|
this.unsubscribeFromGeonamesChanges = store.subscribe(() => {
|
51
|
+
const zoomLevel = this.map.getZoom();
|
52
|
+
/*
|
53
|
+
* Unsubscribe if the user has zoomed from the initial position as this
|
54
|
+
* was causing the map to zoom back to it's inital position
|
55
|
+
*/
|
56
|
+
if (window.initialZoomLevel && window.initialZoomLevel !== zoomLevel) return this.unsubscribeFromGeonamesChanges();
|
57
|
+
|
51
58
|
const { geonames, properties } = store.getState().properties
|
52
59
|
|
53
60
|
if (properties?.length) this.geonamesInit();
|
@@ -78,7 +85,14 @@ export default class GeonamesMap extends DraggableMap {
|
|
78
85
|
* If for some reason the markers have not rendered after a few seconds
|
79
86
|
* render them so we don't have an empty map
|
80
87
|
*/
|
81
|
-
setTimeout(() => {
|
88
|
+
const geoNamesTimer = setTimeout(() => {
|
89
|
+
const zoomLevel = this.map.getZoom();
|
90
|
+
/*
|
91
|
+
* Cancel timer if the user has zoomed from the initial position as this
|
92
|
+
* was causing the map to zoom back to it's inital position
|
93
|
+
*/
|
94
|
+
if (window.initialZoomLevel && window.initialZoomLevel !== zoomLevel) return cancelGeonamesTimer();
|
95
|
+
|
82
96
|
if (!this.markersInitialized) {
|
83
97
|
const { geonames, properties } = store.getState().properties
|
84
98
|
if (!properties && !geonames?.length) {
|
@@ -93,6 +107,10 @@ export default class GeonamesMap extends DraggableMap {
|
|
93
107
|
this.setToMarkeredBounds();
|
94
108
|
}
|
95
109
|
}, 5000);
|
110
|
+
|
111
|
+
function cancelGeonamesTimer() {
|
112
|
+
clearTimeout(geoNamesTimer);
|
113
|
+
}
|
96
114
|
}
|
97
115
|
|
98
116
|
setMarkerTypeforZoomLevel() {
|
@@ -172,6 +190,7 @@ export default class GeonamesMap extends DraggableMap {
|
|
172
190
|
|
173
191
|
this.setMarkers();
|
174
192
|
this.setToMarkeredBounds();
|
193
|
+
if (!window.initialZoomLevel) window.initialZoomLevel = this.map.getZoom();
|
175
194
|
|
176
195
|
const zoomLevel = this.map.getZoom();
|
177
196
|
|
@@ -24,6 +24,7 @@ const PropertyResults = ({
|
|
24
24
|
MapItem,
|
25
25
|
defaultView,
|
26
26
|
infiniteScroll,
|
27
|
+
infiniteScrollLoader,
|
27
28
|
noMap,
|
28
29
|
inserts,
|
29
30
|
noResultsMessage,
|
@@ -36,6 +37,7 @@ const PropertyResults = ({
|
|
36
37
|
Item={ListItem}
|
37
38
|
displayType="list"
|
38
39
|
infiniteScroll={infiniteScroll}
|
40
|
+
InfiniteScrollLoader={infiniteScrollLoader}
|
39
41
|
inserts={inserts}
|
40
42
|
noResultsMessage={noResultsMessage}
|
41
43
|
{...other}
|
@@ -47,6 +49,7 @@ const PropertyResults = ({
|
|
47
49
|
Item={GridItem}
|
48
50
|
displayType="grid"
|
49
51
|
infiniteScroll={infiniteScroll}
|
52
|
+
InfiniteScrollLoader={infiniteScrollLoader}
|
50
53
|
inserts={inserts}
|
51
54
|
noResultsMessage={noResultsMessage}
|
52
55
|
{...other}
|
@@ -60,6 +63,7 @@ const PropertyResults = ({
|
|
60
63
|
displayType="map"
|
61
64
|
infiniteScroll={infiniteScroll}
|
62
65
|
inserts={inserts}
|
66
|
+
InfiniteScrollLoader={infiniteScrollLoader}
|
63
67
|
noResultsMessage={noResultsMessage}
|
64
68
|
{...other}
|
65
69
|
/>
|
@@ -74,6 +78,7 @@ const PropertyResults = ({
|
|
74
78
|
Item={GridItem}
|
75
79
|
displayType="grid"
|
76
80
|
infiniteScroll={infiniteScroll}
|
81
|
+
InfiniteScrollLoader={infiniteScrollLoader}
|
77
82
|
inserts={inserts}
|
78
83
|
noResultsMessage={noResultsMessage}
|
79
84
|
{...other}
|
@@ -85,6 +90,7 @@ const PropertyResults = ({
|
|
85
90
|
Item={ListItem}
|
86
91
|
displayType="list"
|
87
92
|
infiniteScroll={infiniteScroll}
|
93
|
+
InfiniteScrollLoader={infiniteScrollLoader}
|
88
94
|
inserts={inserts}
|
89
95
|
noResultsMessage={noResultsMessage}
|
90
96
|
{...other}
|
@@ -101,6 +107,7 @@ PropertyResults.propTypes = {
|
|
101
107
|
MapItem: PropTypes.elementType,
|
102
108
|
defaultView: PropTypes.string,
|
103
109
|
infiniteScroll: PropTypes.bool,
|
110
|
+
infiniteScrollLoader: PropTypes.elementType,
|
104
111
|
noMap: PropTypes.bool,
|
105
112
|
inserts: PropTypes.array,
|
106
113
|
};
|
@@ -111,6 +118,7 @@ PropertyResults.defaultProps = {
|
|
111
118
|
MapItem: null,
|
112
119
|
defaultView: 'list',
|
113
120
|
infiniteScroll: false,
|
121
|
+
infiniteScrollLoader: null,
|
114
122
|
noMap: false,
|
115
123
|
inserts: null,
|
116
124
|
};
|