Skip to content

Commit cc95acd

Browse files
committed
search page
1 parent 6855e2b commit cc95acd

File tree

15 files changed

+1806
-5202
lines changed

15 files changed

+1806
-5202
lines changed

components/Forms/SearchForm.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
.container {
44
padding: spacing(2) spacing(1);
55
background: $color-white;
6+
transition: $transition;
67
.row {
78
display: grid;
89
grid-template-columns: 1fr 1fr;

components/Forms/SearchForm.tsx

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
/* eslint-disable no-underscore-dangle */
22
import React, { useState, useEffect } from 'react'
3-
import { reduxForm } from 'redux-form' // tslint:disable
3+
import { reduxForm, reset, getFormValues, change } from 'redux-form' // tslint:disable
44
import classNames from 'classnames'
55
import useFetchVehicleModels from '../../hooks/useFetchVehicleModels'
66
import { useRouter } from 'next/router'
7+
import get from 'lodash/get'
8+
import reduce from 'lodash/reduce'
9+
import { useDispatch, useSelector } from 'react-redux'
710
import PropTypes from 'prop-types'
811
import useModal from '../../hooks/useModal'
912
import { useTranslation } from 'react-i18next'
@@ -21,20 +24,40 @@ type Props = {
2124
fluid?: boolean
2225
cb?: () => void
2326
defaultExpanded?: boolean
27+
dirty: boolean
2428
handleSubmit: (fn: any) => void
2529
}
2630

31+
const createResetFieldsMap = (fields: any, formValues: any, cb: any) => {
32+
return reduce(
33+
fields,
34+
(prev, field) => {
35+
const value = get(formValues, field)
36+
if (!prev) prev = {}
37+
if (value && value !== '') {
38+
return {
39+
...prev,
40+
[field]: cb(field),
41+
}
42+
}
43+
return prev
44+
},
45+
{}
46+
)
47+
}
48+
2749
const SearchFormComponent: React.FunctionComponent<Props> = ({
2850
className,
2951
fluid,
3052
cb,
3153
defaultExpanded,
3254
handleSubmit,
55+
dirty,
3356
}) => {
3457
const router = useRouter()
3558
useFetchVehicleModels(form)
3659
const [openExpand, setOpenExpand] = useState(defaultExpanded || false)
37-
60+
const dispatch = useDispatch()
3861
useEffect(() => {
3962
if (defaultExpanded) setOpenExpand(true)
4063
}, [defaultExpanded])
@@ -54,12 +77,29 @@ const SearchFormComponent: React.FunctionComponent<Props> = ({
5477
if (cb) cb()
5578
}
5679

80+
const formValues = useSelector(getFormValues(form))
81+
82+
const resetFields = createResetFieldsMap(
83+
[
84+
fieldTypes.make,
85+
fieldTypes.model,
86+
fieldTypes.fuel,
87+
fieldTypes.gearbox,
88+
fieldTypes.bodyType,
89+
],
90+
formValues,
91+
(field: string) => () => dispatch(change(form, field, ''))
92+
)
93+
5794
return (
5895
<form
5996
className={classNames(styles.container, className, fluid && styles.fluid)}
6097
onSubmit={() => handleSubmit(onSubmit)}
6198
>
62-
<BaseVehicleFields />
99+
<BaseVehicleFields
100+
onReset={!dirty ? undefined : () => dispatch(reset(form))}
101+
resetFields={resetFields}
102+
/>
63103
<div className={styles.row}>
64104
{/* @ts-ignore */}
65105
<Checkbox name={fieldTypes.remember} label={t('label.remember')} />

components/Forms/parts/BaseVehicleFields.module.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@
1515
@extend .spacing;
1616
min-width: 50%;
1717
}
18+
19+
.buttonReset {
20+
display: flex;
21+
margin-bottom: spacing(1);
22+
@media (min-width: $tablet) {
23+
justify-content: flex-end;
24+
}
25+
}

components/Forms/parts/BaseVehicleFields.tsx

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ import React from 'react'
22
import { useTranslation } from 'react-i18next'
33
import { useSelector } from 'react-redux'
44
import includes from 'lodash/includes'
5+
import get from 'lodash/get'
6+
import { FiTrash2 } from 'react-icons/fi'
57
import {
68
modelsSelector,
79
makesSelector,
810
modelsLoadingSelector,
911
makesLoadingSelector,
1012
} from '../../../store/vehicles/selectors'
1113
import { transmissionTypes, bodyType, fuelTypes } from '../../../consts/vehicle'
12-
import { Select } from '../..'
14+
import { Button, Select } from '../..'
1315
import {
1416
mapBaseOptions,
1517
mapVehicleTranslatableOptions,
@@ -20,11 +22,15 @@ import styles from './BaseVehicleFields.module.scss'
2022
type Props = {
2123
singleVehicleBodySelect?: boolean
2224
requiredFields?: string[]
25+
onReset?: any
26+
resetFields?: any
2327
}
2428

2529
const BaseVehicleFields: React.FunctionComponent<Props> = ({
2630
singleVehicleBodySelect,
2731
requiredFields,
32+
onReset,
33+
resetFields,
2834
}) => {
2935
const { t } = useTranslation()
3036
const models = useSelector(modelsSelector)
@@ -41,6 +47,18 @@ const BaseVehicleFields: React.FunctionComponent<Props> = ({
4147

4248
return (
4349
<>
50+
{onReset && (
51+
<div className={styles.buttonReset}>
52+
<Button
53+
color={Button.colors.RED}
54+
type={Button.types.GHOST}
55+
onClick={onReset}
56+
>
57+
<FiTrash2 />
58+
</Button>
59+
</div>
60+
)}
61+
4462
<div className={styles.row}>
4563
{/* @ts-ignore */}
4664
<Select
@@ -51,6 +69,7 @@ const BaseVehicleFields: React.FunctionComponent<Props> = ({
5169
isRequired={includes(requiredFields, fieldTypes.make)}
5270
name={fieldTypes.make}
5371
options={makesOptions}
72+
onReset={get(resetFields, fieldTypes.make)}
5473
/>
5574
{/* @ts-ignore */}
5675
<Select
@@ -61,6 +80,7 @@ const BaseVehicleFields: React.FunctionComponent<Props> = ({
6180
name={fieldTypes.model}
6281
isRequired={includes(requiredFields, fieldTypes.model)}
6382
options={modelsOptions}
83+
onReset={get(resetFields, fieldTypes.model)}
6484
/>
6585
</div>
6686
<div className={styles.row}>
@@ -72,6 +92,7 @@ const BaseVehicleFields: React.FunctionComponent<Props> = ({
7292
name={fieldTypes.fuel}
7393
isRequired={includes(requiredFields, fieldTypes.fuel)}
7494
options={fuels}
95+
onReset={get(resetFields, fieldTypes.fuel)}
7596
/>
7697
{/* @ts-ignore */}
7798
<Select
@@ -81,20 +102,22 @@ const BaseVehicleFields: React.FunctionComponent<Props> = ({
81102
name={fieldTypes.gearbox}
82103
isRequired={includes(requiredFields, fieldTypes.gearbox)}
83104
options={transmissions}
105+
onReset={get(resetFields, fieldTypes.gearbox)}
84106
/>
85107
</div>
86108
<div className={styles.spacing}>
87-
{/* @ts-ignore */}
88-
<Select
89-
label={t('label.bodyType')}
90-
fluid
91-
multiple={!singleVehicleBodySelect}
92-
isRequired={includes(requiredFields, fieldTypes.bodyType)}
93-
placeholder={t('placeholder.bodyType')}
94-
name={fieldTypes.bodyType}
95-
className={styles.marginBottom}
96-
options={vehicleBodyTypes}
97-
/>
109+
{/* @ts-ignore */}
110+
<Select
111+
label={t('label.bodyType')}
112+
fluid
113+
multiple={!singleVehicleBodySelect}
114+
isRequired={includes(requiredFields, fieldTypes.bodyType)}
115+
placeholder={t('placeholder.bodyType')}
116+
name={fieldTypes.bodyType}
117+
className={styles.marginBottom}
118+
onReset={get(resetFields, fieldTypes.bodyType)}
119+
options={vehicleBodyTypes}
120+
/>
98121
</div>
99122
</>
100123
)

components/Input/Input.module.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
margin-bottom: spacing(1);
5656
display: inline-flex;
5757
align-items: center;
58+
position: relative;
5859
span {
5960
transition: $transition;
6061
font-size: $font-size-p;
@@ -135,3 +136,9 @@
135136
border-bottom: 10px solid $color-complimentary-transparent-heavy;
136137
}
137138
}
139+
140+
.cancelButton {
141+
position: absolute;
142+
right: 0;
143+
top: 0;
144+
}

components/Input/Select.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const SelectComponent = ({
3737
placeholder,
3838
multiple,
3939
isCustom,
40+
onReset,
4041
}) => {
4142
const { value } = input
4243
const { error, active } = meta
@@ -116,7 +117,12 @@ const SelectComponent = ({
116117
onClick={handleOpen}
117118
onKeyPress={handleKeyPress}
118119
>
119-
<InputLabel isRequired={isRequired} label={label} name={name} />
120+
<InputLabel
121+
isRequired={isRequired}
122+
label={label}
123+
name={name}
124+
onReset={onReset}
125+
/>
120126
{isCustom ? (
121127
<select
122128
name={name}
@@ -131,7 +137,7 @@ const SelectComponent = ({
131137
onChange={(e) => handleOptionClick(e.target.value)}
132138
tabIndex="0"
133139
>
134-
<option value="">---</option>
140+
<option value="">---</option>
135141
{map(options, (option, index) => (
136142
<option key={index} value={option.value}>
137143
{option.label}
@@ -188,6 +194,7 @@ SelectComponent.propTypes = {
188194
onChange: PropTypes.func,
189195
fluid: PropTypes.bool,
190196
label: PropTypes.string,
197+
onReset: PropTypes.any,
191198
multiple: PropTypes.bool,
192199
loading: PropTypes.bool,
193200
isRequired: PropTypes.bool,
@@ -223,6 +230,7 @@ SelectComponent.defaultProps = {
223230
options: [],
224231
multiple: false,
225232
isRequired: false,
233+
onReset: null,
226234
onChange: null,
227235
}
228236

@@ -241,6 +249,7 @@ const Select = ({
241249
multiple,
242250
loading,
243251
isCustom,
252+
onReset,
244253
...dropdownProps
245254
}) => {
246255
if (!visible) return null
@@ -263,6 +272,7 @@ const Select = ({
263272
multiple,
264273
loading,
265274
isCustom,
275+
onReset,
266276
...dropdownProps,
267277
}}
268278
/>
@@ -283,6 +293,7 @@ Select.propTypes = {
283293
fluid: PropTypes.bool,
284294
label: PropTypes.string,
285295
multiple: PropTypes.bool,
296+
onReset: PropTypes.any,
286297
loading: PropTypes.bool,
287298
isRequired: PropTypes.bool,
288299
isCustom: PropTypes.bool, // use HTML5 option select instead
@@ -298,6 +309,7 @@ Select.defaultProps = {
298309
disabled: false,
299310
options: [],
300311
validate: null,
312+
onReset: null,
301313
onChange: null,
302314
normalize: null,
303315
multiple: false,

components/Input/parts/InputLabel.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React, { memo, useState, useRef } from 'react'
22
import classNames from 'classnames'
33
import PropTypes from 'prop-types'
4-
import { FcQuestions } from 'react-icons/fc'
4+
import { FcQuestions, FcCancel } from 'react-icons/fc'
5+
import { Button } from '~components'
56
import useOutsideClick from '~hooks/useOutsideClick'
67
import styles from '../Input.module.scss'
78

@@ -13,6 +14,7 @@ const InputLabel = ({
1314
small,
1415
tooltip,
1516
className,
17+
onReset,
1618
}) => {
1719
const [tooltipActive, setTooltipActive] = useState(false)
1820
const ref = useRef(null)
@@ -32,8 +34,22 @@ const InputLabel = ({
3234
<span>{label}</span>
3335
{isRequired && <span className={styles.required}>&nbsp;*</span>}
3436
</label>
37+
{onReset && (
38+
<button
39+
onClick={(e) => {
40+
e.preventDefault()
41+
e.stopPropagation()
42+
onReset()
43+
}}
44+
type="button"
45+
className={styles.cancelButton}
46+
>
47+
<FcCancel />
48+
</button>
49+
)}
3550
{tooltip && (
3651
<button
52+
type="button"
3753
className={styles.tooltipButton}
3854
onClick={() => setTooltipActive(!tooltipActive)}
3955
>
@@ -54,6 +70,7 @@ InputLabel.propTypes = {
5470
small: PropTypes.bool,
5571
name: PropTypes.string,
5672
tooltip: PropTypes.string,
73+
onReset: PropTypes.any,
5774
}
5875

5976
InputLabel.defaultProps = {
@@ -62,6 +79,7 @@ InputLabel.defaultProps = {
6279
className: null,
6380
tooltip: null,
6481
isRequired: false,
82+
onReset: null,
6583
}
6684

6785
export default memo(InputLabel)

0 commit comments

Comments
 (0)