Skip to content

Commit ffe1669

Browse files
committed
Added search functionality
1 parent cc7c439 commit ffe1669

File tree

7 files changed

+256
-72
lines changed

7 files changed

+256
-72
lines changed

components/Results/index.vue

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<template>
2+
<div class="results">
3+
<p
4+
v-for="(item, index) in items"
5+
:key="index"
6+
class="cases">
7+
{{ item.label }}
8+
<animated-number
9+
v-if="showValue"
10+
:value="item.value"
11+
:formatValue="formatNumber"
12+
:duration="duration"
13+
:style="`color: ${item.color}`" />
14+
</p>
15+
</div>
16+
</template>
17+
18+
<script>
19+
import AnimatedNumber from 'animated-number-vue'
20+
21+
export default {
22+
name: 'Results',
23+
components: {
24+
AnimatedNumber
25+
},
26+
props: {
27+
items: Array,
28+
duration: Number,
29+
showValue: Boolean
30+
},
31+
methods: {
32+
formatNumber(s) {
33+
return s.toFixed(0).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ',')
34+
}
35+
}
36+
}
37+
</script>
38+
39+
40+
<style lang="scss" scoped>
41+
.results {
42+
43+
.cases {
44+
margin-bottom: 12px;
45+
46+
span {
47+
font-weight: 700;
48+
}
49+
}
50+
}
51+
</style>

components/Search/index.vue

Lines changed: 157 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
ref="countries"
1111
type="text"
1212
v-model="country"
13+
placeholder="Country"
1314
@keydown.enter="enter"
1415
@keydown.down="down"
1516
@keydown.up="up"
@@ -19,17 +20,24 @@
1920
<div
2021
class="provinces-wrapper"
2122
:class="{
22-
'is-show': provinces && provinces.length
23+
'is-show': hasSelected && provinces && provinces.length
2324
}">
2425
<select ref="provinces">
26+
<option
27+
label="Province"
28+
value=""
29+
selected
30+
disabled />
2531
<option
2632
v-for="(province, index) in provinces"
2733
:key="index"
2834
:label="province"
2935
:value="province" />
3036
</select>
3137
</div>
32-
<button @click="onSearch">Search</button>
38+
<button
39+
:disabled="!hasSelected"
40+
@click="onSearch">Search</button>
3341
</div>
3442
<ul class="dropdown-menu">
3543
<li
@@ -41,12 +49,29 @@
4149
<span>{{ suggestion }}</span>
4250
</li>
4351
</ul>
52+
<div
53+
v-if="hasSelected && country_case.length"
54+
class="search-results">
55+
<p class="">Cases</p>
56+
<Results
57+
:items="results"
58+
:duration="duration"
59+
:show-value="!!country_case.length" />
60+
</div>
4461
</div>
4562
</template>
4663

4764
<script>
65+
import { mapGetters } from 'vuex'
66+
import AnimatedNumber from 'animated-number-vue'
67+
import Results from '~/components/Results'
68+
4869
export default {
4970
name: 'Search',
71+
components: {
72+
Results,
73+
AnimatedNumber
74+
},
5075
props: {
5176
suggestions: {
5277
type: Object,
@@ -58,6 +83,9 @@ export default {
5883
}
5984
},
6085
computed: {
86+
...mapGetters([
87+
'country_case'
88+
]),
6189
setSelection: {
6290
get() {
6391
return this.selection
@@ -78,23 +106,53 @@ export default {
78106
return (
79107
this.country !== '' && this.matches.length != 0 && this.open === true
80108
)
109+
},
110+
results() {
111+
const cases = this.country_case || []
112+
return [
113+
{
114+
label: 'Confirmed / ',
115+
value: cases.length ? cases[0].properties.confirmed_count : 0,
116+
color: '#ffa500'
117+
},
118+
{
119+
label: 'Recovered / ',
120+
value: cases.length ? cases[0].properties.recovered_count : 0,
121+
color: '#66a266'
122+
},
123+
{
124+
label: 'Deaths / ',
125+
value: cases.length ? cases[0].properties.dead_count : 0,
126+
color: '#b20000'
127+
}
128+
]
81129
}
82130
},
83131
data() {
84132
return {
85133
open: false,
86134
current: 0,
87135
country: '',
88-
provinces: ''
136+
provinces: [],
137+
tempValue: null,
138+
hasSelected: false,
139+
duration: 1000
89140
}
90141
},
91142
methods: {
92143
enter() {
93144
this.setSelection = this.matches[this.current]
145+
this.tempValue = this.country
94146
this.open = false
147+
this.hasSelected = true
95148
this.$nextTick(_ => {
96149
if (this.$refs.provinces) this.$refs.provinces.focus()
97150
})
151+
this.$gtag('event', 'enter', {
152+
event_category: 'input',
153+
event_label: 'input enter',
154+
value: this.country
155+
})
98156
},
99157
up() {
100158
if (this.current > 0) this.current--
@@ -105,24 +163,41 @@ export default {
105163
isActive(index) {
106164
return index === this.current
107165
},
108-
change() {
166+
change(e) {
109167
if (!this.open) {
110168
this.open = true
111169
this.current = 0
112170
}
171+
this.tempValue = !e.target.value ? null : e.target.value
172+
if (this.tempValue === null) {
173+
this.provinces = []
174+
this.hasSelected = false
175+
}
113176
},
114177
suggestionClick(index) {
115178
this.setSelection = this.matches[index]
179+
this.tempValue = this.country
116180
this.open = false
181+
this.hasSelected = true
117182
this.$nextTick(_ => {
118183
if (this.$refs.provinces) this.$refs.provinces.focus()
119184
})
185+
this.$gtag('event', 'click', {
186+
event_category: 'select',
187+
event_label: 'select click',
188+
value: this.country
189+
})
120190
},
121191
onSearch() {
122192
this.$store.dispatch('getCasesByCountry', {
123193
country: this.country,
124194
province: this.$refs.provinces.value
125195
})
196+
this.$gtag('event', 'click', {
197+
event_category: 'search',
198+
event_label: 'search click',
199+
value: `${this.country}${this.$refs.provinces.value ? ', ' + this.$refs.provinces.value : ''}`
200+
})
126201
}
127202
}
128203
}
@@ -141,28 +216,102 @@ export default {
141216
}
142217
143218
.countries-wrapper {
219+
display: block;
220+
144221
input {
145222
margin: 0;
146-
padding: 0;
147-
border: 0;
148-
border-bottom: 1px solid #ffffff;
223+
padding: 12px 16px 14px;
224+
border: 1px solid #ffffff;
225+
border-radius: 4px;
226+
width: calc(100% - 32px);
227+
font-size: 24px;
149228
color: #ffffff;
150229
background-color: transparent;
151-
outline: none;
230+
231+
&::placeholder {
232+
color: #cccccc;
233+
}
152234
}
153235
}
154236
155237
.provinces-wrapper {
238+
position: relative;
156239
display: none;
240+
margin-top: 16px;
241+
242+
&:after {
243+
content: "";
244+
width: 0;
245+
height: 0;
246+
border: 4px solid transparent;
247+
border-color: #fff transparent transparent transparent;
248+
position: absolute;
249+
top: 50%;
250+
right: 10px;
251+
}
157252
158253
&.is-show {
159254
display: block;
160255
}
256+
257+
select {
258+
padding: 12px 16px 14px;
259+
border: 1px solid #ffffff;
260+
border-radius: 4px;
261+
font-size: 24px;
262+
color: #ffffff;
263+
width: 100%;
264+
background-color: transparent;
265+
appearance: none;
266+
}
267+
}
268+
269+
button {
270+
border-radius: 4px;
271+
margin-top: 16px;
272+
padding: 12px 16px 14px;
273+
font-size: 24px;
274+
width: 100%;
275+
background-color: #ffffff;
276+
cursor: pointer;
161277
}
162278
163279
.dropdown-menu {
280+
position: absolute;
281+
top: 60px;
164282
display: none;
283+
border-radius: 4px;
284+
box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 4px -1px, rgba(0, 0, 0, 0.14) 0px 4px 5px 0px, rgba(0, 0, 0, 0.12) 0px 1px 10px 0px;
285+
margin: 0;
286+
padding: 0;
287+
max-height: 24vh;
165288
width: 100%;
289+
overflow: auto;
290+
background-color: #ffffff;
291+
292+
li {
293+
display: block;
294+
padding: 12px 8px;
295+
font-size: 18px;
296+
color: #343332;
297+
298+
&.active {
299+
background-color: #dddddd;
300+
}
301+
}
302+
}
303+
304+
.search-results {
305+
font-size: 24px;
306+
307+
& > p{
308+
margin-top: 24px;
309+
margin-bottom: 12px;
310+
font-weight: 700;
311+
letter-spacing: 1px;
312+
color: #cccccc;
313+
text-transform: uppercase;
314+
}
166315
}
167316
}
168317
</style>

0 commit comments

Comments
 (0)