homeflowjs 0.13.43 → 0.13.45

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.
@@ -25,6 +25,8 @@ const INITIAL_STATE = {
25
25
  properties: [],
26
26
  property_type: '',
27
27
  bedrooms: '',
28
+ lat: '',
29
+ lng: '',
28
30
  },
29
31
  lead: {
30
32
  first_name: '',
@@ -122,6 +124,7 @@ class InstantValuation extends Component {
122
124
  lead_url_referrer: referrerURL,
123
125
  };
124
126
 
127
+
125
128
  const params = flatten({ search: restOfSearch, lead });
126
129
 
127
130
  const query = new URLSearchParams(params);
@@ -200,6 +203,11 @@ class InstantValuation extends Component {
200
203
  ...prevState.lead,
201
204
  full_address: this.constructor.formatAddress(json.Addresses[0]),
202
205
  },
206
+ search: {
207
+ ...prevState.search,
208
+ lat: json.Latitude,
209
+ lng: json.Longitude,
210
+ },
203
211
  }));
204
212
 
205
213
  return null;
@@ -149,18 +149,20 @@ const ResultStep = ({
149
149
  </div>
150
150
  )}
151
151
 
152
- {!!recentSales?.length && <ValuationMap recentSales={recentSales} />}
152
+ <ValuationMap recentSales={recentSales} search={search} />
153
153
 
154
154
  <div style={{ clear: 'both' }} />
155
155
 
156
- <div className="recently-sold">
157
- <h3>Recently sold in the area</h3>
158
- <p>These properties near you were sold recently.</p>
156
+ {!!recentSales?.length && (
157
+ <div className="recently-sold">
158
+ <h3>Recently sold in the area</h3>
159
+ <p>These properties near you were sold recently.</p>
159
160
 
160
- <ul id="recently-sold-list">
161
- {recentSales?.map((property) => recentSale(property))}
162
- </ul>
163
- </div>
161
+ <ul id="recently-sold-list">
162
+ {recentSales?.map((property) => recentSale(property))}
163
+ </ul>
164
+ </div>
165
+ )}
164
166
 
165
167
  <div className="clear" />
166
168
  </div>
@@ -9,19 +9,21 @@ import {
9
9
 
10
10
  import '../../properties/properties-map/leaflet.css';
11
11
 
12
- const ValuationMap = ({ recentSales }) => {
12
+ const ValuationMap = ({ recentSales, search }) => {
13
+ if (!recentSales.length && !search.lat && !search.lng) return null;
14
+
13
15
  const defaultIcon = L.icon({
14
16
  iconRetinaUrl: '/assets/marker-icon.png',
15
17
  iconUrl: '/assets/marker-icon.png',
16
18
  shadowUrl: '/assets/marker-shadow.png',
17
19
  });
18
20
 
19
- const bounds = latLngBounds([
21
+ const bounds = recentSales?.length ? latLngBounds([
20
22
  parseFloat(recentSales[0].latitude),
21
23
  parseFloat(recentSales[0].longitude),
22
- ]);
24
+ ]) : null;
23
25
 
24
- const markers = recentSales?.map((property) => {
26
+ const markers = recentSales?.length ? recentSales?.map((property) => {
25
27
  bounds.extend([property.latitude, property.longitude]);
26
28
 
27
29
  return (
@@ -31,11 +33,17 @@ const ValuationMap = ({ recentSales }) => {
31
33
  icon={defaultIcon}
32
34
  />
33
35
  );
34
- });
36
+ }) : (
37
+ <Marker
38
+ position={[search.lat, search.lng]}
39
+ icon={defaultIcon}
40
+ />
41
+ );
35
42
 
36
43
  return (
37
44
  <MapContainer
38
- bounds={bounds}
45
+ {...(!!recentSales.length && bounds && { bounds })}
46
+ {...(!recentSales.length && { center: [search.lat, search.lng], zoom: 14 })}
39
47
  scrollWheelZoom={false}
40
48
  style={{ height: 300 }}
41
49
  >
@@ -50,6 +58,14 @@ const ValuationMap = ({ recentSales }) => {
50
58
 
51
59
  ValuationMap.propTypes = {
52
60
  recentSales: PropTypes.array.isRequired,
61
+ search: PropTypes.shape({
62
+ lat: PropTypes.number,
63
+ lng: PropTypes.number,
64
+ }),
65
+ };
66
+
67
+ ValuationMap.defaultProps = {
68
+ search: null,
53
69
  };
54
70
 
55
71
  export default ValuationMap;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homeflowjs",
3
- "version": "0.13.43",
3
+ "version": "0.13.45",
4
4
  "sideEffects": [
5
5
  "modal/**/*",
6
6
  "user/default-profile/**/*",
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable */
2
2
  import DraggableMap from './draggable-map';
3
3
  import store from '../../store';
4
- import { currentGeonameId, filterGeonames } from '../../utils/index';
4
+ import { currentGeonameId, filterGeonames, uniqueGeonamesByNameAndArea } from '../../utils/index';
5
5
  import { setProperties, setGeonames, setSelectedMarker } from '../../actions/properties.actions';
6
6
  import { setInitialSearch, setPlace, setSearchField } from '../../actions/search.actions';
7
7
  import { buildQueryString } from '../../search/property-search/property-search';
@@ -283,11 +283,20 @@ export default class GeonamesMap extends DraggableMap {
283
283
  if (json.geonames) {
284
284
  this.geonames = this.concatenateDistinctObjects('geoname_id', this.geonames, json.geonames);
285
285
  window.markerType = 'geonames';
286
- const currentAreaId = store.getState().search.currentSearch?.place?.area;
287
- const geonamesFiltered = filterGeonames(
288
- this.currentGeonameIdFromLocationPath, Number(currentAreaId), this.geonames
289
- );
290
- store.dispatch(setGeonames(geonamesFiltered));
286
+
287
+ const currentSearchPlace = store.getState().search.currentSearch?.place;
288
+ const geonamePosition = currentSearchPlace?.geoname_position || null;
289
+ const area = currentSearchPlace?.area || null;
290
+
291
+ let geonamesToDisplay = uniqueGeonamesByNameAndArea(this.geonames);
292
+
293
+ if (geonamePosition || area) {
294
+ geonamesToDisplay = filterGeonames(
295
+ this.currentGeonameIdFromLocationPath, Number(area), Number(geoname_position), geonamesToDisplay
296
+ );
297
+
298
+ }
299
+ store.dispatch(setGeonames(geonamesToDisplay));
291
300
  } else if (json.properties) {
292
301
  this.properties = this.concatenateDistinctObjects('property_id', this.properties, json.properties);
293
302
  window.markerType = 'properties';
@@ -310,11 +319,20 @@ export default class GeonamesMap extends DraggableMap {
310
319
  this.hideSuggestedDestinations();
311
320
  this.markersInitialized = true;
312
321
  } else if (window.markerType === 'geonames' && this.geonames?.length) {
313
- const currentAreaId = store.getState().search.currentSearch?.place?.area;
314
- const geonamesFiltered = filterGeonames(
315
- this.currentGeonameIdFromLocationPath, Number(currentAreaId), this.geonames
316
- );
317
- geonamesFiltered.forEach(geoname => this.setGeonameMarker(geoname));
322
+ const currentSearchPlace = store.getState()?.search?.currentSearch?.place;
323
+
324
+ const geonamePosition = currentSearchPlace?.geoname_position || null;
325
+ const area = currentSearchPlace?.area || null;
326
+
327
+ let geonamesToDisplay = uniqueGeonamesByNameAndArea(this.geonames);
328
+
329
+ if (geonamePosition || area) {
330
+ geonamesToDisplay = filterGeonames(
331
+ this.currentGeonameIdFromLocationPath, Number(area), Number(geonamePosition), geonamesToDisplay
332
+ );
333
+ }
334
+
335
+ geonamesToDisplay.forEach(geoname => this.setGeonameMarker(geoname));
318
336
  this.showSuggestedDestinations();
319
337
  this.markersInitialized = true;
320
338
  }
package/utils/index.js CHANGED
@@ -93,10 +93,42 @@ export const currentGeonameId = (path) => {
93
93
 
94
94
  export const DEBOUNCE_DELAY = 200;
95
95
 
96
- export const filterGeonames = (geonameId = null, areaId = null, geonames) => {
96
+ export const filterGeonames = (geonameId = null, areaId = null, geoPosition = null, geonames) => {
97
97
  if (!geonameId) return geonames;
98
98
 
99
- if (areaId) return geonames.filter((geoname) => geoname?.geoname_id !== geonameId && geoname?.area < areaId);
100
-
101
- return geonames.filter((geoname) => geoname?.geoname_id !== geonameId);
99
+ // Filter our same id
100
+ let filtered = geonames.filter((geoname) => geoname?.geoname_id !== geonameId);
101
+
102
+ // Filter out higher area
103
+ if (areaId && !geoPosition) filtered = filtered.filter((geoname) => geoname?.area < areaId);
104
+
105
+ // Filter out lower geoname_position
106
+ if (geoPosition) filtered = filtered.filter((geoname) => {
107
+ // Fallback to area if no geoname_position
108
+ if (
109
+ geoname?.geoname_position === 0
110
+ && geoname?.area
111
+ && geoname?.area !== 0
112
+ && areaId
113
+ ) return geoname?.area < areaId;
114
+ return geoname?.geoname_position > geoPosition;
115
+ });
116
+
117
+ return filtered;
102
118
  };
119
+
120
+ export const uniqueGeonamesByNameAndArea = (geonames) => {
121
+ // One of the duplicated Geonames comes with geoname_position set as 0
122
+ // First set the one with geoname_position = 0 before the one with actual value, ordered by properties_count (as the response).
123
+ const sortByNameAndGeonamePosition = geonames.sort(
124
+ (first, second) => {
125
+ if (first.name === second.name) return first?.geoname_position - second?.geoname_position;
126
+ return first.properties_count > second.properties_count ? -1 : 1;
127
+ }
128
+ );
129
+ // Then remove duplicates by name
130
+ const uniqueNamesOnly = [...new Map(sortByNameAndGeonamePosition.map(item => [item['name'], item])).values()];
131
+
132
+ // Finally remove if they have the same area
133
+ return [...new Map(uniqueNamesOnly.map(item => [item['area'], item])).values()]
134
+ };