Passed
Push — feature/lighthouse ( 506e99...db2e00 )
by Kevin Van
11:37 queued 05:51
created

Search.componentDidMount   A

Complexity

Conditions 1

Size

Total Lines 50
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 34
dl 0
loc 50
rs 9.064
c 0
b 0
f 0
cc 1
1
import React, { Component } from "react"
2
import Axios from "axios"
3
import { Link } from "gatsby"
4
5
import * as JsSearch from "js-search"
6
7
import "./search-container.scss"
8
9
class Search extends Component {
10
  state = {
11
    articleList: [],
12
    teamList: [],
13
    playerList: [],
14
    staffList: [],
15
    eventList: [],
16
    search: [],
17
    searchResults: [],
18
    isLoading: true,
19
    isError: false,
20
    searchQuery: ``,
21
  }
22
  /**
23
   * React lifecycle method to fetch the data
24
   */
25
  async componentDidMount() {
26
    Axios.get(`https://api.kcvvelewijt.be/jsonapi/node/article?sort=-created`)
27
      .then((result) => {
28
        const articleData = result.data.data
29
        this.setState({ articleList: articleData })
30
31
        return Axios.get(
32
          `https://api.kcvvelewijt.be/jsonapi/node/team?sort=title`
33
        )
34
      })
35
      .then((result) => {
36
        const teamData = result.data.data
37
        this.setState({ teamList: teamData })
38
39
        return Axios.get(
40
          `https://api.kcvvelewijt.be/jsonapi/node/player?sort=title`
41
        )
42
      })
43
      .then((result) => {
44
        const playerData = result.data.data
45
        this.setState({ playerList: playerData })
46
47
        return Axios.get(
48
          `https://api.kcvvelewijt.be/jsonapi/node/staff?sort=title`
49
        )
50
      })
51
      .then((result) => {
52
        const staffData = result.data.data
53
        this.setState({ staffList: staffData })
54
55
        return Axios.get(
56
          `https://api.kcvvelewijt.be/jsonapi/node/event?sort=title`
57
        )
58
      })
59
      .then((result) => {
60
        const eventData = result.data.data
61
        this.setState({ eventList: eventData })
62
63
        setTimeout(() => {
64
          this.rebuildIndex()
65
        }, 250)
66
      })
67
      .catch((err) => {
68
        this.setState({ isError: true })
69
        console.log(`====================================`)
70
        console.log(`Something bad happened while fetching some data for the search.\n${err}`)
71
        console.log(`====================================`)
72
      })
73
  }
74
  /**
75
   * rebuilds the overall index based on the options
76
   */
77
  rebuildIndex = () => {
78
    const {
79
      articleList,
80
      teamList,
81
      playerList,
82
      staffList,
83
      eventList,
84
    } = this.state
85
    const dataToSearch = new JsSearch.Search(`id`)
86
    /**
87
     *  defines a indexing strategy for the data
88
     * more more about it in here https://github.com/bvaughn/js-search#configuring-the-index-strategy
89
     */
90
    dataToSearch.indexStrategy = new JsSearch.PrefixIndexStrategy()
91
    /**
92
     * defines the sanitizer for the search
93
     * to prevent some of the words from being excluded
94
     *
95
     */
96
    dataToSearch.sanitizer = new JsSearch.LowerCaseSanitizer()
97
98
    /**
99
     * defines the search index
100
     * read more in here https://github.com/bvaughn/js-search#configuring-the-search-index
101
     */
102
    dataToSearch.searchIndex = new JsSearch.TfIdfSearchIndex(`id`)
103
    dataToSearch.addIndex([`attributes`, `body`, `processed`])
104
    dataToSearch.addIndex([`attributes`, `title`])
105
    dataToSearch.addDocuments(articleList)
106
    dataToSearch.addDocuments(teamList)
107
    dataToSearch.addDocuments(playerList)
108
    dataToSearch.addDocuments(staffList)
109
    dataToSearch.addDocuments(eventList)
110
    this.setState({ search: dataToSearch, isLoading: false })
111
  }
112
  /**
113
   * handles the input change and perform a search with js-search
114
   * in which the results will be added to the state
115
   */
116
  searchData = (e) => {
117
    const { search } = this.state
118
    const queryResult = search.search(e.target.value)
119
120
    this.setState({ searchQuery: e.target.value, searchResults: queryResult })
121
  }
122
123
  handleSubmit = (e) => {
124
    e.preventDefault()
125
  }
126
127
  renderForm = (searchQuery) => (
128
    <form onSubmit={this.handleSubmit}>
129
      <div>
130
        <label className={"search_input__label"} htmlFor="search">
131
          <input
132
            id="search"
133
            onChange={this.searchData}
134
            className={"search_input__input"}
135
            placeholder="Spelersnaam, ploegnaam, deel van een artikel..."
136
            value={searchQuery}
137
            required
138
          />
139
          <span className={"search_input__label__inner_wrapper"}>
140
            <span className={"search_input__label__inner_text"}>
141
              Waar bent u naar op zoek?
142
            </span>
143
          </span>
144
        </label>
145
      </div>
146
    </form>
147
  )
148
149
  renderQueryResultsCaption = () => (
150
    <caption>
151
      <i
152
        className={`article__footer_related__icon article__footer_related__icon--node--article fa`}
153
      />{" "}
154
      Nieuwsbericht
155
      <br />
156
      <i
157
        className={`article__footer_related__icon article__footer_related__icon--node--team fa`}
158
      />{" "}
159
      Ploeg
160
      <br />
161
      <i
162
        className={`article__footer_related__icon article__footer_related__icon--node--player fa`}
163
      />{" "}
164
      Speler
165
      <br />
166
      <i
167
        className={`article__footer_related__icon article__footer_related__icon--node--staff fa`}
168
      />{" "}
169
      Staflid
170
      <br />
171
      <i
172
        className={`article__footer_related__icon article__footer_related__icon--node--event fa`}
173
      />{" "}
174
      Evenement
175
      <br />
176
    </caption>
177
  )
178
179
  renderQueryResultItem = (item) => (
180
    <tr key={`row_${item.attributes.drupal_internal__nid}`}>
181
      <td>
182
        <Link to={item.attributes.path.alias}>
183
          <i
184
            className={`article__footer_related__icon article__footer_related__icon--${item.type} fa`}
185
          />
186
          {item.attributes.title}
187
        </Link>
188
      </td>
189
    </tr>
190
  )
191
192
  renderQueryResults = (queryResults) => (
193
    <div>
194
      <h3>Gevonden resultaten: {queryResults.length}</h3>
195
      <table>
196
        <thead>
197
          <tr>
198
            <th>Titel</th>
199
          </tr>
200
        </thead>
201
        <tbody>
202
          {/* eslint-disable */}
203
          {queryResults.map((item) => {
204
            return this.renderQueryResultItem(item)
205
          })}
206
          {/* eslint-enable */}
207
        </tbody>
208
        {this.renderQueryResultsCaption()}
209
      </table>
210
    </div>
211
  )
212
213
  render() {
214
    const { isError, isLoading, searchResults, searchQuery } = this.state
215
    const queryResults = searchQuery === `` ? [] : searchResults
216
217
    if (isLoading) {
218
      return <p>Zoekfunctie is aan het laden...</p>
219
    }
220
    if (isError) {
221
      return (
222
        <>
223
          <h2>Aiiii...</h2>
224
          <h3>
225
            Er ging iets mis - gelieve{" "}
226
            <a href="mailto:[email protected]">contact op te nemen</a>{" "}
227
            indien het probleem zich blijft voordoen.
228
          </h3>
229
        </>
230
      )
231
    }
232
233
    return (
234
      <div className={"search--placeholder"}>
235
        {this.renderForm(searchQuery)}
236
237
        {queryResults.length > 0 && this.renderQueryResults(queryResults)}
238
      </div>
239
    )
240
  }
241
}
242
export default Search
243