/
SearchResultPage.vue
144 lines (132 loc) · 3.76 KB
/
SearchResultPage.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
<template>
<main data-test="search-results-page" class="flex flex-col p-8 h-auto">
<div>
<h1>Data Sources Search results</h1>
<p data-test="search-results-section-header-p" class="text-2xl">
Searching for <span class="font-semibold">"{{ searchTerm }}"</span> in
<span class="font-semibold">"{{ location }}"</span>.
<span v-if="searched && count > 0" data-test="search-results-count"
>Found {{ getResultsCopy() }}.</span
>
</p>
<Button class="my-4" intent="secondary" @click="() => $router.push('/')">
<i class="fa fa-plus" /> New search
</Button>
</div>
<p v-if="!searched" component="p" data-test="loading" :span-column="3">
Loading results...
</p>
<p v-else-if="searched && count === 0" data-test="no-search-results">
No results found.
</p>
<div v-else>
<p class="text-xl max-w-full">
If you don't see what you need,
<a
href="https://airtable.com/shrbFfWk6fjzGnNsk"
data-test="search-results-request-link"
>
make a request <i class="fa fa-external-link" />
</a>
</p>
<p class="text-xl max-w-full">
To see these results in a table,
<a href="https://airtable.com/shrUAtA8qYasEaepI">
view the full database <i class="fa fa-external-link" />
</a>
</p>
</div>
<div data-test="search-results">
<section
v-for="section in uiShape"
:key="section.header"
data-test="search"
class="mt-8 p-0 w-full"
>
<h2 class="section-subheading w-full">
{{ section.header }}
</h2>
<div class="grid pdap-grid-container-column-3 gap-4">
<SearchResultCard
v-for="result in [...getAllRecordsFromSection(section)]"
:key="result.record"
data-test="search-results-cards"
:data-source="result"
/>
</div>
</section>
</div>
</main>
</template>
<script>
import { Button } from 'pdap-design-system';
import SearchResultCard from '../components/SearchResultCard.vue';
import axios from 'axios';
import pluralize from '../util/pluralize';
import { SEARCH_RESULTS_UI_SHAPE } from '../util/pageData';
export default {
name: 'SearchResultPage',
components: {
Button,
SearchResultCard,
},
data: () => ({
count: 0,
searched: false,
searchResult: {},
searchTerm: '',
location: '',
uiShape: {},
}),
mounted: function () {
this.searchTerm = this.$route.params.searchTerm;
this.location = this.$route.params.location;
this.search();
},
methods: {
getAllRecordsFromSection(section) {
return section.records.reduce((acc, cur) => {
return [...acc, ...this.searchResult[cur.type]];
}, []);
},
getResultsCopy() {
return `${this.count} ${pluralize('result', this.count)}`;
},
async search() {
const url = `${
import.meta.env.VITE_VUE_API_BASE_URL
}/search-tokens?endpoint=quick-search&arg1=${this.searchTerm}&arg2=${
this.location
}`;
try {
const res = await axios.get(url);
// Format results into object keyed by record_type
const resultFormatted = res.data.data.reduce((acc, cur) => {
return {
...acc,
[cur.record_type]: Array.isArray(acc[cur.record_type])
? [...acc[cur.record_type], cur]
: [cur],
};
}, {});
// Modify ui shape object to exclude any sections / data sources that do not have records returned by API
this.uiShape = SEARCH_RESULTS_UI_SHAPE.reduce((acc, cur) => {
const recordsFiltered = cur.records.filter(
(record) => resultFormatted[record.type],
);
return recordsFiltered.length > 0
? [...acc, { header: cur.header, records: recordsFiltered }]
: acc;
}, []);
// Set data and away we go
this.searchResult = resultFormatted;
this.count = res.data.count;
} catch (error) {
console.error(error);
} finally {
this.searched = true;
}
},
},
};
</script>