You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
spa_instat_tv/src/features/MatchPage/store/hooks/usePlayersStats.tsx

248 lines
6.4 KiB

import type { Dispatch, SetStateAction } from 'react'
import {
useMemo,
useEffect,
useState,
useCallback,
} from 'react'
import { useQueryClient } from 'react-query'
import throttle from 'lodash/throttle'
import isEmpty from 'lodash/isEmpty'
import includes from 'lodash/includes'
import find from 'lodash/find'
import isUndefined from 'lodash/isUndefined'
import flatMapDepth from 'lodash/flatMapDepth'
import uniqBy from 'lodash/uniqBy'
import values from 'lodash/values'
import size from 'lodash/size'
import { querieKeys } from 'config'
import type {
DataItem,
MatchScore,
PlayerParam,
} from 'requests'
import {
MatchInfo,
PlayersStats,
Player,
getPlayersStats,
getMatchParticipants,
} from 'requests'
import { getLocalStorageItem } from 'helpers/getLocalStorage'
import { useObjectState, usePageParams } from 'hooks'
import { StatsType, Tabs as StatsTabs } from 'features/MatchSidePlaylists/components/TabStats/config'
import { getHalfTime } from 'features/MatchPage/helpers/getHalfTime'
import { TOUR_COMPLETED_STORAGE_KEY } from 'features/MatchTour'
import { Tabs } from 'features/MatchSidePlaylists/config'
import { DISPLAYED_PARAMS_COLUMNS } from 'features/MatchSidePlaylists/components/PlayersTable/config'
import { useFakeData } from './useFakeData'
const REQUEST_DELAY = 5000
const STATS_POLL_INTERVAL = 30000
type UsePlayersStatsArgs = {
matchProfile: MatchInfo,
playingProgress: number,
selectedStatsTable: StatsTabs,
selectedTab: Tabs,
setIsPlayersStatsFetching: Dispatch<SetStateAction<boolean>>,
statsType: StatsType,
}
type PlayersData = {
team1: Array<Player>,
team2: Array<Player>,
}
export const usePlayersStats = ({
matchProfile,
playingProgress,
selectedStatsTable,
selectedTab,
setIsPlayersStatsFetching,
statsType,
}: UsePlayersStatsArgs) => {
const [playersStats, setPlayersStats] = useObjectState<Record<string, PlayersStats>>({})
const [playersData, setPlayersData] = useState<PlayersData>({ team1: [], team2: [] })
const {
profileId: matchId,
sportName,
sportType,
} = usePageParams()
const fakeData = useFakeData(matchProfile)
const client = useQueryClient()
const matchScore = client.getQueryData<MatchScore>(querieKeys.matchScore)
const isCurrentStats = statsType === StatsType.CURRENT_STATS
const getParams = useCallback((stats: PlayersStats) => (
uniqBy(flatMapDepth(stats, values), 'id') as Array<PlayerParam>
), [])
const fetchPlayers = useMemo(() => throttle(async (second?: number) => {
const videoBounds = matchScore?.video_bounds || matchProfile?.video_bounds
if (
!matchProfile?.team1.id
|| !matchProfile?.team2.id
|| !videoBounds
) return null
try {
return getMatchParticipants({
matchId,
sportType,
...(!isUndefined(second) && getHalfTime(videoBounds, second)),
})
} catch (e) {
return Promise.reject(e)
}
}, REQUEST_DELAY), [
matchId,
matchProfile?.team1.id,
matchProfile?.team2.id,
matchProfile?.video_bounds,
matchScore?.video_bounds,
sportType,
])
const fetchPlayersStats = useMemo(() => (async (team: 'team1' | 'team2', second?: number) => {
const videoBounds = matchScore?.video_bounds || matchProfile?.video_bounds
if (!sportName || !matchProfile?.[team].id || !videoBounds) return null
try {
return getPlayersStats({
matchId,
sportName,
teamId: matchProfile[team].id,
...(!isUndefined(second) && getHalfTime(videoBounds, second)),
})
} catch (e) {
return Promise.reject(e)
}
}), [
matchScore?.video_bounds,
matchProfile,
sportName,
matchId,
])
const fetchData = useMemo(() => throttle(async (second?: number) => {
const isTeam1Selected = selectedStatsTable === StatsTabs.TEAM1
if (
selectedTab !== Tabs.STATS
|| !includes([StatsTabs.TEAM1, StatsTabs.TEAM2], selectedStatsTable)
|| !matchProfile?.team1.id
|| !matchProfile?.team2.id
|| (!matchProfile?.live && !isCurrentStats && !isEmpty(playersStats[isTeam1Selected
? matchProfile.team1.id
: matchProfile.team2.id]))
) return
const [res1, res2] = await Promise.all([
fetchPlayers(second),
isTeam1Selected
? fetchPlayersStats('team1', second)
: fetchPlayersStats('team2', second),
]) as [Array<DataItem> | null, PlayersStats | null]
const team1Players = find(res1, { team_id: matchProfile?.team1.id })?.players || []
const team2Players = find(res1, { team_id: matchProfile?.team2.id })?.players || []
const needUseFakeData = getLocalStorageItem(TOUR_COMPLETED_STORAGE_KEY) !== 'true'
&& (
isEmpty(team1Players)
|| isEmpty(res2)
|| size(getParams(res2)) <= DISPLAYED_PARAMS_COLUMNS
)
setPlayersData({
team1: needUseFakeData ? fakeData.playersData[0].players : team1Players,
team2: needUseFakeData ? fakeData.playersData[1].players : team2Players,
})
setPlayersStats({
...(isTeam1Selected && res2 && {
[matchProfile.team1.id]: needUseFakeData
? fakeData.playersStats as unknown as PlayersStats
: res2,
}),
...(!isTeam1Selected && res2 && {
[matchProfile.team2.id]: needUseFakeData
? fakeData.playersStats as unknown as PlayersStats
: res2,
}),
})
setIsPlayersStatsFetching(false)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, REQUEST_DELAY), [
fetchPlayers,
fetchPlayersStats,
setPlayersStats,
matchProfile?.team1.id,
matchProfile?.team2.id,
matchProfile?.live,
setIsPlayersStatsFetching,
getParams,
fakeData,
selectedTab,
selectedStatsTable,
isCurrentStats,
])
const beforeCloseTourCallback = () => {
isCurrentStats ? fetchData(playingProgress) : fetchData()
}
useEffect(() => {
let interval: NodeJS.Timeout
if (!isCurrentStats) {
fetchData()
}
if (matchProfile?.live && !isCurrentStats) {
interval = setInterval(() => {
fetchData()
}, STATS_POLL_INTERVAL)
}
return () => clearInterval(interval)
}, [
fetchData,
isCurrentStats,
matchProfile?.live,
])
useEffect(() => {
if (isCurrentStats) {
fetchData(playingProgress)
}
}, [
fetchData,
playingProgress,
isCurrentStats,
matchProfile?.live,
])
return {
beforeCloseTourCallback,
getParams,
playersData,
playersStats,
}
}