Passed
Push — feature/share-pages ( 23d161...c7a8d0 )
by Kevin Van
03:31
created

PlayerShare.onCapture   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
1
import React, { Component, Fragment } from "react"
2
import { graphql, StaticQuery } from "gatsby"
3
import { mapPositionCode } from "../scripts/helper"
4
import { getSrc } from "gatsby-plugin-image"
5
import { useQueryParam, StringParam } from "use-query-params"
6
import * as htmlToImage from "html-to-image"
7
8
import moment from "moment"
9
10
import "./player.scss"
11
import { Link } from "gatsby"
12
import Helmet from "react-helmet"
13
14
import Icon from "../components/Icon"
15
import RelatedNews from "../components/RelatedNews"
16
17
import iconCleansheet from "../images/i_cleansheet.png"
18
import iconCardRed from "../images/i_card_red.png"
19
import iconCardYellow from "../images/i_card_yellow.png"
20
import iconGoal from "../images/i_goal.png"
21
import Card from "./Card"
22
23
// eslint-disable-next-line
24
String.prototype.replaceAll = function (search, replacement) {
25
  var target = this
26
  return target.replace(new RegExp(search, `g`), replacement)
27
}
28
29
class Player extends Component {
30
  render() {
31
    const { player, config } = this.props
32
    const [view, setView] = useQueryParam(`view`, StringParam)
33
34
    if (view === `share`) {
35
      return <PlayerShare player={player} />
36
    }
37
    return <PlayerDetail player={player} config={config} />
38
  }
39
}
40
41
class PlayerShare extends Component {
42
  renderPlayerName = (player) => (
43
    <h1 className={`player-detail__name`}>
44
      <span className={`player-detail__name-first`}>{player.field_firstname}</span>
45
      <span className={`player-detail__name-last`}>{player.field_lastname}</span>
46
    </h1>
47
  )
48
  renderPlayerImage = (player) => (
49
    <Fragment>
50
      <div
51
        className={`player-detail__bg-avatar`}
52
        style={
53
          player.relationships.field_image && {
54
            backgroundImage: `url(${getSrc(
55
              player.relationships.field_image.localFile.childImageSharp.gatsbyImageData
56
            )})`,
57
          }
58
        }
59
      />
60
    </Fragment>
61
  )
62
  renderPlayerHeader = (player) => (
63
    <Fragment>
64
      {this.renderPlayerName(player)}
65
      {this.renderPlayerImage(player)}
66
67
      <div className={`player-detail__bg-shirt-number`} aria-hidden="true">
68
        {player.field_shirtnumber || ``}
69
      </div>
70
    </Fragment>
71
  )
72
73
  onCapture = () => {
74
    htmlToImage.toPng(document.getElementById(`share-image-source`)).then(function (dataUrl) {
75
      const image = document.getElementById(`share-image`)
76
      image.src = dataUrl
77
    })
78
  }
79
80
  render() {
81
    const { player } = this.props
82
    const [score] = useQueryParam(`score`, StringParam)
83
    const [match] = useQueryParam(`match`, StringParam)
84
85
    const fallback =
86
      player.relationships?.field_image?.localFile?.childImageSharp?.gatsbyImageData?.placeholder?.fallback || null
87
88
    return (
89
      <Fragment>
90
        <button onClick={this.onCapture} id="share-image-button">
91
          Genereer afbeelding
92
        </button>
93
        <img id="share-image" width="1080" height="1920" />
94
        <article className={`player-detail player-detail--share`} id="share-image-source">
95
          <Helmet
96
            bodyAttributes={{
97
              class: `share`,
98
            }}
99
          />
100
          <img src={fallback} class="player-detail__bg--fallback" />
101
          {this.renderPlayerHeader(player)}
102
103
          <div className={`bg-green-mask player-detail--share__details`}>
104
            <span className="player-detail--share__match">{match}</span>
105
            <span className="player-detail--share__title">Goal!</span>
106
            <span className="player-detail--share__score">{score}</span>
107
          </div>
108
        </article>
109
      </Fragment>
110
    )
111
  }
112
}
113
114
/**
115
 */
116
class PlayerDetail extends Component {
117
  constructor(props) {
118
    super(props)
119
120
    this.state = {
121
      data: [],
122
      loading: true,
123
    }
124
125
    const {
126
      config: {
127
        site: {
128
          siteMetadata: { kcvvPsdApi },
129
        },
130
      },
131
      player: { field_vv_id: playerId },
132
    } = this.props
133
134
    this.kcvvPsdApi = kcvvPsdApi
135
    this.playerId = playerId
136
  }
137
138
  updateData() {
139
    if (this.playerId === null) {
140
      return
141
    }
142
143
    const apiUrl = `${this.kcvvPsdApi}/stats/player/${this.playerId}`
144
145
    fetch(apiUrl)
146
      .then((response) => response.json())
147
      .then((json) => this.setState({ data: json, loading: false }))
148
      .catch(() => this.setState({ data: {}, loading: false }))
149
  }
150
151
  componentDidMount() {
152
    this.updateData()
153
  }
154
155
  renderPlayerName = (player) => (
156
    <h1 className={`player-detail__name`}>
157
      <span className={`player-detail__name-first`}>{player.field_firstname}</span>
158
      <span className={`player-detail__name-last`}>{player.field_lastname}</span>
159
    </h1>
160
  )
161
  renderPlayerImage = (player) => (
162
    <div className={`bg-green-mask`}>
163
      <div
164
        className={`player-detail__bg-avatar`}
165
        style={
166
          player.relationships.field_image && {
167
            backgroundImage: `url(${getSrc(
168
              player.relationships.field_image.localFile.childImageSharp.gatsbyImageData
169
            )})`,
170
          }
171
        }
172
      />
173
      <div className={`bg-white-end`} />
174
    </div>
175
  )
176
  renderPlayerHeader = (player) => (
177
    <header className={`player-detail__header`}>
178
      {this.renderPlayerName(player)}
179
      {this.renderPlayerImage(player)}
180
181
      <div className={`player-detail__bg-shirt-number`} aria-hidden="true">
182
        {player.field_shirtnumber || ``}
183
      </div>
184
    </header>
185
  )
186
  renderPlayerStats = (player) => {
187
    if (this.state.loading === false && this.state.data) {
188
      const { playerStatistics = [] } = this.state.data
189
190
      return (
191
        <aside className={`player-detail__statistics`}>
192
          <section className={`player-detail__statistics-item`}>
193
            <div className={`player-detail__statistics-item__number`}>
194
              {playerStatistics.reduce((a, b) => a + (b?.gamesPlayed || 0), 0) || `0`}
195
            </div>
196
            <div className={`player-detail__statistics-item__label`}>Wedstrijden</div>
197
          </section>
198
199
          {(player.field_position === `k` || player.field_position === `d`) && (
200
            <section className={`player-detail__statistics-item`}>
201
              <div className={`player-detail__statistics-item__number`}>
202
                {playerStatistics.reduce((a, b) => a + (b?.cleanSheets || 0), 0) || `0`}
203
              </div>
204
              <div className={`player-detail__statistics-item__label`}>Cleansheets</div>
205
            </section>
206
          )}
207
          {player.field_position !== `k` && (
208
            <section className={`player-detail__statistics-item`}>
209
              <div className={`player-detail__statistics-item__number`}>
210
                {playerStatistics.reduce((a, b) => a + (b?.goals || 0), 0) || `0`}
211
              </div>
212
              <div className={`player-detail__statistics-item__label`}>Doelpunten</div>
213
            </section>
214
          )}
215
          <section className={`player-detail__statistics-item`}>
216
            <div className={`player-detail__statistics-item__number`}>
217
              {playerStatistics.reduce((a, b) => a + (b?.yellowCards || 0), 0) || `0`}
218
            </div>
219
            <div className={`player-detail__statistics-item__label`}>Gele kaarten</div>
220
          </section>
221
          <section className={`player-detail__statistics-item`}>
222
            <div className={`player-detail__statistics-item__number`}>
223
              {playerStatistics.reduce((a, b) => a + (b?.redCards || 0), 0) || `0`}
224
            </div>
225
            <div className={`player-detail__statistics-item__label`}>Rode kaarten</div>
226
          </section>
227
        </aside>
228
      )
229
    }
230
  }
231
232
  renderPlayerStatsFull = (player) => {
233
    if (this.state.loading === false && this.state.data) {
234
      const { playerStatistics = [] } = this.state.data
235
236
      return (
237
        <Card title="Statistieken" className={`player-detail__stats`} hasTable={true}>
238
          <table className={`player-detail__stats__table`}>
239
            <thead>
240
              <tr>
241
                <th className={`player-detail__column player-detail__column--string`}>Team</th>
242
                <th className={`player-detail__column player-detail__column--number show-for-medium`}>
243
                  <span title="Wedstrijden gespeeld">P</span>
244
                </th>
245
                <th className={`player-detail__column player-detail__column--number`}>
246
                  <span title="Wedstrijden gewonnen">W</span>
247
                </th>
248
                <th className={`player-detail__column player-detail__column--number`}>
249
                  <span title="Wedstrijden gelijkgespeeld">D</span>
250
                </th>
251
                <th className={`player-detail__column player-detail__column--number`}>
252
                  <span title="Wedstrijden verloren">L</span>
253
                </th>
254
                <th className={`player-detail__column player-detail__column--number`}>
255
                  <img
256
                    src={iconCardYellow}
257
                    title="Gele kaart"
258
                    alt="Gele kaart"
259
                    className="player-detail__stats--header_icon"
260
                  />
261
                </th>
262
                <th className={`player-detail__column player-detail__column--number`}>
263
                  <img
264
                    src={iconCardRed}
265
                    title="Rode kaart"
266
                    alt="Rode kaart"
267
                    className="player-detail__stats--header_icon"
268
                  />
269
                </th>
270
                <th className={`player-detail__column player-detail__column--number`}>
271
                  <img
272
                    src={iconGoal}
273
                    title="Doelpunt(en) gescoord"
274
                    alt="Doelpunt(en) gescoord"
275
                    className="player-detail__stats--header_icon"
276
                  />
277
                </th>
278
                <th className={`player-detail__column player-detail__column--number  show-for-medium`}>
279
                  <img
280
                    src={iconCleansheet}
281
                    title="Cleansheets"
282
                    alt="Cleansheets"
283
                    className="player-detail__stats--header_icon"
284
                  />
285
                </th>
286
                <th className={`player-detail__column player-detail__column--number`}>
287
                  <span title="Minuten gespeeld">
288
                    <Icon icon="fa-clock-o" />
289
                  </span>
290
                </th>
291
              </tr>
292
            </thead>
293
            <tbody>
294
              {playerStatistics.map(function (stats) {
295
                return (
296
                  <tr>
297
                    <td className={`player-detail__column player-detail__column--string`}>
298
                      {stats.team.replace(`Voetbal : `, ``)}
299
                    </td>
300
                    <td className={`player-detail__column player-detail__column--number show-for-medium`}>
301
                      {stats.gamesPlayed}
302
                    </td>
303
                    <td className={`player-detail__column player-detail__column--number`}>{stats.gamesWon}</td>
304
                    <td className={`player-detail__column player-detail__column--number`}>{stats.gamesEqual}</td>
305
                    <td className={`player-detail__column player-detail__column--number`}>{stats.gamesLost}</td>
306
                    <td className={`player-detail__column player-detail__column--number`}>{stats.yellowCards}</td>
307
                    <td className={`player-detail__column player-detail__column--number`}>{stats.redCards}</td>
308
                    <td className={`player-detail__column player-detail__column--number`}>{stats.goals}</td>
309
                    <td className={`player-detail__column player-detail__column--number show-for-medium`}>
310
                      {stats.cleanSheets}
311
                    </td>
312
                    <td className={`player-detail__column player-detail__column--number`}>{stats.minutes}'</td>
313
                  </tr>
314
                )
315
              })}
316
            </tbody>
317
          </table>
318
        </Card>
319
      )
320
    }
321
  }
322
  renderPlayerGamesFull = () => {
323
    if (this.state.loading === false && this.state.data) {
324
      const { gameReports = [] } = this.state.data
325
326
      return (
327
        <Card className={`player-detail__games`} title="Wedstrijden" hasTable={true}>
328
          <table className={`player-detail__games__table responsive-card-table`}>
329
            <thead>
330
              <tr>
331
                <th className={`player-detail__column player-detail__column--string`}>Team</th>
332
                <th className={`player-detail__column player-detail__column--string`}>Type</th>
333
                <th className={`player-detail__column player-detail__column--string`}>Datum</th>
334
                <th className={`player-detail__column player-detail__column--number`}>
335
                  <span title="Thuis/uit">H/A</span>
336
                </th>
337
                <th className={`player-detail__column player-detail__column--score`}>Score</th>
338
                <th className={`player-detail__column player-detail__column--string`}>Tegenstander</th>
339
                <th className={`player-detail__column player-detail__column--number`}>
340
                  <img
341
                    src={iconCardYellow}
342
                    title="Gele kaart"
343
                    alt="Gele kaart"
344
                    className="player-detail__stats--header_icon"
345
                  />
346
                </th>
347
                <th className={`player-detail__column player-detail__column--number`}>
348
                  <img
349
                    src={iconCardRed}
350
                    title="Rode kaart"
351
                    alt="Rode kaart"
352
                    className="player-detail__stats--header_icon"
353
                  />
354
                </th>
355
                <th className={`player-detail__column player-detail__column--number`}>
356
                  <img
357
                    src={iconGoal}
358
                    title="Doelpunten gescoord"
359
                    alt="Rode kaart"
360
                    className="player-detail__stats--header_icon"
361
                  />
362
                </th>
363
                <th className={`player-detail__column player-detail__column--number`}>
364
                  <span title="Minuten gespeeld">
365
                    <Icon icon="fa-clock-o" />
366
                  </span>
367
                </th>
368
              </tr>
369
            </thead>
370
            <tbody>
371
              {gameReports.map(function (game) {
372
                return (
373
                  <tr>
374
                    <td data-label="Team" className={`player-detail__column player-detail__column--string`}>
375
                      {game.team.replace(`Voetbal : `, ``)}
376
                    </td>
377
                    <td data-label="Type" className={`player-detail__column player-detail__column--string`}>
378
                      {game.competition}
379
                    </td>
380
                    <td data-label="Datum" className={`player-detail__column player-detail__column--string`}>
381
                      {moment(game.date).format(`DD/MM/YYYY`)}
382
                    </td>
383
                    <td data-label="Thuis/uit" className={`player-detail__column player-detail__column--number`}>
384
                      {game.home ? (
385
                        <span className={`player-detail__games__home`} title="Thuiswedstrijd">
386
                          <Icon icon="fa-home" alt="Thuiswedstrijd" />
387
                        </span>
388
                      ) : (
389
                        <span className={`player-detail__games__away`} title="Uitwedstrijd">
390
                          <Icon icon="fa-bus" alt="Uitwedstrijd" />
391
                        </span>
392
                      )}
393
                    </td>
394
                    <td data-label="Score" className={`player-detail__column player-detail__column--score`}>
395
                      {game.goalsHomeTeam}&nbsp;-&nbsp;{game.goalsAwayTeam}
396
                    </td>
397
                    <td data-label="Tegenstander" className={`player-detail__column player-detail__column--string`}>
398
                      {game.opponent}
399
                    </td>
400
                    <td data-label="Gele kaart(en)" className={`player-detail__column player-detail__column--number`}>
401
                      {game.yellowCards}
402
                    </td>
403
                    <td data-label="Rode kaart(en)" className={`player-detail__column player-detail__column--number`}>
404
                      {game.redCards}
405
                    </td>
406
                    <td data-label="Doelpunten" className={`player-detail__column player-detail__column--number`}>
407
                      {game.goals}
408
                    </td>
409
                    <td data-label="Speeltijd" className={`player-detail__column player-detail__column--number`}>
410
                      {game.minutesPlayed}'
411
                    </td>
412
                  </tr>
413
                )
414
              })}
415
            </tbody>
416
          </table>
417
        </Card>
418
      )
419
    }
420
  }
421
422
  renderPlayerBirthdate = (player) => (
423
    <div className={`player-detail__data-item player-detail__data-item--birthdate`}>
424
      <span className={`player-detail__data-item__label`}>Geboortedatum</span>
425
      <span className={`player-detail__data-item__data`}>{player.field_birth_date || `Onbekend`}</span>
426
    </div>
427
  )
428
  renderPlayerPosition = (player) => (
429
    <div className={`player-detail__data-item player-detail__data-item--position`}>
430
      <span className={`player-detail__date-item__data`}>
431
        {player.field_position && mapPositionCode(player.field_position)}
432
      </span>
433
      <span className={`player-detail__data-item__label`}>
434
        {player.relationships.node__team && (
435
          <Link to={player.relationships.node__team[0].path.alias}>{player.relationships.node__team[0].title}</Link>
436
        )}
437
      </span>
438
    </div>
439
  )
440
  renderPlayerJoinDate = (player) => {
441
    const currentlyPlaying = !player.field_date_leave
442
    return (
443
      <div className={`player-detail__data-item player-detail__data-item--joindate`}>
444
        <span className={`player-detail__data-item__label`}>
445
          {currentlyPlaying && `Speler bij KCVV sinds`}
446
          {!currentlyPlaying && `Speler tussen`}
447
        </span>
448
        <span className={`player-detail__data-item__data`}>
449
          {player.field_join_date || `Onbekend`}
450
          {!currentlyPlaying && (
451
            <Fragment>
452
              <span className={`text--regular`}> en </span> {player.field_date_leave}
453
            </Fragment>
454
          )}
455
        </span>
456
      </div>
457
    )
458
  }
459
  renderPlayerData = (player) => (
460
    <section className={`player-detail__data`}>
461
      {this.renderPlayerBirthdate(player)}
462
      {this.renderPlayerPosition(player)}
463
      {this.renderPlayerJoinDate(player)}
464
    </section>
465
  )
466
  renderPlayerBody = (player) => {
467
    const cleanBody =
468
      (player.body &&
469
        player.body.processed.replaceAll(`/sites/default/`, `${process.env.GATSBY_API_DOMAIN}/sites/default/`)) ||
470
      ``
471
472
    return (
473
      <section className={`player-detail__body`}>
474
        <div dangerouslySetInnerHTML={{ __html: cleanBody }} />
475
      </section>
476
    )
477
  }
478
  render() {
479
    const { player } = this.props
480
481
    const team = player.relationships.node__team || []
482
    const articles = player.relationships.node__article || []
483
484
    return (
485
      <Fragment>
486
        <article className={`player-detail`}>
487
          {this.renderPlayerHeader(player)}
488
          {this.renderPlayerStats(player)}
489
          <div className={`player-break`}></div>
490
          {this.renderPlayerData(player)}
491
          {this.renderPlayerBody(player)}
492
          {this.renderPlayerStatsFull(player)}
493
          {this.renderPlayerGamesFull(player)}
494
        </article>
495
496
        {(team || articles) && <RelatedNews items={team.concat(articles)} limit={6} />}
497
      </Fragment>
498
    )
499
  }
500
}
501
502
// Retrieve endpoint of the logo's api from the site metadata (gatsby-config.js).
503
const query = graphql`
504
  query {
505
    site {
506
      siteMetadata {
507
        kcvvPsdApi
508
      }
509
    }
510
  }
511
`
512
513
export default ({ player }) => (
514
  <StaticQuery
515
    query={query}
516
    render={(data) => (
517
      <Player
518
        // Data is the result of our query.
519
        config={data}
520
        player={player}
521
      />
522
    )}
523
  />
524
)
525