Passed
Pull Request — develop (#758)
by Kevin Van
04:17
created

src/pages/game.tsx   B

Complexity

Total Complexity 45
Complexity/F 45

Size

Lines of Code 317
Function Count 1

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 45
eloc 279
mnd 44
bc 44
fnc 1
dl 0
loc 317
rs 8.8
bpm 44
cpm 45
noi 0
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A game.tsx ➔ getData 0 6 1

How to fix   Complexity   

Complexity

Complex classes like src/pages/game.tsx 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 ReactFitText from "@kennethormandy/react-fittext"
3
import { useState, useEffect, Fragment } from "react"
4
import { useSiteMetaData } from "../hooks/use-site-metadata"
5
import iconBench from "../images/i_bench_2.png"
6
import iconCardRed from "../images/i_card_red.png"
7
import iconCardYellow from "../images/i_card_yellow.png"
8
import iconCardYellowRed from "../images/i_card_yellow_red.png"
9
import iconGoal from "../images/i_goal.png"
10
import iconStart from "../images/i_start.png"
11
import iconSubIn from "../images/i_sub_in.png"
12
import iconSubOut from "../images/i_sub_out.png"
13
import {
14
  MatchDetails,
15
  MatchDetailsEventItem,
16
  MatchDetailsLineupItem,
17
  MatchDetailsSubstituteItem,
18
  MatchDetailsSubstitutes,
19
} from "../Types/Match"
20
import { GamePageProps } from "../Types/PageProps"
21
import moment from "moment"
22
import "moment-timezone"
23
import "moment/locale/nl-be"
24
import React from "react"
25
import Layout from "../layouts"
26
import { Spinner } from "../components/Spinner"
27
import { Seo } from "../components/Seo"
28
import "./game.scss"
29
import { mapPsdStatus } from "../scripts/helper"
30
import LazyLoad from "react-lazyload"
31
import Icon from "../components/Icon"
32
import { MiniRanking } from "../components/MiniRanking"
33
const GamePage = ({ matchId }: GamePageProps) => {
34
  const { kcvvPsdApi } = useSiteMetaData()
35
  const [data, setData] = useState<MatchDetails>()
36
37
  useEffect(() => {
38
    async function getData() {
39
      const response = await axios.get(`${kcvvPsdApi}/match/${matchId}`)
40
      console.log(response)
41
      console.log(`Getting data`)
42
      console.log(`${kcvvPsdApi}/match/${matchId}`)
43
      setData(response.data)
44
    }
45
    getData()
46
  }, [kcvvPsdApi, matchId])
47
48
  moment.tz.setDefault(`Europe/Brussels`)
49
  moment.locale(`nl-be`)
50
  moment.localeData(`nl-be`)
51
52
  if (matchId === null) {
53
    return (
54
      <Layout>
55
        <main className="page__wrapper">Geen match beschikbaar...</main>
56
      </Layout>
57
    )
58
  }
59
60
  console.log(data)
61
62
  if (data) {
63
    const { general, substitutes, lineup, events = [] } = data
64
    const { home: homeLineup = [], away: awayLineup = [] } = lineup
65
    const { home: homeSubs = [], away: awaySubs = [] } = substitutes
66
67
    const matchTime = moment(general.date)
68
    const homeTeamId = general.homeClub?.id
69
70
    const ogImage = {
71
      src: general?.homeClub?.logo,
72
      width: 180,
73
      height: 180,
74
    }
75
76
    return (
77
      <Layout>
78
        <Seo
79
          title={`Matchverslag ${general.homeClub?.abbreviation || general?.homeClub?.name} - ${
80
            general.awayClub?.abbreviation || general?.awayClub?.name
81
          }`}
82
          description={`Matchverslag ${general.homeClub?.abbreviation || general?.homeClub?.name} - ${
83
            general.awayClub?.abbreviation || general?.awayClub?.name
84
          }`}
85
          path={`/game/${general?.id}`}
86
          image={ogImage}
87
        />
88
        <header className="game__header__wrapper full-width">
89
          <div className="game__header__inner">
90
            <div className="game__teams">
91
              <div className={`game__teams-inner`}>
92
                <LazyLoad debounce={false}>
93
                  <img src={general.homeClub?.logo} alt={general.homeClub?.name} title={general.homeClub?.name} />
94
                </LazyLoad>
95
              </div>
96
              {renderScore(general.goalsHomeTeam, general.goalsAwayTeam)}
97
              <div className={`game__teams-inner`}>
98
                <LazyLoad debounce={false}>
99
                  <img src={general.awayClub?.logo} alt={general.awayClub?.name} title={general.awayClub?.name} />
100
                </LazyLoad>
101
              </div>
102
            </div>
103
            <h1>
104
              <ReactFitText compressor={2.5}>{`${general.homeClub?.abbreviation || general.homeClub?.name} - ${
105
                general.awayClub?.abbreviation || general.awayClub?.name
106
              }`}</ReactFitText>
107
            </h1>
108
            <h4>{general.competitionType}</h4>
109
            <time dateTime={matchTime.format(`YYYY-MM-DD - H:mm`)}>{matchTime.format(`dddd DD MMMM YYYY - H:mm`)}</time>
110
            <br />
111
112
            {general.status !== 0 && (
113
              <span className={`game__status game__status--${general.status}`}>{mapPsdStatus(general.status)}</span>
114
            )}
115
116
            <br />
117
          </div>
118
        </header>
119
120
        <main className="page__wrapper">
121
          {(homeLineup.length !== 0 || awayLineup.length !== 0) && (
122
            <div className={`lineup__wrapper`}>
123
              <div className={`lineup__wrapper--home`}>
124
                <h3>{general.homeClub?.abbreviation || general.homeClub?.name}</h3>
125
                {homeLineup && renderLineup(homeLineup, homeSubs)}
126
              </div>
127
              <div className={`lineup__wrapper--away`}>
128
                <h3>{general.awayClub?.abbreviation || general.awayClub?.name}</h3>
129
                {awayLineup && renderLineup(awayLineup, awaySubs)}
130
              </div>
131
            </div>
132
          )}
133
        </main>
134
135
        <section className="page__wrapper">
136
          {events.length !== 0 && (
137
            <div className={`event__wrapper`}>
138
              <h3>Gebeurtenissen</h3>
139
              {events && renderEvents(events, homeTeamId)}
140
            </div>
141
          )}
142
143
          {general.competitionType === `Competitie` && (
144
            <MiniRanking
145
              teamId={general.homeTeamId || general.awayTeamId || 0}
146
              homeTeam={general.homeClub?.name}
147
              awayTeam={general.awayClub?.name}
148
            />
149
          )}
150
        </section>
151
      </Layout>
152
    )
153
  } else {
154
    return (
155
      <Layout>
156
        <Spinner />
157
      </Layout>
158
    )
159
  }
160
}
161
162
const renderScore = (resultHome?: number, resultAway?: number) => {
163
  return resultHome !== null && resultAway !== null ? (
164
    <div className={`game__details__vs game__details__vs--score`}>
165
      {renderScoreWithWinnerIndicator(resultHome || 0, resultAway || 0, `home`)}
166
      <span className={`match-details__divider`}>&nbsp;-&nbsp;</span>
167
      {renderScoreWithWinnerIndicator(resultAway || 0, resultHome || 0, `away`)}
168
    </div>
169
  ) : (
170
    <div className={`game__details__vs`}>VS</div>
171
  )
172
}
173
174
const renderScoreWithWinnerIndicator = (result1: number, result2: number, extraClass?: string) => {
175
  return result1 > result2 ? (
176
    <span className={`game__details__winner game__details__winner--${extraClass}`}>{result1}</span>
177
  ) : (
178
    <span className={`game__details__loser`}>{result1}</span>
179
  )
180
}
181
182
const renderLineup = (lineup: MatchDetailsLineupItem[], substitutes: MatchDetailsSubstituteItem[]) => {
183
  return (
184
    <Fragment>
185
      {renderLineupHeader()}
186
      {lineup.map((element, i) => renderLineupLine(i, element))}
187
      <hr />
188
      {substitutes.map((element, i) => renderSubLine(i, element))}
189
    </Fragment>
190
  )
191
}
192
193
const renderLineupHeader = () => {
194
  return (
195
    <div className={`lineup__header`}>
196
      <span className={`lineup__header__item lineup__item--status`}></span>
197
      <span className={`lineup__header__item lineup__item--number`}>#</span>
198
      <span className={`lineup__header__item lineup__item--name`}>Name</span>
199
      <span className={`lineup__header__item lineup__item--time`}>
200
        <Icon icon="fa-clock-o" />
201
      </span>
202
    </div>
203
  )
204
}
205
206
const renderLineupLine = (i: React.Key, element: MatchDetailsLineupItem) => {
207
  return (
208
    <div className={`lineup__row lineup__row--lineup`} key={i}>
209
      <span
210
        className={`lineup__row__item lineup__item--status`}
211
        style={{
212
          backgroundImage: `url(${element.changed ? iconSubOut : iconStart})`,
213
        }}
214
        title={`${element.changed ? `Basisspeler gewisseld` : `Basisspeler`}`}
215
      ></span>
216
      <span className={`lineup__row__item lineup__item--number`}>{element.number}</span>
217
      <span className={`lineup__row__item lineup__item--name`}>
218
        {element.playerName} {element.captain && `(C)`}
219
      </span>
220
      <span className={`lineup__row__item lineup__item--time`}>{element.minutesPlayed}'</span>
221
    </div>
222
  )
223
}
224
225
const renderSubLine = (i: React.Key, element: MatchDetailsSubstituteItem) => {
226
  return (
227
    <div className={`lineup__row lineup__row--substitute`} key={i}>
228
      <span
229
        className={`lineup__row__item lineup__item--status`}
230
        style={{
231
          backgroundImage: `url(${element.changed ? iconSubIn : iconBench})`,
232
        }}
233
        title={`${element.changed ? `Wisselspeler ingevallen` : `Wisselspeler`}`}
234
      ></span>
235
      <span className={`lineup__row__item lineup__item--number`}>{element.number}</span>
236
      <span className={`lineup__row__item lineup__item--name`}>{element.playerName}</span>
237
      <span className={`lineup__row__item lineup__item--time`}>{element.minutesPlayed}'</span>
238
    </div>
239
  )
240
}
241
242
const renderEvents = (events: MatchDetailsEventItem[], homeTeamId: number) => {
243
  return <Fragment>{events.map((element, i) => renderEventLine(i, element, homeTeamId))}</Fragment>
244
}
245
246
const renderEventLine = (i: React.Key, element: MatchDetailsEventItem, homeTeamId: number) => {
247
  const homeTeam = element.clubId == homeTeamId
248
  let actionIcon = null
249
  let actionMessage = ``
250
  let actionText = ``
251
252
  switch (element.action) {
253
    case `geel`:
254
      actionIcon = iconCardYellow
255
      actionText = `Gele kaart voor`
256
      actionMessage = `Gele kaart`
257
      break
258
    case `rood`:
259
      actionIcon = iconCardRed
260
      actionText = `Rode kaart voor`
261
      actionMessage = `Rode kaart`
262
      break
263
    case `tweedegeel`:
264
      actionIcon = iconCardYellowRed
265
      actionText = `Tweede gele kaart voor`
266
      actionMessage = `Tweede gele kaart`
267
      break
268
    case `doelpunt`:
269
      actionIcon = iconGoal
270
      actionText = `${element?.goalsHome} - ${element?.goalsAway} — Doelpunt gescoord door`
271
      actionMessage = `Doelpunt`
272
      break
273
    case `minuteOut`:
274
      actionIcon = iconSubOut
275
      actionText = `Speler uit:`
276
      actionMessage = `Wissel`
277
      break
278
    case `minuteIn`:
279
      actionIcon = iconSubIn
280
      actionText = `Speler in:`
281
      actionMessage = `Wissel`
282
      break
283
  }
284
285
  return (
286
    <div className={`event__row ${homeTeam ? `event__row--home` : `event__row--away`}`} key={i}>
287
      {homeTeam && (
288
        <span className={`event__row__item event__row__item--home lineup__item--name`}>
289
          {actionText} {element.playerName}
290
        </span>
291
      )}
292
      {homeTeam && (
293
        <span
294
          className={`event__row__item event__row__item--home lineup__item--action center`}
295
          style={{ backgroundImage: `url(${actionIcon})` }}
296
          title={actionMessage}
297
        ></span>
298
      )}
299
      <span className={`event__row__item lineup__item--time center`}>{element.minute}'</span>
300
      {homeTeam || (
301
        <span
302
          className={`event__row__item event__row__item--away lineup__item--action center`}
303
          style={{ backgroundImage: `url(${actionIcon})` }}
304
          title={actionMessage}
305
        ></span>
306
      )}
307
      {homeTeam || (
308
        <span className={`event__row__item event__row__item--away lineup__item--name`}>
309
          {actionText} {element.playerName}
310
        </span>
311
      )}
312
    </div>
313
  )
314
}
315
316
export default GamePage
317