Passed
Push — feature/full-redesign ( 58f6d4...ff7e17 )
by Kevin Van
04:32
created

Player.tsx ➔ getData   F

Complexity

Conditions 15

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 4
rs 2.9998
c 0
b 0
f 0
cc 15

How to fix   Complexity   

Complexity

Complex classes like Player.tsx ➔ getData often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import axios from "axios"
2
import { graphql, Link } from "gatsby"
3
import { GatsbyImage, getSrc, StaticImage } from "gatsby-plugin-image"
4
import React, { useEffect, useState } from "react"
5
import { Card } from "../components/Card"
6
import Icon from "../components/Icon"
7
import { Seo } from "../components/Seo"
8
import { useSiteMetaData } from "../hooks/use-site-metadata"
9
import Layout from "../layouts"
10
import moment from "moment"
11
import "moment-timezone"
12
import "moment/locale/nl-be"
13
import { mapPositionCode } from "../scripts/helper"
14
import {
15
  PlayerQuery,
16
  PlayerStatsDataObject,
17
  PlayerStatsDataResponseObject,
18
  PlayerStatsReportsResponseObject,
19
} from "../Types/Player"
20
import "./Player.scss"
21
import iconCardRed from "../images/i_card_red.png"
22
import iconCardYellow from "../images/i_card_yellow.png"
23
import iconCleansheet from "../images/i_cleansheet.png"
24
import iconGoal from "../images/i_goal.png"
25
26
const Player = ({ data: { nodePlayer } }: PlayerQuery) => {
27
  const cleanBody =
28
    (nodePlayer?.body &&
29
      nodePlayer?.body?.processed?.replaceAll(`/sites/default/`, `${process.env.GATSBY_API_DOMAIN}/sites/default/`)) ||
30
    ``
31
  const picture = nodePlayer?.relationships?.field_image?.localFile?.childImageSharp?.gatsbyImageData && (
32
    <GatsbyImage
33
      image={nodePlayer?.relationships?.field_image?.localFile?.childImageSharp?.gatsbyImageData}
34
      alt={`${nodePlayer.field_firstname} ${nodePlayer.field_lastname}`}
35
    />
36
  )
37
38
  const [data, setData] = useState<PlayerStatsDataObject>()
39
  const [loading, setLoading] = useState<boolean>(true)
40
  const { kcvvPsdApi } = useSiteMetaData()
41
  const playerId = nodePlayer.field_vv_id
42
43
  useEffect(() => {
44
    async function getData() {
45
      const response = await axios.get(`${kcvvPsdApi}/stats/player/${playerId}`)
46
      setData(response.data)
47
      setLoading(false)
48
    }
49
    getData()
50
  }, [kcvvPsdApi, playerId])
51
52
  return (
53
    <Layout>
54
      <div className="player__details__top">
55
        <header className="page_header__wrapper player__header__wrapper">
56
          <div className="page_header page_header--max player__header">
57
            <div className="player__header__inner">
58
              <div className="player__header__inner_text">
59
                <h1 className={`player__detail__name`}>
60
                  <span className={`player__detail__name_first`}>{nodePlayer.field_firstname}</span>
61
                  <span className={`player__detail__name_last`}>{nodePlayer.field_lastname}</span>
62
                </h1>
63
                <p className={`player__detail__shirt_number`} aria-hidden="true">
64
                  {nodePlayer?.field_shirtnumber || ``}
65
                </p>
66
              </div>
67
              <div className="player__header__inner_image">
68
                {picture || (
69
                  <StaticImage
70
                    src={`../images/kcvv-player-bg.png`}
71
                    alt={`${nodePlayer.field_firstname} ${nodePlayer.field_lastname}`}
72
                    placeholder={`tracedSVG`}
73
                  />
74
                )}
75
              </div>
76
            </div>
77
          </div>
78
        </header>
79
        {!loading && renderStats(data?.playerStatistics || [], nodePlayer.field_position || ``)}
80
      </div>
81
      <main className="player__details__middle">
82
        {renderMeta(nodePlayer)}
83
        {cleanBody && <div dangerouslySetInnerHTML={{ __html: cleanBody }} className="player__details__intro" />}
84
      </main>
85
86
      <footer className="player__details__bottom">
87
        {renderPlayerStatsFull(data?.playerStatistics || [])}
88
        {renderPlayerGamesFull(data?.gameReports || [])}
89
      </footer>
90
      {/* <PlayerDetail player={nodePlayer} /> */}
91
    </Layout>
92
  )
93
}
94
95
export const Head = ({ data: { nodePlayer } }: PlayerQuery) => {
96
  const pathUrl = nodePlayer?.path?.alias || ``
97
  const heroImage = nodePlayer?.relationships?.field_image?.localFile?.childImageSharp?.gatsbyImageData
98
99
  const ogImage = heroImage && {
100
    src: getSrc(heroImage) || ``,
101
    width: heroImage.width,
102
    height: heroImage.height,
103
  }
104
  return (
105
    <Seo
106
      title={nodePlayer?.title || ``}
107
      path={pathUrl}
108
      image={ogImage}
109
      description={nodePlayer?.title + ` - (ex-)speler van KCVV Elewijt`}
110
    />
111
  )
112
}
113
114
export default Player
115
116
const renderStats = (playerStatistics: PlayerStatsDataResponseObject[], playerPosition = ``) => (
117
  <aside className="player__stats">
118
    <section className="player__stats__item">
119
      <div className="player__stats__item__number">
120
        {playerStatistics.reduce((a, b) => a + (b?.gamesPlayed || 0), 0) || `0`}
121
      </div>
122
      <div className="player__stats__item__label">Wedstrijden</div>
123
    </section>
124
    {(playerPosition === `k` || playerPosition === `d`) && (
125
      <section className="player__stats__item">
126
        <div className="player__stats__item__number">
127
          {playerStatistics.reduce((a, b) => a + (b?.cleanSheets || 0), 0) || `0`}
128
        </div>
129
        <div className="player__stats__item__label">Cleansheets</div>
130
      </section>
131
    )}
132
    <section className="player__stats__item">
133
      <div className="player__stats__item__number">
134
        {playerStatistics.reduce((a, b) => a + (b?.goals || 0), 0) || `0`}
135
      </div>
136
      <div className="player__stats__item__label">Doelpunten</div>
137
    </section>
138
    <section className="player__stats__item">
139
      <div className="player__stats__item__number">
140
        {playerStatistics.reduce((a, b) => a + (b?.yellowCards || 0), 0) || `0`}
141
      </div>
142
      <div className="player__stats__item__label">Gele kaarten</div>
143
    </section>
144
    <section className="player__stats__item">
145
      <div className="player__stats__item__number">
146
        {playerStatistics.reduce((a, b) => a + (b?.redCards || 0), 0) || `0`}
147
      </div>
148
      <div className="player__stats__item__label">Rode kaarten</div>
149
    </section>
150
  </aside>
151
)
152
153
const renderMeta = (nodePlayer: Queries.node__player) => {
154
  const currentlyPlaying = !nodePlayer.field_date_leave
155
  return (
156
    <div className="player__details__meta">
157
      <div className="player__details__meta__item player__details__meta__item--birthdate">
158
        <span className="player__details__meta__item__label">Geboortedatum</span>
159
        <span className="player__details__meta__item__data">{nodePlayer.field_birth_date || `Onbekend`}</span>
160
      </div>
161
      <div className="player__details__meta__item player__details__meta__item--position">
162
        <span className="player__details__meta__item__data">{mapPositionCode(nodePlayer.field_position || ``)}</span>
163
        <span className="player__details__meta__item__label">
164
          {nodePlayer?.relationships?.node__team && (
165
            <Link to={nodePlayer?.relationships?.node__team[0]?.path?.alias || ``}>
166
              {nodePlayer?.relationships?.node__team[0]?.title}
167
            </Link>
168
          )}
169
        </span>
170
      </div>
171
      <div className="player__details__meta__item player__details__meta__item--joindate">
172
        <span className="player__details__meta__item__label">
173
          {currentlyPlaying && `Speler bij KCVV sinds`}
174
          {!currentlyPlaying && `Speler tussen`}
175
        </span>
176
        <span className="player__details__meta__item__data">
177
          {nodePlayer.field_join_date || `Onbekend`}
178
          {!currentlyPlaying && (
179
            <>
180
              <span className={`text--regular`}> en </span> {nodePlayer.field_date_leave}
181
            </>
182
          )}
183
        </span>
184
      </div>
185
    </div>
186
  )
187
}
188
189
const renderPlayerStatsFull = (playerStatistics: PlayerStatsDataResponseObject[]) => {
190
  return (
191
    <Card title="Statistieken" className={`player__stats__stats`} hasTable={true}>
192
      <table className={`player__stats__stats__table`}>
193
        <thead>
194
          <tr>
195
            <th className={`table__column__string`}>Team</th>
196
            <th className={`table__column__number show-for-medium`}>
197
              <span title="Wedstrijden gespeeld">P</span>
198
            </th>
199
            <th className={`table__column__number`}>
200
              <span title="Wedstrijden gewonnen">W</span>
201
            </th>
202
            <th className={`table__column__number`}>
203
              <span title="Wedstrijden gelijkgespeeld">D</span>
204
            </th>
205
            <th className={`table__column__number`}>
206
              <span title="Wedstrijden verloren">L</span>
207
            </th>
208
            <th className={`table__column__number`}>
209
              <img src={iconCardYellow} title="Gele kaart" alt="Gele kaart" className="table__header__icon" />
210
            </th>
211
            <th className={`table__column__number`}>
212
              <img src={iconCardRed} title="Rode kaart" alt="Rode kaart" className="table__header__icon" />
213
            </th>
214
            <th className={`table__column__number`}>
215
              <img
216
                src={iconGoal}
217
                title="Doelpunt(en) gescoord"
218
                alt="Doelpunt(en) gescoord"
219
                className="table__header__icon"
220
              />
221
            </th>
222
            <th className={`table__column__number  show-for-medium`}>
223
              <img src={iconCleansheet} title="Cleansheets" alt="Cleansheets" className="table__header__icon" />
224
            </th>
225
            <th className={`table__column__number`}>
226
              <span title="Minuten gespeeld">
227
                <Icon icon="fa-clock-o" />
228
              </span>
229
            </th>
230
          </tr>
231
        </thead>
232
        <tbody>
233
          {playerStatistics.map(function (stats) {
234
            return (
235
              <tr>
236
                <td className={`table__column__string`}>{stats?.team?.replace(`Voetbal : `, ``)}</td>
237
                <td className={`table__column__number show-for-medium`}>{stats.gamesPlayed}</td>
238
                <td className={`table__column__number`}>{stats.gamesWon}</td>
239
                <td className={`table__column__number`}>{stats.gamesEqual}</td>
240
                <td className={`table__column__number`}>{stats.gamesLost}</td>
241
                <td className={`table__column__number`}>{stats.yellowCards}</td>
242
                <td className={`table__column__number`}>{stats.redCards}</td>
243
                <td className={`table__column__number`}>{stats.goals}</td>
244
                <td className={`table__column__number show-for-medium`}>{stats.cleanSheets}</td>
245
                <td className={`table__column__number`}>{stats.minutes}'</td>
246
              </tr>
247
            )
248
          })}
249
        </tbody>
250
      </table>
251
    </Card>
252
  )
253
}
254
255
const renderPlayerGamesFull = (gameReports: PlayerStatsReportsResponseObject[]) => {
256
  return (
257
    <Card className={`player__stats__games`} title="Wedstrijden" hasTable={true}>
258
      <table className={`player__stats__games__table responsive-card-table`}>
259
        <thead>
260
          <tr>
261
            <th className={`table__column__string`}>Team</th>
262
            <th className={`table__column__string`}>Type</th>
263
            <th className={`table__column__string`}>Datum</th>
264
            <th className={`table__column__number`}>
265
              <span title="Thuis/uit">H/A</span>
266
            </th>
267
            <th className={`table__column__string table__column__score`}>Score</th>
268
            <th className={`table__column__string`}>Tegenstander</th>
269
            <th className={`table__column__number`}>
270
              <img src={iconCardYellow} title="Gele kaart" alt="Gele kaart" className="table__header__icon" />
271
            </th>
272
            <th className={`table__column__number`}>
273
              <img src={iconCardRed} title="Rode kaart" alt="Rode kaart" className="table__header__icon" />
274
            </th>
275
            <th className={`table__column__number`}>
276
              <img src={iconGoal} title="Doelpunten gescoord" alt="Rode kaart" className="table__header__icon" />
277
            </th>
278
            <th className={`table__column__number`}>
279
              <span title="Minuten gespeeld">
280
                <Icon icon="fa-clock-o" />
281
              </span>
282
            </th>
283
          </tr>
284
        </thead>
285
        <tbody>
286
          {gameReports.map(function (game) {
287
            return (
288
              <tr>
289
                <td data-label="Team" className={`table__column__string`}>
290
                  {game.team?.replace(`Voetbal : `, ``)}
291
                </td>
292
                <td data-label="Type" className={`table__column__string`}>
293
                  {game.competition}
294
                </td>
295
                <td data-label="Datum" className={`table__column__string`}>
296
                  {moment(game.date).format(`DD/MM/YYYY`)}
297
                </td>
298
                <td data-label="Thuis/uit" className={`table__column__number`}>
299
                  {game.home ? (
300
                    <span className={`player__stats__games__home`} title="Thuiswedstrijd">
301
                      <Icon icon="fa-home" alt="Thuiswedstrijd" />
302
                    </span>
303
                  ) : (
304
                    <span className={`player__stats__games__away`} title="Uitwedstrijd">
305
                      <Icon icon="fa-bus" alt="Uitwedstrijd" />
306
                    </span>
307
                  )}
308
                </td>
309
                <td data-label="Score" className={`table__column__string table__column__score`}>
310
                  {game.goalsHomeTeam}&nbsp;-&nbsp;{game.goalsAwayTeam}
311
                </td>
312
                <td data-label="Tegenstander" className={`table__column__string`}>
313
                  {game.opponent}
314
                </td>
315
                <td data-label="Gele kaart(en)" className={`table__column__number`}>
316
                  {game.yellowCards}
317
                </td>
318
                <td data-label="Rode kaart(en)" className={`table__column__number`}>
319
                  {game.redCards}
320
                </td>
321
                <td data-label="Doelpunten" className={`table__column__number`}>
322
                  {game.goals}
323
                </td>
324
                <td data-label="Speeltijd" className={`table__column__number`}>
325
                  {game.minutesPlayed}'
326
                </td>
327
              </tr>
328
            )
329
          })}
330
        </tbody>
331
      </table>
332
    </Card>
333
  )
334
}
335
336
export const query = graphql`
337
  query PlayerQuery($slug: String!) {
338
    nodePlayer(path: { alias: { eq: $slug } }) {
339
      path {
340
        alias
341
      }
342
      body {
343
        processed
344
      }
345
      title
346
      field_join_date
347
      field_date_leave
348
      field_lastname
349
      field_position
350
      field_firstname
351
      field_birth_date
352
      field_shirtnumber
353
      field_vv_id
354
      relationships {
355
        node__article {
356
          title
357
          timestamp: created(formatString: "x")
358
          path {
359
            alias
360
          }
361
          relationships {
362
            field_media_article_image {
363
              ...ArticleImage
364
            }
365
          }
366
        }
367
        node__team {
368
          title
369
          relationships {
370
            field_media_article_image {
371
              ...ArticleImage
372
            }
373
          }
374
          path {
375
            alias
376
          }
377
        }
378
        field_image {
379
          localFile {
380
            ...KCVVFluid480
381
          }
382
        }
383
      }
384
    }
385
  }
386
`
387