homeflowjs 0.10.18 → 0.10.20

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.
@@ -71,7 +71,7 @@ describe('Instant Valuation', () => {
71
71
 
72
72
  describe('Instant Valuation Results', () => {
73
73
  it('renders error message if it can\'t provide an accurate valuation', () => {
74
- render(<ResultStep valuation={{ price: null }} />);
74
+ render(<ResultStep valuation={{ price: null }} getValuation={jest.fn} />);
75
75
  const errorMessage = screen.getByTestId('valuation-error');
76
76
  expect(errorMessage).toBeInTheDocument();
77
77
  });
@@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
6
6
  import Autosuggest from 'react-autosuggest';
7
7
  import debounce from 'lodash.debounce';
8
8
  import { setBranchesSearch } from '../../actions/branches.actions';
9
+ import { DEBOUNCE_DELAY } from '../../utils';
9
10
 
10
11
  const BranchesSearchInput = ({
11
12
  placeholder,
@@ -53,7 +54,7 @@ const BranchesSearchInput = ({
53
54
  setSuggestions(suggestions);
54
55
  });
55
56
 
56
- const debouncedGetSuggestions = useCallback(debounce(getSuggestions, 300), []);
57
+ const debouncedGetSuggestions = useCallback(debounce(getSuggestions, DEBOUNCE_DELAY), []);
57
58
 
58
59
  const renderSuggestion = (suggestion) => (
59
60
  <span className="react-autosuggest_span">{suggestion}</span>
package/hooks/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import useDefaultSort from './use-default-sort.hook';
2
2
  import useGeolocate from './use-geolocate';
3
+ import useOutsideClick from './use-outside-click';
3
4
 
4
5
  export {
5
6
  useDefaultSort,
6
7
  useGeolocate,
8
+ useOutsideClick,
7
9
  };
@@ -0,0 +1,18 @@
1
+ import { useEffect } from 'react';
2
+
3
+ const useOutsideClick = (ref, callback) => {
4
+ useEffect(() => {
5
+ const handleClick = (e) => {
6
+ if (ref.current && !ref.current.contains(e.target)) {
7
+ callback();
8
+ }
9
+ };
10
+ document.addEventListener('mousedown', handleClick);
11
+ return () => {
12
+ document.removeEventListener('mousedown', handleClick);
13
+ };
14
+ }, [ref]);
15
+ return ref;
16
+ };
17
+
18
+ export default useOutsideClick;
@@ -10,6 +10,7 @@ import IntroStep from '../intro-step/intro-step.component';
10
10
  import YourDetailsStep from '../your-details-step/your-details-step.component';
11
11
  import SimilarPropertiesStep from '../similar-properties-step/similar-properties-step.component';
12
12
  import ResultStep from '../result-step/result-step.component';
13
+ import { DEBOUNCE_DELAY } from '../../utils';
13
14
 
14
15
  import './instant-valuation.styles.scss';
15
16
 
@@ -82,7 +83,7 @@ class InstantValuation extends Component {
82
83
  this.getSimilarProperties = this.getSimilarProperties.bind(this);
83
84
  this.toggleSimilarProperty = this.toggleSimilarProperty.bind(this);
84
85
  this.getValuation = this.getValuation.bind(this);
85
- this.addressLookup = debounce(this.addressLookup, 1000).bind(this);
86
+ this.addressLookup = debounce(this.addressLookup, DEBOUNCE_DELAY).bind(this);
86
87
  this.reset = this.reset.bind(this);
87
88
  this.setMessage = this.setMessage.bind(this);
88
89
  }
@@ -17,6 +17,18 @@ const ResultStep = ({
17
17
  reset,
18
18
  loading,
19
19
  }) => {
20
+ const [selectedChannel, setSelectedChannel] = useState('sales');
21
+
22
+ useEffect(() => {
23
+ getValuation();
24
+ }, []);
25
+
26
+ useEffect(() => {
27
+ if (valuation) Homeflow.kickEvent('valuation_successful');
28
+ }, [valuation])
29
+
30
+ if (!valuation || loading) return <Loader className="hfjs-instant-val__loader" />;
31
+
20
32
  if (!valuation.price) {
21
33
  return (
22
34
  <div data-testid="valuation-error" id="no_results">
@@ -32,16 +44,6 @@ const ResultStep = ({
32
44
  );
33
45
  }
34
46
 
35
- const [selectedChannel, setSelectedChannel] = useState('sales');
36
-
37
- useEffect(() => {
38
- getValuation();
39
- }, []);
40
-
41
- useEffect(() => {
42
- if (valuation) Homeflow.kickEvent('valuation_successful');
43
- }, [valuation])
44
-
45
47
  const formatPrice = (price) => (
46
48
  `£${Math.round(price)}${selectedChannel === 'lettings' ? '/month' : ''}`
47
49
  .replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,')
@@ -82,11 +84,8 @@ const ResultStep = ({
82
84
  const companyName = Homeflow.get('company_name');
83
85
  const gmapsKey = Homeflow.get('theme_preferences').google_maps_api_key;
84
86
 
85
- if (!valuation || loading) return <Loader className="hfjs-instant-val__loader" />;
86
-
87
87
  const streetviewQuery = `size=900x900&location=${lead.full_address},${search.postcode}&key=${gmapsKey}`;
88
88
 
89
-
90
89
  return (
91
90
  <div className="result-container">
92
91
  <div className="inner-wrapper">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homeflowjs",
3
- "version": "0.10.18",
3
+ "version": "0.10.20",
4
4
  "description": "JavaScript toolkit for Homeflow themes",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -6,6 +6,7 @@ import Autosuggest from 'react-autosuggest';
6
6
 
7
7
  import { setSuggestions, setSearchField } from '../../actions/search.actions';
8
8
  import propertySearch from '../property-search/property-search';
9
+ import { DEBOUNCE_DELAY } from '../../utils';
9
10
 
10
11
  import { autosuggestTheme } from './location-input.styles';
11
12
 
@@ -15,7 +16,7 @@ class LocationInput extends Component {
15
16
 
16
17
  this.onLocationChange = this.onLocationChange.bind(this);
17
18
  // wait half a second after typing stops before fetching results
18
- this.debouncedLoadSuggestions = debounce(this.loadSuggestions, 500);
19
+ this.debouncedLoadSuggestions = debounce(this.loadSuggestions, DEBOUNCE_DELAY);
19
20
  }
20
21
 
21
22
  onLocationChange(event, { newValue }) {
@@ -1,10 +1,11 @@
1
- import React from 'react';
1
+ import React, { useRef } from 'react';
2
2
  import { connect } from 'react-redux';
3
3
  import {
4
4
  HashRouter as Router,
5
5
  Route,
6
6
  Switch,
7
7
  NavLink,
8
+ useHistory
8
9
  } from 'react-router-dom';
9
10
  import PropTypes from 'prop-types';
10
11
 
@@ -17,6 +18,7 @@ import ForgottenPassword from '../forgotten-password/forgotten-password.componen
17
18
  import SignOutButton from '../../sign-out-button/sign-out-button.component';
18
19
  import Loader from '../../../shared/loader.component';
19
20
  import { loadingStyles } from '../../../modal/modal.component';
21
+ import useOutsideClick from '../../../hooks/use-outside-click';
20
22
 
21
23
  import './user-profile.styles.scss';
22
24
 
@@ -32,9 +34,17 @@ const UserProfileModal = ({ currentUser, loading }) => {
32
34
  }
33
35
 
34
36
  const logo = Homeflow.get('agency_logo');
37
+ const history = useHistory();
38
+ const ref = useRef();
39
+
40
+ const handleClickOutside = () => {
41
+ history.push('/')
42
+ };
43
+
44
+ useOutsideClick(ref, handleClickOutside);
35
45
 
36
46
  return (
37
- <div className="user-profile hf-modal">
47
+ <div className="user-profile hf-modal" ref={ref}>
38
48
  <div className="user-profile__side">
39
49
  <img src={logo} alt="Logo" className="user-profile__agency-logo" />
40
50
 
package/utils/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  export { default as stampDutyCalculator } from './stamp-duty-calculator/stamp-duty-calculator';
2
2
 
3
- export const capitalizeFirstLetter = str => (
3
+ export const capitalizeFirstLetter = (str) => (
4
4
  str.charAt(0).toUpperCase() + str.slice(1)
5
- )
5
+ );
6
6
 
7
- export const camelToSnakeCase = str => (
8
- str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)
9
- )
7
+ export const camelToSnakeCase = (str) => (
8
+ str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)
9
+ );
10
10
 
11
11
  export const isEmpty = (obj) => {
12
12
  for (const key in obj) {
@@ -16,9 +16,7 @@ export const isEmpty = (obj) => {
16
16
  return true;
17
17
  };
18
18
 
19
- export const numberWithCommas = (num) => {
20
- return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
21
- }
19
+ export const numberWithCommas = (num) => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
22
20
 
23
21
  // TODO: DRY these two functions up
24
22
  export const findSavedSearchIndex = (savedSearches, search) => {
@@ -64,9 +62,7 @@ export const formatMoney = (num) => {
64
62
  return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
65
63
  };
66
64
 
67
- export const uniqueKey = () => {
68
- return Math.random().toString(36).substring(7);
69
- };
65
+ export const uniqueKey = () => Math.random().toString(36).substring(7);
70
66
 
71
67
  export const objectDiff = (oldObject, newObject) => {
72
68
  const changed = {};
@@ -78,8 +74,10 @@ export const objectDiff = (oldObject, newObject) => {
78
74
  }
79
75
 
80
76
  return changed;
81
- }
77
+ };
82
78
 
83
- export const compact = (array) => array.filter(item => typeof item !== 'undefined' && item !== null);
79
+ export const compact = (array) => array.filter((item) => typeof item !== 'undefined' && item !== null);
84
80
 
85
81
  export const sanitizeText = (string) => new Option(string).innerHTML;
82
+
83
+ export const DEBOUNCE_DELAY = 200;