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.
493 lines
13 KiB
493 lines
13 KiB
import {
|
|
useEffect,
|
|
useState,
|
|
useMemo,
|
|
} from 'react'
|
|
import { useHistory } from 'react-router'
|
|
|
|
import includes from 'lodash/includes'
|
|
import filter from 'lodash/filter'
|
|
import isEmpty from 'lodash/isEmpty'
|
|
|
|
import { PAGES } from 'config'
|
|
|
|
import { useAuthStore } from 'features/AuthStore'
|
|
import { Tabs } from 'features/MatchSidePlaylists/config'
|
|
import { initialCircleAnimation } from 'features/CircleAnimationBar'
|
|
import type { TCircleAnimation } from 'features/CircleAnimationBar'
|
|
import { StatsType } from 'features/MatchSidePlaylists/components/TabStats/config'
|
|
import { PlaylistTypes } from 'features/MatchPage/types'
|
|
import { FULL_GAME_KEY } from 'features/MatchPage/helpers/buildPlaylists'
|
|
|
|
import type { MatchInfo } from 'requests/getMatchInfo'
|
|
import { getMatchInfo } from 'requests/getMatchInfo'
|
|
import { getViewMatchDuration } from 'requests/getViewMatchDuration'
|
|
import { getLandingStatus } from 'requests/getLandingStatus'
|
|
|
|
import { usePageParams, useToggle } from 'hooks'
|
|
|
|
import { redirectToUrl } from 'helpers/redirectToUrl'
|
|
import { parseDate } from 'helpers/parseDate'
|
|
|
|
import { useAds } from 'components/Ads/hooks'
|
|
|
|
import { useTournamentData } from './useTournamentData'
|
|
import { useMatchData } from './useMatchData'
|
|
import { useFiltersPopup } from './useFitersPopup'
|
|
import { useTabEvents } from './useTabEvents'
|
|
import { useTeamsStats } from './useTeamsStats'
|
|
import { useStatsTab } from './useStatsTab'
|
|
import { usePlayersStats } from './usePlayersStats'
|
|
import { useLexicsStore } from '../../../LexicsStore'
|
|
|
|
type PlayingData = {
|
|
player: {
|
|
id: number | null,
|
|
paramId: number | null,
|
|
},
|
|
team: {
|
|
id: number | null,
|
|
paramId: number | null,
|
|
},
|
|
}
|
|
|
|
type EpisodeInfo = {
|
|
episodesCount?: number,
|
|
paramName?: string,
|
|
playerOrTeamName?: string,
|
|
}
|
|
|
|
const initPlayingData: PlayingData = {
|
|
player: {
|
|
id: null,
|
|
paramId: null,
|
|
},
|
|
team: {
|
|
id: null,
|
|
paramId: null,
|
|
},
|
|
}
|
|
|
|
const ACCESS_TIME = 60
|
|
|
|
export const useMatchPage = () => {
|
|
const [matchProfile, setMatchProfile] = useState<MatchInfo>(null)
|
|
const [watchAllEpisodesTimer, setWatchAllEpisodesTimer] = useState(false)
|
|
const [isFullscreen, setIsFullScreen] = useState(false)
|
|
const [access, setAccess] = useState(true)
|
|
const [playingProgress, setPlayingProgress] = useState(0)
|
|
const [playingData, setPlayingData] = useState<PlayingData>(initPlayingData)
|
|
const [playingOrder, setPlaingOrder] = useState(0)
|
|
const [isPlayFilterEpisodes, setIsPlayingFiltersEpisodes] = useState(false)
|
|
const [selectedTab, setSelectedTab] = useState<Tabs>(Tabs.WATCH)
|
|
const [circleAnimation, setCircleAnimation] = useState<TCircleAnimation>(initialCircleAnimation)
|
|
const [episodeInfo, setEpisodeInfo] = useState<EpisodeInfo>({
|
|
episodesCount: 0,
|
|
paramName: '',
|
|
playerOrTeamName: '',
|
|
})
|
|
const { suffix } = useLexicsStore()
|
|
|
|
const { profileId: matchId, sportType } = usePageParams()
|
|
|
|
const { ads } = useAds({
|
|
matchId,
|
|
sportType,
|
|
tournamentId: matchProfile?.tournament?.id,
|
|
})
|
|
|
|
useEffect(() => {
|
|
sessionStorage.removeItem('isFromLanding')
|
|
}, [])
|
|
|
|
const {
|
|
isFromLanding,
|
|
landingUrlFrom,
|
|
setIsFromLanding,
|
|
setLandingUrlFrom,
|
|
user,
|
|
userInfo,
|
|
} = useAuthStore()
|
|
const history = useHistory()
|
|
|
|
const {
|
|
close: hideProfileCard,
|
|
isOpen: profileCardShown,
|
|
open: showProfileCard,
|
|
} = useToggle(true)
|
|
|
|
const {
|
|
events,
|
|
handlePlaylistClick,
|
|
matchPlaylists,
|
|
selectedPlaylist,
|
|
setFullMatchPlaylistDuration,
|
|
} = useMatchData({ matchProfile, selectedTab })
|
|
|
|
const profile = matchProfile
|
|
|
|
const isPlayingEpisode = selectedPlaylist.id !== FULL_GAME_KEY
|
|
|
|
const isStatsPlaylist = selectedPlaylist.tab === Tabs.STATS
|
|
|
|
const {
|
|
activeEvents,
|
|
activeFirstTeamPlayers,
|
|
activeSecondTeamPlayers,
|
|
allActionsToggle,
|
|
allPlayersToggle,
|
|
applyFilters,
|
|
close: closePopup,
|
|
countOfFilters,
|
|
filters,
|
|
isAllActionsChecked,
|
|
isEmptyFilters,
|
|
isFirstTeamPlayersChecked,
|
|
isOpen: isOpenFiltersPopup,
|
|
isSecondTeamPlayersChecked,
|
|
toggle: togglePopup,
|
|
toggleActiveEvents,
|
|
toggleActivePlayers,
|
|
uniqEvents,
|
|
} = useFiltersPopup({
|
|
events,
|
|
matchPlaylists,
|
|
})
|
|
|
|
const getMatchViewDuration = (id: number) => (getViewMatchDuration({
|
|
matchId,
|
|
sportType,
|
|
userId: id,
|
|
}).then(({
|
|
duration,
|
|
error,
|
|
}) => {
|
|
if (error || (duration && Number(duration) > ACCESS_TIME)) {
|
|
setAccess(false)
|
|
}
|
|
}))
|
|
|
|
useEffect(() => {
|
|
if (user || isFromLanding || history.length > 1) return
|
|
setLandingUrlFrom(window.location.pathname)
|
|
getLandingStatus({ matchId, sportType })
|
|
.then((data) => {
|
|
sessionStorage.setItem(
|
|
'landingData',
|
|
JSON.stringify({ ...data, defaultLanding: false }),
|
|
)
|
|
setIsFromLanding(false)
|
|
if (data.landing_id) redirectToUrl(`${PAGES.landing}/${data.landing_id}`)
|
|
})
|
|
.catch(() => {
|
|
getMatchInfo(sportType, matchId).then((data) => {
|
|
sessionStorage.setItem('landingData', JSON.stringify({
|
|
defaultLanding: true,
|
|
sportType,
|
|
tournamentId: data?.tournament.id,
|
|
}))
|
|
redirectToUrl(`
|
|
${PAGES.landing}/default
|
|
?season=${data?.season.name}
|
|
&tournament=${data?.tournament[`name_${suffix}`]}`)
|
|
})
|
|
})
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [
|
|
setLandingUrlFrom,
|
|
isFromLanding,
|
|
landingUrlFrom,
|
|
matchId,
|
|
setIsFromLanding,
|
|
sportType,
|
|
user,
|
|
])
|
|
|
|
useEffect(() => {
|
|
getMatchInfo(sportType, matchId).then(
|
|
(info) => (info?.sport
|
|
// проверяем именно какой-то ключ в объекте,
|
|
// потому что, когда матча не существует, приходит - []
|
|
? setMatchProfile(info) : window.location.replace(PAGES.home)),
|
|
)
|
|
}, [sportType, matchId])
|
|
|
|
useEffect(() => {
|
|
let getIntervalMatch: ReturnType<typeof setInterval>
|
|
if (matchProfile?.live && !matchProfile.youtube_link) {
|
|
getIntervalMatch = setInterval(
|
|
() => getMatchInfo(sportType, matchId).then(setMatchProfile),
|
|
1000 * 60 * 3,
|
|
)
|
|
}
|
|
return () => clearInterval(getIntervalMatch)
|
|
}, [
|
|
matchProfile,
|
|
sportType,
|
|
matchId,
|
|
])
|
|
|
|
useEffect(() => {
|
|
if (user || !userInfo?.email) return
|
|
|
|
const counter = setInterval(
|
|
() => getMatchViewDuration(Number(userInfo?.email)),
|
|
1000 * 30,
|
|
)
|
|
// eslint-disable-next-line
|
|
return () => clearInterval(counter)
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [
|
|
sportType,
|
|
matchId,
|
|
userInfo,
|
|
])
|
|
|
|
const disablePlayingStatsEpisodes = () => {
|
|
setStatsIsPlayinFiltersEpisodes(false)
|
|
setStatsWatchAllEpisodesTimer(false)
|
|
setStatsCircleAnimation(initialCircleAnimation)
|
|
setStatsPlaingOrder(0)
|
|
}
|
|
|
|
const disablePlayingPlaysEpisodes = () => {
|
|
setIsPlayingFiltersEpisodes(false)
|
|
setWatchAllEpisodesTimer(false)
|
|
setCircleAnimation(initialCircleAnimation)
|
|
setPlaingOrder(0)
|
|
}
|
|
|
|
const disablePlayingEpisodes = () => {
|
|
isStatsPlaylist ? disablePlayingStatsEpisodes() : disablePlayingPlaysEpisodes()
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (selectedPlaylist.type !== PlaylistTypes.EVENT) {
|
|
disablePlayingStatsEpisodes()
|
|
disablePlayingPlaysEpisodes()
|
|
} else {
|
|
!isStatsPlaylist ? disablePlayingStatsEpisodes() : disablePlayingPlaysEpisodes()
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [selectedPlaylist])
|
|
|
|
const {
|
|
circleAnimation: statsCircleAnimation,
|
|
filteredEvents: statsFilteredEvents,
|
|
isExpanded,
|
|
isPlayersStatsFetching,
|
|
isPlayFilterEpisodes: isStatsPlayFilterEpisodes,
|
|
isTeamsStatsFetching,
|
|
playEpisodes: playStatsEpisodes,
|
|
playingOrder: statsPlaingOrder,
|
|
playNextEpisode: playStatsNextEpisode,
|
|
reduceTable,
|
|
selectedStatsTable,
|
|
setCircleAnimation: setStatsCircleAnimation,
|
|
setIsPlayersStatsFetching,
|
|
setIsPlayingFiltersEpisodes: setStatsIsPlayinFiltersEpisodes,
|
|
setIsTeamsStatsFetching,
|
|
setPlaingOrder: setStatsPlaingOrder,
|
|
setSelectedStatsTable,
|
|
setStatsType,
|
|
setWatchAllEpisodesTimer: setStatsWatchAllEpisodesTimer,
|
|
statsType,
|
|
toggleIsExpanded,
|
|
toggleStatsType,
|
|
watchAllEpisodesTimer: statsWatchAllEpisodesTimer,
|
|
} = useStatsTab({
|
|
disablePlayingEpisodes,
|
|
handlePlaylistClick,
|
|
matchProfile,
|
|
selectedPlaylist,
|
|
})
|
|
|
|
const {
|
|
beforeCloseTourCallback: beforeCloseTourCallbackTeams,
|
|
getFirstClickableParam,
|
|
isClickable,
|
|
teamsStats,
|
|
} = useTeamsStats({
|
|
matchProfile,
|
|
playingProgress,
|
|
selectedStatsTable,
|
|
selectedTab,
|
|
setIsTeamsStatsFetching,
|
|
statsType,
|
|
})
|
|
|
|
const {
|
|
beforeCloseTourCallback: beforeCloseTourCallbackPlayers,
|
|
getParams,
|
|
playersData,
|
|
playersStats,
|
|
} = usePlayersStats({
|
|
matchProfile,
|
|
playingProgress,
|
|
selectedStatsTable,
|
|
selectedTab,
|
|
setIsPlayersStatsFetching,
|
|
statsType,
|
|
})
|
|
|
|
const beforeCloseTourCallback = () => {
|
|
beforeCloseTourCallbackPlayers()
|
|
beforeCloseTourCallbackTeams()
|
|
|
|
setStatsType(profile?.live ? StatsType.CURRENT_STATS : StatsType.FINAL_STATS)
|
|
isExpanded && toggleIsExpanded()
|
|
}
|
|
|
|
const isStarted = useMemo(() => (
|
|
profile?.date
|
|
? parseDate(profile.date) < new Date()
|
|
: true
|
|
), [profile?.date])
|
|
|
|
const { tournamentData } = useTournamentData(matchProfile)
|
|
|
|
const filteredEvents = useMemo(() => {
|
|
switch (true) {
|
|
case (!isEmpty(filters.events) && !isEmpty(filters.players)):
|
|
return filter(events, (event) => includes(filters.players, event.p)
|
|
&& includes(filters.events, event.l))
|
|
case (!isEmpty(filters.players)):
|
|
return filter(events, (event) => includes(filters.players, event.p))
|
|
case (!isEmpty(filters.events)):
|
|
return filter(events, (event) => includes(filters.events, event.l))
|
|
default: return events
|
|
}
|
|
}, [events, filters])
|
|
|
|
const {
|
|
activeStatus,
|
|
episodesToPlay,
|
|
isLiveMatch,
|
|
likeImage,
|
|
likeToggle,
|
|
reversedGroupEvents,
|
|
setReversed,
|
|
setUnreversed,
|
|
} = useTabEvents({ events: filteredEvents, profile })
|
|
|
|
const playNextEpisode = (order?: number) => {
|
|
const isLastEpisode = playingOrder === episodesToPlay.length
|
|
|
|
const currentOrder = order === 0 ? order : playingOrder
|
|
|
|
if (isLastEpisode || !episodesToPlay[currentOrder]) {
|
|
setIsPlayingFiltersEpisodes(false)
|
|
setPlaingOrder(0)
|
|
|
|
return
|
|
}
|
|
|
|
handlePlaylistClick({
|
|
playlist: episodesToPlay[currentOrder],
|
|
tab: Tabs.EVENTS,
|
|
})
|
|
|
|
setPlaingOrder(currentOrder + 1)
|
|
}
|
|
|
|
const playEpisodes = () => {
|
|
setPlayingData(initPlayingData)
|
|
setStatsWatchAllEpisodesTimer(true)
|
|
setStatsIsPlayinFiltersEpisodes(false)
|
|
setStatsCircleAnimation(initialCircleAnimation)
|
|
|
|
if (!watchAllEpisodesTimer) {
|
|
setWatchAllEpisodesTimer(true)
|
|
}
|
|
|
|
setIsPlayingFiltersEpisodes(true)
|
|
playNextEpisode(0)
|
|
}
|
|
|
|
return {
|
|
access,
|
|
activeEvents,
|
|
activeFirstTeamPlayers,
|
|
activeSecondTeamPlayers,
|
|
activeStatus,
|
|
ads,
|
|
allActionsToggle,
|
|
allPlayersToggle,
|
|
applyFilters,
|
|
beforeCloseTourCallback,
|
|
circleAnimation: isStatsPlaylist ? statsCircleAnimation : circleAnimation,
|
|
closePopup,
|
|
countOfFilters,
|
|
disablePlayingEpisodes,
|
|
episodeInfo,
|
|
events,
|
|
filteredEvents: isStatsPlaylist ? statsFilteredEvents : filteredEvents,
|
|
getFirstClickableParam,
|
|
getParams,
|
|
handlePlaylistClick,
|
|
hideProfileCard,
|
|
isAllActionsChecked,
|
|
isClickable,
|
|
isEmptyFilters,
|
|
isExpanded,
|
|
isFirstTeamPlayersChecked,
|
|
isFullscreen,
|
|
isLiveMatch,
|
|
isOpenFiltersPopup,
|
|
isPlayFilterEpisodes: isStatsPlaylist ? isStatsPlayFilterEpisodes : isPlayFilterEpisodes,
|
|
isPlayersStatsFetching,
|
|
isPlayingEpisode,
|
|
isSecondTeamPlayersChecked,
|
|
isStarted,
|
|
isTeamsStatsFetching,
|
|
likeImage,
|
|
likeToggle,
|
|
matchPlaylists,
|
|
playEpisodes,
|
|
playNextEpisode: isStatsPlaylist ? playStatsNextEpisode : playNextEpisode,
|
|
playStatsEpisodes,
|
|
playersData,
|
|
playersStats,
|
|
playingData,
|
|
playingOrder: isStatsPlaylist ? statsPlaingOrder : playingOrder,
|
|
playingProgress,
|
|
profile,
|
|
profileCardShown,
|
|
reduceTable,
|
|
reversedGroupEvents,
|
|
selectedPlaylist,
|
|
selectedStatsTable,
|
|
selectedTab,
|
|
setCircleAnimation: isStatsPlaylist ? setStatsCircleAnimation : setCircleAnimation,
|
|
setEpisodeInfo,
|
|
setFullMatchPlaylistDuration,
|
|
setIsFullScreen,
|
|
setIsPlayingFiltersEpisodes: isStatsPlaylist
|
|
? setStatsIsPlayinFiltersEpisodes
|
|
: setIsPlayersStatsFetching,
|
|
setMatchProfile,
|
|
setPlaingOrder: isStatsPlaylist ? setStatsPlaingOrder : setPlaingOrder,
|
|
setPlayingData,
|
|
setPlayingProgress,
|
|
setReversed,
|
|
setSelectedStatsTable,
|
|
setSelectedTab,
|
|
setStatsType,
|
|
setUnreversed,
|
|
setWatchAllEpisodesTimer: isStatsPlaylist
|
|
? setStatsWatchAllEpisodesTimer
|
|
: setWatchAllEpisodesTimer,
|
|
showProfileCard,
|
|
statsType,
|
|
teamsStats,
|
|
toggleActiveEvents,
|
|
toggleActivePlayers,
|
|
toggleIsExpanded,
|
|
togglePopup,
|
|
toggleStatsType,
|
|
tournamentData,
|
|
uniqEvents,
|
|
user,
|
|
watchAllEpisodesTimer: isStatsPlaylist ? statsWatchAllEpisodesTimer : watchAllEpisodesTimer,
|
|
}
|
|
}
|
|
|