1 | import React from 'react'
|
2 | import PropTypes from 'prop-types'
|
3 | import styled from 'styled-components'
|
4 |
|
5 | import cloudinary from 'SRC/services/cloudinary'
|
6 |
|
7 | const SearchDiv = styled.div`
|
8 | position: relative;
|
9 | display: flex;
|
10 | align-items: center;
|
11 | `
|
12 |
|
13 | const SearchBarDiv = styled.div`
|
14 | z-index: 4;
|
15 | position: fixed;
|
16 | top: 0;
|
17 | left: 0;
|
18 | height: 326px;
|
19 | width: 100%;
|
20 | background-color: #FFFFFF;
|
21 | overflow: hidden;
|
22 |
|
23 | ${props => props.theme.breakpointsVerbose.aboveTabletMax`
|
24 | height: 336px;
|
25 | `}
|
26 | `
|
27 |
|
28 | const SearchModalDiv = styled.div`
|
29 | z-index: 3;
|
30 | position: fixed;
|
31 | width: 100%;
|
32 | height: 100%;
|
33 | top: 0;
|
34 | left: 0;
|
35 | background-color: rgba(216, 216, 216, 0.7);
|
36 | `
|
37 |
|
38 | const SearchOverlayImage = styled.img`
|
39 | margin: 17px auto 0 auto;
|
40 | display: block;
|
41 |
|
42 | ${props => props.theme.breakpointsVerbose.aboveTabletMax`
|
43 | margin: 30px auto 0 auto;
|
44 | `}
|
45 | `
|
46 |
|
47 | const SearchExitWrapperDiv = styled.div`
|
48 | display: inline-block;
|
49 | cursor: pointer;
|
50 | width: 37px;
|
51 | height: 37px;
|
52 | position: absolute;
|
53 | top: 0;
|
54 | right: 0;
|
55 |
|
56 | ${props => props.theme.breakpointsVerbose.aboveTabletMax`
|
57 | top: 53px;
|
58 | right: calc(50% - 300px - 10%);
|
59 | `}
|
60 |
|
61 | > svg {
|
62 | position: absolute;
|
63 | bottom: 0;
|
64 | left: 0;
|
65 |
|
66 | ${props => props.theme.breakpointsVerbose.aboveTabletMax`
|
67 | top: 10px;
|
68 | left: 10px;
|
69 | `}
|
70 | }
|
71 | `
|
72 |
|
73 | const SearchSuggestionsDiv = styled.div`
|
74 | height: 42px;
|
75 | width: 265px;
|
76 | margin: auto;
|
77 | margin-top: 5px;
|
78 | font-family: ff-din-web,Helvetica,Arial,sans-serif;
|
79 | font-size: 16px;
|
80 | text-align: center;
|
81 | color: #00003C;
|
82 |
|
83 | ${props => props.theme.breakpointsVerbose.aboveTabletMax`
|
84 | height: 21px;
|
85 | width: 565px;
|
86 | margin-top: 15px;
|
87 | `}
|
88 | `
|
89 |
|
90 | const SearchForm = styled.form`
|
91 | margin: auto;
|
92 | margin-top: 75px;
|
93 | width: 280px;
|
94 | height: 37px;
|
95 | border-bottom: 1px solid #0073D1;
|
96 |
|
97 | ${props => props.theme.breakpointsVerbose.aboveTabletMax`
|
98 | margin-top: 90px;
|
99 | width: 600px;
|
100 | height: 37px;
|
101 | `}
|
102 | `
|
103 |
|
104 | const SearchClearWrapperDiv = styled.div`
|
105 | display: inline-block;
|
106 | cursor: pointer;
|
107 | height: 26px;
|
108 | width: 26px;
|
109 |
|
110 | > svg {
|
111 | margin-left: 10px;
|
112 |
|
113 | ${props => props.theme.breakpointsVerbose.aboveTabletMax`
|
114 | margin-bottom: 10px;
|
115 | `}
|
116 | }
|
117 | `
|
118 |
|
119 | const SearchInput = styled.input`
|
120 | width: 250px;
|
121 | height: 36px;
|
122 | border: 0;
|
123 | outline: none;
|
124 | font-family: ${props => props.theme.fonts.secondaryFont};
|
125 | font-size: 26px;
|
126 | font-weight: 500;
|
127 | color: #00003C;
|
128 | display: inline-block;
|
129 | padding: 0;
|
130 | margin: 0;
|
131 |
|
132 | ${props => props.theme.breakpointsVerbose.aboveTabletMax`
|
133 | width: 570px;
|
134 | height: 34px;
|
135 | `}
|
136 | `
|
137 |
|
138 | class BaseSearchModal extends React.Component {
|
139 | constructor (props) {
|
140 | super(props)
|
141 |
|
142 | this.state = { searchTerm: props.initialSearchTerm || '' }
|
143 |
|
144 | this.updateSearchTerm = this.updateSearchTerm.bind(this)
|
145 | this.clearSearchInput = this.clearSearchInput.bind(this)
|
146 | this.keyDownSearchInput = this.keyDownSearchInput.bind(this)
|
147 | this.submitSearch = this.submitSearch.bind(this)
|
148 | }
|
149 |
|
150 | updateSearchTerm = (event) => {
|
151 | const { saveInitialSearchTerm } = this.props
|
152 |
|
153 | const currentSearchTerm = event.target.value
|
154 |
|
155 | this.setState({ searchTerm: currentSearchTerm })
|
156 | saveInitialSearchTerm(currentSearchTerm)
|
157 | }
|
158 |
|
159 | clearSearchInput = () => {
|
160 | this.setState({ searchTerm: '' })
|
161 |
|
162 | const searchInput = document.getElementById('input-search');
|
163 | searchInput.focus()
|
164 | }
|
165 |
|
166 |
|
167 | keyDownSearchInput = (event) => {
|
168 | const { exitSearch } = this.props
|
169 |
|
170 | if (event.keyCode === 27) { exitSearch() }
|
171 | }
|
172 |
|
173 | submitSearch = (event) => {
|
174 | event.preventDefault()
|
175 |
|
176 | const { exitSearch, submitSearch } = this.props
|
177 | const { searchTerm } = this.state
|
178 |
|
179 | if (searchTerm.length > 0) {
|
180 | submitSearch(searchTerm)
|
181 | exitSearch()
|
182 | }
|
183 | }
|
184 |
|
185 | render () {
|
186 | const { exitSearch } = this.props
|
187 | const { searchTerm } = this.state
|
188 |
|
189 | const searchOverlayImageSrc = cloudinary.url('web/search/SearchOverlayDesktop')
|
190 |
|
191 | return (
|
192 | <SearchDiv>
|
193 | <SearchBarDiv>
|
194 | <SearchForm role='search' onSubmit={this.submitSearch}>
|
195 | <SearchInput
|
196 | id='input-search'
|
197 | value={searchTerm}
|
198 | onChange={this.updateSearchTerm}
|
199 | onKeyDown={this.keyDownSearchInput}
|
200 | autoFocus />
|
201 | <SearchClearWrapperDiv onClick={this.clearSearchInput}>
|
202 | <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
|
203 | <g fill="none" fillRule="evenodd">
|
204 | <circle cx="7" cy="7" r="7" fill="#DCD6CE" />
|
205 | <path stroke="#FFF" strokeLinecap="square" strokeWidth="2" d="M9.898 4.142l-5.796 6.216M4.102 4.142l5.796 6.216" />
|
206 | </g>
|
207 | </svg>
|
208 | </SearchClearWrapperDiv>
|
209 | </SearchForm>
|
210 |
|
211 | <SearchSuggestionsDiv>Find it fast! Try: rainbow, sequin, neon, camo, ombre…</SearchSuggestionsDiv>
|
212 | <SearchExitWrapperDiv onClick={() => exitSearch()}>
|
213 | <svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 17 17">
|
214 | <g fill="none" fillRule="evenodd" stroke="#0073D1">
|
215 | <path d="M1.37 1.841a.442.442 0 0 0-.002.628l12.69 12.69a.439.439 0 0 0 .628 0 .442.442 0 0 0 .001-.628L1.997 1.84a.439.439 0 0 0-.628 0z" />
|
216 | <path d="M1.37 15.159a.442.442 0 0 0 .627 0l12.69-12.69a.439.439 0 0 0 0-.628.442.442 0 0 0-.628 0L1.369 14.53a.439.439 0 0 0 0 .628z" />
|
217 | </g>
|
218 | </svg>
|
219 | </SearchExitWrapperDiv>
|
220 |
|
221 | <SearchOverlayImage src={searchOverlayImageSrc} />
|
222 | </SearchBarDiv>
|
223 | <SearchModalDiv onClick={() => exitSearch()} />
|
224 | </SearchDiv>
|
225 | )
|
226 | }
|
227 | }
|
228 |
|
229 | BaseSearchModal.propTypes = {
|
230 | initialSearchTerm: PropTypes.string,
|
231 | saveInitialSearchTerm: PropTypes.func,
|
232 | exitSearch: PropTypes.func,
|
233 | submitSearch: PropTypes.func
|
234 | }
|
235 |
|
236 | const SearchModal = styled(BaseSearchModal)``
|
237 |
|
238 | export default SearchModal
|