homeflowjs 0.10.2 → 0.10.4
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/package.json +1 -1
- package/properties/stamp-duty-calculator/default-calculator.component.jsx +113 -62
- package/properties/stamp-duty-calculator/stamp-duty-calculator.component.jsx +23 -3
- package/search/bedrooms-select/bedrooms-select.component.jsx +50 -36
- package/search/property-search/property-search.js +3 -1
package/package.json
CHANGED
|
@@ -101,70 +101,121 @@ const DefaultCalculator = ({ purchasePrice, setPurchasePrice, firstTimeBuyer, ad
|
|
|
101
101
|
Stamp duty
|
|
102
102
|
</p>
|
|
103
103
|
|
|
104
|
+
{(firstTimeBuyer && property.price_value >= 625000) && (
|
|
105
|
+
<p id='first_time_buyer_info'>First time buyers purchasing property for more than £625,000 will not be entitled to any relief and will pay SDLT at the standard rates.</p>
|
|
106
|
+
)}
|
|
107
|
+
|
|
104
108
|
<div className="results-table-wrap">
|
|
105
109
|
<p><strong>How this was calculated:</strong></p>
|
|
106
|
-
|
|
107
|
-
<
|
|
108
|
-
<
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
<
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
<
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
<
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
</
|
|
154
|
-
</
|
|
155
|
-
<
|
|
156
|
-
<
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
%
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
</
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
110
|
+
{(firstTimeBuyer && property.price_value <= 625000) ? (
|
|
111
|
+
<table className="SD_results_table residential">
|
|
112
|
+
<thead>
|
|
113
|
+
<tr>
|
|
114
|
+
<th>Band</th>
|
|
115
|
+
<th>Stamp Duty Rate</th>
|
|
116
|
+
<th>Due</th>
|
|
117
|
+
</tr>
|
|
118
|
+
</thead>
|
|
119
|
+
<tbody>
|
|
120
|
+
<tr>
|
|
121
|
+
<td>Between £0 and £425,000</td>
|
|
122
|
+
<td> 0% </td>
|
|
123
|
+
<td className="rate1">
|
|
124
|
+
£
|
|
125
|
+
{Number(rate1).toLocaleString()}
|
|
126
|
+
</td>
|
|
127
|
+
</tr>
|
|
128
|
+
<tr>
|
|
129
|
+
<td>Between £425,001 and £625,000</td>
|
|
130
|
+
<td> 5% </td>
|
|
131
|
+
<td className="rate3">
|
|
132
|
+
£
|
|
133
|
+
{Number(rate2).toLocaleString()}
|
|
134
|
+
</td>
|
|
135
|
+
</tr>
|
|
136
|
+
<tr className="totals">
|
|
137
|
+
<td>Total</td>
|
|
138
|
+
<td className="effectiveRate">
|
|
139
|
+
{effectiveRate}
|
|
140
|
+
%
|
|
141
|
+
</td>
|
|
142
|
+
<td className="totalRate">
|
|
143
|
+
£
|
|
144
|
+
{Number(totalRate).toLocaleString()}
|
|
145
|
+
</td>
|
|
146
|
+
</tr>
|
|
147
|
+
</tbody>
|
|
148
|
+
</table>
|
|
149
|
+
) : (
|
|
150
|
+
<table className="SD_results_table residential">
|
|
151
|
+
<thead>
|
|
152
|
+
<tr>
|
|
153
|
+
<th>Band</th>
|
|
154
|
+
<th>Stamp Duty Rate</th>
|
|
155
|
+
<th>Additional Property Rate</th>
|
|
156
|
+
<th>Due</th>
|
|
157
|
+
</tr>
|
|
158
|
+
</thead>
|
|
159
|
+
<tbody>
|
|
160
|
+
<tr>
|
|
161
|
+
<td>Between £0 and £250,000</td>
|
|
162
|
+
<td> 0% </td>
|
|
163
|
+
<td className='additional_rate'> 3% </td>
|
|
164
|
+
<td className="rate1">
|
|
165
|
+
£
|
|
166
|
+
{Number(rate1).toLocaleString()}
|
|
167
|
+
</td>
|
|
168
|
+
</tr>
|
|
169
|
+
{/* <tr>
|
|
170
|
+
<td>Between £125,000 and £250,000</td>
|
|
171
|
+
<td> 2% </td>
|
|
172
|
+
<td className="rate2">
|
|
173
|
+
£
|
|
174
|
+
{Number(rate2).toLocaleString()}
|
|
175
|
+
</td>
|
|
176
|
+
</tr> */}
|
|
177
|
+
<tr>
|
|
178
|
+
<td>Between £250,001 and £925,000</td>
|
|
179
|
+
<td> 5% </td>
|
|
180
|
+
<td className='additional_rate'> 8% </td>
|
|
181
|
+
<td className="rate3">
|
|
182
|
+
£
|
|
183
|
+
{Number(rate2).toLocaleString()}
|
|
184
|
+
</td>
|
|
185
|
+
</tr>
|
|
186
|
+
<tr>
|
|
187
|
+
<td>Between £925,000 and £1,500,000 </td>
|
|
188
|
+
<td> 10% </td>
|
|
189
|
+
<td className='additional_rate'> 13% </td>
|
|
190
|
+
<td className="rate4">
|
|
191
|
+
£
|
|
192
|
+
{Number(rate3).toLocaleString()}
|
|
193
|
+
</td>
|
|
194
|
+
</tr>
|
|
195
|
+
<tr>
|
|
196
|
+
<td>Over £1,500,000 </td>
|
|
197
|
+
<td> 12% </td>
|
|
198
|
+
<td className='additional_rate'> 15% </td>
|
|
199
|
+
<td className="rate5">
|
|
200
|
+
£
|
|
201
|
+
{Number(rate4).toLocaleString()}
|
|
202
|
+
</td>
|
|
203
|
+
</tr>
|
|
204
|
+
<tr className="totals">
|
|
205
|
+
<td>Total</td>
|
|
206
|
+
<td className="effectiveRate">
|
|
207
|
+
{effectiveRate}
|
|
208
|
+
%
|
|
209
|
+
</td>
|
|
210
|
+
<td></td>
|
|
211
|
+
<td className="totalRate">
|
|
212
|
+
£
|
|
213
|
+
{Number(totalRate).toLocaleString()}
|
|
214
|
+
</td>
|
|
215
|
+
</tr>
|
|
216
|
+
</tbody>
|
|
217
|
+
</table>
|
|
218
|
+
)}
|
|
168
219
|
</div>
|
|
169
220
|
</div>
|
|
170
221
|
</div>
|
|
@@ -7,6 +7,7 @@ import './stamp-duty-calculator.styles.scss';
|
|
|
7
7
|
|
|
8
8
|
const StampDutyCalculator = ({ scotland, themePreferences }) => {
|
|
9
9
|
const [type, setType] = useState('residential');
|
|
10
|
+
const [purchaseType, setPurchaseType] = useState('additional')
|
|
10
11
|
const [purchasePrice, setPurchasePrice] = useState();
|
|
11
12
|
|
|
12
13
|
const renderCalculator = () => {
|
|
@@ -15,8 +16,8 @@ const StampDutyCalculator = ({ scotland, themePreferences }) => {
|
|
|
15
16
|
<DefaultCalculator
|
|
16
17
|
purchasePrice={purchasePrice}
|
|
17
18
|
setPurchasePrice={setPurchasePrice}
|
|
18
|
-
firstTimeBuyer
|
|
19
|
-
additionalProperty={
|
|
19
|
+
firstTimeBuyer={purchaseType === 'firstTimeBuyer'}
|
|
20
|
+
additionalProperty={purchaseType === 'additional'}
|
|
20
21
|
ukResident
|
|
21
22
|
/>
|
|
22
23
|
);
|
|
@@ -57,7 +58,26 @@ const StampDutyCalculator = ({ scotland, themePreferences }) => {
|
|
|
57
58
|
</button>
|
|
58
59
|
</div>
|
|
59
60
|
</div>
|
|
60
|
-
|
|
61
|
+
<div className="switches">
|
|
62
|
+
<div className="form-group">
|
|
63
|
+
<button
|
|
64
|
+
type="button"
|
|
65
|
+
className={`stamp-duty-cal__type ${purchaseType === 'additional' ? 'selected' : ''}`}
|
|
66
|
+
onClick={() => setPurchaseType('additional')}
|
|
67
|
+
>
|
|
68
|
+
Additional Property
|
|
69
|
+
</button>
|
|
70
|
+
</div>
|
|
71
|
+
<div className="form-group">
|
|
72
|
+
<button
|
|
73
|
+
type="button"
|
|
74
|
+
className={`stamp-duty-cal__type ${purchaseType === 'firstTimeBuyer' ? 'selected' : ''}`}
|
|
75
|
+
onClick={() => setPurchaseType('firstTimeBuyer')}
|
|
76
|
+
>
|
|
77
|
+
First Time Buyer
|
|
78
|
+
</button>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
61
81
|
{renderCalculator()}
|
|
62
82
|
</div>
|
|
63
83
|
);
|
|
@@ -20,36 +20,50 @@ const NormalSelect = ({
|
|
|
20
20
|
placeholder,
|
|
21
21
|
bedOptionText,
|
|
22
22
|
...otherProps
|
|
23
|
-
}) =>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
title={`${type} beds`}
|
|
35
|
-
className={optionClass}
|
|
23
|
+
}) => {
|
|
24
|
+
const isNumberArray = (array) => array.every((item) => typeof item === 'number');
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<select
|
|
28
|
+
value={value}
|
|
29
|
+
onChange={(e) => setSearchField({
|
|
30
|
+
[e.target.name]: e.target.value ? parseInt(e.target.value) : null,
|
|
31
|
+
})}
|
|
32
|
+
name={`${type}Beds`}
|
|
33
|
+
{...otherProps}
|
|
36
34
|
>
|
|
37
|
-
{placeholder || `${capitalizeFirstLetter(type)}. bedrooms`}
|
|
38
|
-
</option>
|
|
39
|
-
{bedValues.map((_, i) => (
|
|
40
35
|
<option
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
title={`${i + 1} Bed`}
|
|
36
|
+
value=""
|
|
37
|
+
title={`${type} beds`}
|
|
44
38
|
className={optionClass}
|
|
45
39
|
>
|
|
46
|
-
{
|
|
47
|
-
{' '}
|
|
48
|
-
{bedOptionText}
|
|
40
|
+
{placeholder || `${capitalizeFirstLetter(type)}. bedrooms`}
|
|
49
41
|
</option>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
{bedValues.map((item) => (
|
|
43
|
+
isNumberArray(bedValues) ? (
|
|
44
|
+
<option
|
|
45
|
+
key={item}
|
|
46
|
+
value={item}
|
|
47
|
+
title={`${item} Bed`}
|
|
48
|
+
className={optionClass}
|
|
49
|
+
>
|
|
50
|
+
{item}
|
|
51
|
+
{' '}
|
|
52
|
+
{bedOptionText}
|
|
53
|
+
</option>
|
|
54
|
+
) : (
|
|
55
|
+
<option
|
|
56
|
+
key={item.label}
|
|
57
|
+
value={item.value}
|
|
58
|
+
title={`${item.value} Bed`}
|
|
59
|
+
className={optionClass}
|
|
60
|
+
>
|
|
61
|
+
{item.label}
|
|
62
|
+
</option>
|
|
63
|
+
)))}
|
|
64
|
+
</select>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
53
67
|
|
|
54
68
|
const ReactSelect = (props) => {
|
|
55
69
|
const {
|
|
@@ -63,7 +77,7 @@ const ReactSelect = (props) => {
|
|
|
63
77
|
bedOptionText,
|
|
64
78
|
} = props;
|
|
65
79
|
|
|
66
|
-
const bedOptions = bedValues.map(bedValue => (
|
|
80
|
+
const bedOptions = bedValues.map((bedValue) => (
|
|
67
81
|
{ value: bedValue, label: `${bedValue} ${bedOptionText}` }
|
|
68
82
|
));
|
|
69
83
|
|
|
@@ -76,17 +90,17 @@ const ReactSelect = (props) => {
|
|
|
76
90
|
options={bedOptions}
|
|
77
91
|
styles={styles}
|
|
78
92
|
placeholder={placeholder || `${capitalizeFirstLetter(type)} bedrooms`}
|
|
79
|
-
value={bedOptions.find(option => option.value === value)}
|
|
93
|
+
value={bedOptions.find((option) => option.value === value)}
|
|
80
94
|
setValue={() => value}
|
|
81
95
|
isSearchable={false}
|
|
82
96
|
onChange={({ value }) => {
|
|
83
97
|
setSearchField({
|
|
84
|
-
[`${type}Beds`]: value ? parseInt(value) : null
|
|
85
|
-
})
|
|
86
|
-
}
|
|
98
|
+
[`${type}Beds`]: value ? parseInt(value) : null,
|
|
99
|
+
});
|
|
100
|
+
}}
|
|
87
101
|
/>
|
|
88
|
-
)
|
|
89
|
-
}
|
|
102
|
+
);
|
|
103
|
+
};
|
|
90
104
|
|
|
91
105
|
const BedroomsSelect = (props) => {
|
|
92
106
|
const {
|
|
@@ -104,18 +118,18 @@ const BedroomsSelect = (props) => {
|
|
|
104
118
|
let filteredBedValues = bedValues;
|
|
105
119
|
|
|
106
120
|
if (type === 'max' && minBeds && !allowUnderOver) {
|
|
107
|
-
filteredBedValues = bedValues.filter(bedValue => bedValue >= minBeds);
|
|
121
|
+
filteredBedValues = bedValues.filter((bedValue) => (bedValue.value || bedValue) >= minBeds);
|
|
108
122
|
}
|
|
109
123
|
|
|
110
124
|
if (type === 'min' && maxBeds && !allowUnderOver) {
|
|
111
|
-
filteredBedValues = bedValues.filter(bedValue => bedValue <= maxBeds);
|
|
125
|
+
filteredBedValues = bedValues.filter((bedValue) => (bedValue.value || bedValue) <= maxBeds);
|
|
112
126
|
}
|
|
113
127
|
|
|
114
128
|
if (reactSelect) {
|
|
115
|
-
return <ReactSelect type={type} value={value || ''} bedValues={filteredBedValues} {...otherProps} />;
|
|
129
|
+
return <ReactSelect type={type} value={value || value === 0 ? value : ''} bedValues={filteredBedValues} {...otherProps} />;
|
|
116
130
|
}
|
|
117
131
|
|
|
118
|
-
return <NormalSelect type={type} value={value || ''} bedValues={filteredBedValues} {...otherProps} />;
|
|
132
|
+
return <NormalSelect type={type} value={value || value === 0 ? value : ''} bedValues={filteredBedValues} {...otherProps} />;
|
|
119
133
|
};
|
|
120
134
|
|
|
121
135
|
BedroomsSelect.propTypes = {
|
|
@@ -17,6 +17,8 @@ const fragmentize = (key, value) => {
|
|
|
17
17
|
return `${pattern[0] ? pattern[0] : ''}${value}${pattern[1] ? pattern[1] : ''}`;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
const minOrMaxBedZero = (key, value) => (key === 'minBeds' || key === 'maxBeds') && value === 0;
|
|
21
|
+
|
|
20
22
|
export const buildQueryString = (search) => {
|
|
21
23
|
const queryParams = [];
|
|
22
24
|
const fragmentParams = [];
|
|
@@ -24,7 +26,7 @@ export const buildQueryString = (search) => {
|
|
|
24
26
|
Object.keys(search).forEach((key) => {
|
|
25
27
|
const value = search[key];
|
|
26
28
|
|
|
27
|
-
if (
|
|
29
|
+
if (minOrMaxBedZero(key, value)) return fragmentParams.push(fragmentize(key, value));
|
|
28
30
|
|
|
29
31
|
if (!value) return;
|
|
30
32
|
|