parent
18068fd10f
commit
a7eb04b6f4
@ -1,159 +0,0 @@ |
|||||||
import { |
|
||||||
useMemo, |
|
||||||
useEffect, |
|
||||||
useState, |
|
||||||
} from 'react' |
|
||||||
|
|
||||||
import throttle from 'lodash/throttle' |
|
||||||
import isEmpty from 'lodash/isEmpty' |
|
||||||
import every from 'lodash/every' |
|
||||||
import find from 'lodash/find' |
|
||||||
|
|
||||||
import type { |
|
||||||
MatchInfo, |
|
||||||
PlayersStats, |
|
||||||
Player, |
|
||||||
} from 'requests' |
|
||||||
import { getPlayersStats, getMatchParticipants } from 'requests' |
|
||||||
|
|
||||||
import { useObjectState, usePageParams } from 'hooks' |
|
||||||
|
|
||||||
import { StatsType } from 'features/MatchSidePlaylists/components/TabStats/config' |
|
||||||
|
|
||||||
const REQUEST_DELAY = 3000 |
|
||||||
const STATS_POLL_INTERVAL = 30000 |
|
||||||
|
|
||||||
type UsePlayersStatsArgs = { |
|
||||||
matchProfile: MatchInfo, |
|
||||||
playingProgress: number, |
|
||||||
statsType: StatsType, |
|
||||||
} |
|
||||||
|
|
||||||
type PlayersData = { |
|
||||||
team1: Array<Player>, |
|
||||||
team2: Array<Player>, |
|
||||||
} |
|
||||||
|
|
||||||
export const usePlayersStats = ({ |
|
||||||
matchProfile, |
|
||||||
playingProgress, |
|
||||||
statsType, |
|
||||||
}: UsePlayersStatsArgs) => { |
|
||||||
const [playersStats, setPlayersStats] = useObjectState<Record<string, PlayersStats>>({}) |
|
||||||
const [playersData, setPlayersData] = useState<PlayersData>({ team1: [], team2: [] }) |
|
||||||
|
|
||||||
const { |
|
||||||
profileId: matchId, |
|
||||||
sportName, |
|
||||||
sportType, |
|
||||||
} = usePageParams() |
|
||||||
|
|
||||||
const isCurrentStats = statsType === StatsType.CURRENT_STATS |
|
||||||
|
|
||||||
const progressSec = Math.floor(playingProgress / 1000) |
|
||||||
|
|
||||||
const isEmptyPlayersStats = (teamId: number) => ( |
|
||||||
isEmpty(playersStats[teamId]) |
|
||||||
|| every(playersStats[teamId], isEmpty) |
|
||||||
|| isEmpty(playersData[matchProfile?.team1.id === teamId ? 'team1' : 'team2']) |
|
||||||
) |
|
||||||
|
|
||||||
const fetchPlayers = useMemo(() => throttle((second?: number) => { |
|
||||||
if (!matchProfile?.team1.id || !matchProfile?.team1.id) return |
|
||||||
|
|
||||||
try { |
|
||||||
getMatchParticipants({ |
|
||||||
matchId, |
|
||||||
second, |
|
||||||
sportType, |
|
||||||
}).then((data) => { |
|
||||||
const team1Players = find(data, { team_id: matchProfile.team1.id })?.players || [] |
|
||||||
const team2Players = find(data, { team_id: matchProfile.team2.id })?.players || [] |
|
||||||
|
|
||||||
setPlayersData({ |
|
||||||
team1: team1Players, |
|
||||||
team2: team2Players, |
|
||||||
}) |
|
||||||
}) |
|
||||||
|
|
||||||
// eslint-disable-next-line no-empty
|
|
||||||
} catch (e) {} |
|
||||||
}, REQUEST_DELAY), [ |
|
||||||
matchId, |
|
||||||
matchProfile?.team1.id, |
|
||||||
matchProfile?.team2.id, |
|
||||||
sportType, |
|
||||||
]) |
|
||||||
|
|
||||||
const fetchPlayersStats = useMemo(() => throttle((second?: number) => { |
|
||||||
if (!sportName || !matchProfile?.team1.id || !matchProfile?.team2.id) return |
|
||||||
|
|
||||||
try { |
|
||||||
getPlayersStats({ |
|
||||||
matchId, |
|
||||||
second, |
|
||||||
sportName, |
|
||||||
teamId: matchProfile.team1.id, |
|
||||||
}).then((data) => setPlayersStats({ [matchProfile.team1.id]: data })) |
|
||||||
|
|
||||||
getPlayersStats({ |
|
||||||
matchId, |
|
||||||
second, |
|
||||||
sportName, |
|
||||||
teamId: matchProfile.team2.id, |
|
||||||
}).then((data) => setPlayersStats({ [matchProfile?.team2.id]: data })) |
|
||||||
// eslint-disable-next-line no-empty
|
|
||||||
} catch (e) {} |
|
||||||
}, REQUEST_DELAY), [ |
|
||||||
matchId, |
|
||||||
matchProfile?.team1.id, |
|
||||||
matchProfile?.team2.id, |
|
||||||
setPlayersStats, |
|
||||||
sportName, |
|
||||||
]) |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
let interval: NodeJS.Timeout |
|
||||||
|
|
||||||
fetchPlayers() |
|
||||||
|
|
||||||
if (!isCurrentStats) { |
|
||||||
fetchPlayersStats() |
|
||||||
} |
|
||||||
|
|
||||||
if (matchProfile?.live) { |
|
||||||
interval = setInterval(() => { |
|
||||||
if (isCurrentStats) return |
|
||||||
|
|
||||||
fetchPlayersStats() |
|
||||||
fetchPlayers() |
|
||||||
}, STATS_POLL_INTERVAL) |
|
||||||
} |
|
||||||
|
|
||||||
return () => clearInterval(interval) |
|
||||||
}, [ |
|
||||||
fetchPlayersStats, |
|
||||||
fetchPlayers, |
|
||||||
isCurrentStats, |
|
||||||
matchProfile?.live, |
|
||||||
]) |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
if (isCurrentStats) { |
|
||||||
fetchPlayersStats(progressSec) |
|
||||||
fetchPlayers(progressSec) |
|
||||||
} |
|
||||||
}, [ |
|
||||||
fetchPlayersStats, |
|
||||||
fetchPlayers, |
|
||||||
progressSec, |
|
||||||
isCurrentStats, |
|
||||||
matchProfile?.live, |
|
||||||
]) |
|
||||||
|
|
||||||
return { |
|
||||||
isEmptyPlayersStats, |
|
||||||
playersData, |
|
||||||
playersStats, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,12 +0,0 @@ |
|||||||
import { useState } from 'react' |
|
||||||
|
|
||||||
import { StatsType } from 'features/MatchSidePlaylists/components/TabStats/config' |
|
||||||
|
|
||||||
export const useStatsTab = () => { |
|
||||||
const [statsType, setStatsType] = useState<StatsType>(StatsType.FINAL_STATS) |
|
||||||
|
|
||||||
return { |
|
||||||
setStatsType, |
|
||||||
statsType, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,78 +0,0 @@ |
|||||||
import { |
|
||||||
useEffect, |
|
||||||
useState, |
|
||||||
useMemo, |
|
||||||
} from 'react' |
|
||||||
|
|
||||||
import throttle from 'lodash/throttle' |
|
||||||
|
|
||||||
import type { MatchInfo } from 'requests' |
|
||||||
import { getTeamsStats, TeamStatItem } from 'requests' |
|
||||||
|
|
||||||
import { usePageParams } from 'hooks/usePageParams' |
|
||||||
|
|
||||||
import { StatsType } from 'features/MatchSidePlaylists/components/TabStats/config' |
|
||||||
|
|
||||||
const REQUEST_DELAY = 3000 |
|
||||||
const STATS_POLL_INTERVAL = 30000 |
|
||||||
|
|
||||||
type UseTeamsStatsArgs = { |
|
||||||
matchProfile: MatchInfo, |
|
||||||
playingProgress: number, |
|
||||||
statsType: StatsType, |
|
||||||
} |
|
||||||
|
|
||||||
export const useTeamsStats = ({ |
|
||||||
matchProfile, |
|
||||||
playingProgress, |
|
||||||
statsType, |
|
||||||
}: UseTeamsStatsArgs) => { |
|
||||||
const [teamsStats, setTeamsStats] = useState<{ |
|
||||||
[teamId: string]: Array<TeamStatItem>, |
|
||||||
}>({}) |
|
||||||
|
|
||||||
const { profileId: matchId, sportName } = usePageParams() |
|
||||||
|
|
||||||
const progressSec = Math.floor(playingProgress / 1000) |
|
||||||
|
|
||||||
const isCurrentStats = statsType === StatsType.CURRENT_STATS |
|
||||||
|
|
||||||
const fetchTeamsStats = useMemo(() => throttle((second?: number) => { |
|
||||||
if (!sportName) return |
|
||||||
|
|
||||||
getTeamsStats({ |
|
||||||
matchId, |
|
||||||
second, |
|
||||||
sportName, |
|
||||||
}).then(setTeamsStats) |
|
||||||
}, REQUEST_DELAY), [matchId, sportName]) |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
let timer: ReturnType<typeof setInterval> |
|
||||||
|
|
||||||
if (!isCurrentStats) { |
|
||||||
fetchTeamsStats() |
|
||||||
} |
|
||||||
|
|
||||||
if (matchProfile?.live) { |
|
||||||
timer = setInterval(() => { |
|
||||||
if (isCurrentStats) return |
|
||||||
|
|
||||||
fetchTeamsStats() |
|
||||||
}, STATS_POLL_INTERVAL) |
|
||||||
} |
|
||||||
|
|
||||||
return () => clearInterval(timer) |
|
||||||
}, [fetchTeamsStats, matchProfile?.live, isCurrentStats]) |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
if (isCurrentStats) { |
|
||||||
fetchTeamsStats(progressSec) |
|
||||||
} |
|
||||||
}, [fetchTeamsStats, progressSec, isCurrentStats]) |
|
||||||
|
|
||||||
return { |
|
||||||
statsType, |
|
||||||
teamsStats, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,6 +0,0 @@ |
|||||||
export const PARAM_COLUMN_WIDTH = 50 |
|
||||||
export const REQUEST_DELAY = 3000 |
|
||||||
export const STATS_POLL_INTERVAL = 30000 |
|
||||||
export const DISPLAYED_PARAMS_COLUMNS = 4 |
|
||||||
export const FIRST_COLUMN_WIDTH_DEFAULT = 100 |
|
||||||
export const SCROLLBAR_WIDTH = 8 |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
import { useState } from 'react' |
|
||||||
|
|
||||||
import type { SortCondition, PlayersTableProps } from '../types' |
|
||||||
import { usePlayers } from './usePlayers' |
|
||||||
import { useTable } from './useTable' |
|
||||||
|
|
||||||
export const usePlayersTable = ({ teamId }: PlayersTableProps) => { |
|
||||||
const [sortCondition, setSortCondition] = useState<SortCondition>({ dir: 'asc', paramId: null }) |
|
||||||
|
|
||||||
const { |
|
||||||
getFullName, |
|
||||||
getPlayerParams, |
|
||||||
players, |
|
||||||
} = usePlayers({ sortCondition, teamId }) |
|
||||||
|
|
||||||
const { |
|
||||||
containerRef, |
|
||||||
firstColumnWidth, |
|
||||||
getDisplayedValue, |
|
||||||
handleScroll, |
|
||||||
handleSortClick, |
|
||||||
isExpanded, |
|
||||||
paramColumnWidth, |
|
||||||
params, |
|
||||||
showExpandButton, |
|
||||||
showLeftArrow, |
|
||||||
showRightArrow, |
|
||||||
slideLeft, |
|
||||||
slideRight, |
|
||||||
tableWrapperRef, |
|
||||||
toggleIsExpanded, |
|
||||||
} = useTable({ |
|
||||||
setSortCondition, |
|
||||||
teamId, |
|
||||||
}) |
|
||||||
|
|
||||||
return { |
|
||||||
containerRef, |
|
||||||
firstColumnWidth, |
|
||||||
getDisplayedValue, |
|
||||||
getFullName, |
|
||||||
getPlayerParams, |
|
||||||
handleScroll, |
|
||||||
handleSortClick, |
|
||||||
isExpanded, |
|
||||||
paramColumnWidth, |
|
||||||
params, |
|
||||||
players, |
|
||||||
showExpandButton, |
|
||||||
showLeftArrow, |
|
||||||
showRightArrow, |
|
||||||
slideLeft, |
|
||||||
slideRight, |
|
||||||
sortCondition, |
|
||||||
tableWrapperRef, |
|
||||||
toggleIsExpanded, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,83 +0,0 @@ |
|||||||
import { useMemo, useCallback } from 'react' |
|
||||||
|
|
||||||
import orderBy from 'lodash/orderBy' |
|
||||||
import isNil from 'lodash/isNil' |
|
||||||
import trim from 'lodash/trim' |
|
||||||
|
|
||||||
import type { Player, PlayerParam } from 'requests' |
|
||||||
|
|
||||||
import { useToggle } from 'hooks' |
|
||||||
|
|
||||||
import { useMatchPageStore } from 'features/MatchPage/store' |
|
||||||
import { useLexicsStore } from 'features/LexicsStore' |
|
||||||
|
|
||||||
import type { SortCondition } from '../types' |
|
||||||
|
|
||||||
type UsePlayersArgs = { |
|
||||||
sortCondition: SortCondition, |
|
||||||
teamId: number, |
|
||||||
} |
|
||||||
|
|
||||||
export const usePlayers = ({ sortCondition, teamId }: UsePlayersArgs) => { |
|
||||||
const { isOpen: isExpanded, toggle: toggleIsExpanded } = useToggle() |
|
||||||
const { |
|
||||||
playersData, |
|
||||||
playersStats, |
|
||||||
profile: matchProfile, |
|
||||||
} = useMatchPageStore() |
|
||||||
const { suffix } = useLexicsStore() |
|
||||||
|
|
||||||
const getPlayerParams = useCallback( |
|
||||||
(playerId: number) => playersStats[teamId][playerId] || {}, |
|
||||||
[playersStats, teamId], |
|
||||||
) |
|
||||||
|
|
||||||
const getDisplayedValue = ({ val }: PlayerParam) => (isNil(val) ? '-' : val) |
|
||||||
|
|
||||||
const getFullName = useCallback((player: Player) => ( |
|
||||||
trim(`${player[`firstname_${suffix}`]} ${player[`lastname_${suffix}`]}`) |
|
||||||
), [suffix]) |
|
||||||
|
|
||||||
const getParamValue = useCallback((playerId: number, paramId: number) => { |
|
||||||
const playerParams = getPlayerParams(playerId) |
|
||||||
const { val } = playerParams[paramId] || {} |
|
||||||
|
|
||||||
return val |
|
||||||
}, [getPlayerParams]) |
|
||||||
|
|
||||||
const sortedPlayers = useMemo(() => { |
|
||||||
const players = playersData[matchProfile?.team1.id === teamId ? 'team1' : 'team2'] |
|
||||||
|
|
||||||
return isNil(sortCondition.paramId) |
|
||||||
? orderBy(players, getFullName) |
|
||||||
: orderBy( |
|
||||||
players, |
|
||||||
[ |
|
||||||
(player) => { |
|
||||||
const paramValue = getParamValue(player.id, sortCondition.paramId!) |
|
||||||
|
|
||||||
return isNil(paramValue) ? -1 : paramValue |
|
||||||
}, |
|
||||||
getFullName, |
|
||||||
], |
|
||||||
sortCondition.dir, |
|
||||||
) |
|
||||||
}, [ |
|
||||||
getFullName, |
|
||||||
getParamValue, |
|
||||||
playersData, |
|
||||||
matchProfile?.team1.id, |
|
||||||
sortCondition.dir, |
|
||||||
sortCondition.paramId, |
|
||||||
teamId, |
|
||||||
]) |
|
||||||
|
|
||||||
return { |
|
||||||
getDisplayedValue, |
|
||||||
getFullName, |
|
||||||
getPlayerParams, |
|
||||||
isExpanded, |
|
||||||
players: sortedPlayers, |
|
||||||
toggleIsExpanded, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,171 +0,0 @@ |
|||||||
import type { |
|
||||||
SyntheticEvent, |
|
||||||
Dispatch, |
|
||||||
SetStateAction, |
|
||||||
} from 'react' |
|
||||||
import { |
|
||||||
useRef, |
|
||||||
useState, |
|
||||||
useEffect, |
|
||||||
useMemo, |
|
||||||
} from 'react' |
|
||||||
|
|
||||||
import size from 'lodash/size' |
|
||||||
import isNil from 'lodash/isNil' |
|
||||||
import reduce from 'lodash/reduce' |
|
||||||
import forEach from 'lodash/forEach' |
|
||||||
import values from 'lodash/values' |
|
||||||
import round from 'lodash/round' |
|
||||||
import map from 'lodash/map' |
|
||||||
|
|
||||||
import { isMobileDevice } from 'config' |
|
||||||
|
|
||||||
import type { PlayerParam, PlayersStats } from 'requests' |
|
||||||
|
|
||||||
import { useToggle } from 'hooks' |
|
||||||
|
|
||||||
import { useMatchPageStore } from 'features/MatchPage/store' |
|
||||||
import { useLexicsConfig } from 'features/LexicsStore' |
|
||||||
|
|
||||||
import type { SortCondition } from '../types' |
|
||||||
import { |
|
||||||
PARAM_COLUMN_WIDTH, |
|
||||||
DISPLAYED_PARAMS_COLUMNS, |
|
||||||
FIRST_COLUMN_WIDTH_DEFAULT, |
|
||||||
SCROLLBAR_WIDTH, |
|
||||||
} from '../config' |
|
||||||
|
|
||||||
type UseTableArgs = { |
|
||||||
setSortCondition: Dispatch<SetStateAction<SortCondition>>, |
|
||||||
teamId: number, |
|
||||||
} |
|
||||||
|
|
||||||
type HeaderParam = Pick<PlayerParam, 'id' | 'lexica_short' | 'lexic'> |
|
||||||
|
|
||||||
export const useTable = ({ |
|
||||||
setSortCondition, |
|
||||||
teamId, |
|
||||||
}: UseTableArgs) => { |
|
||||||
const containerRef = useRef<HTMLDivElement>(null) |
|
||||||
const tableWrapperRef = useRef<HTMLDivElement>(null) |
|
||||||
|
|
||||||
const [showLeftArrow, setShowLeftArrow] = useState(false) |
|
||||||
const [showRightArrow, setShowRightArrow] = useState(false) |
|
||||||
|
|
||||||
const { isOpen: isExpanded, toggle: toggleIsExpanded } = useToggle() |
|
||||||
const { playersStats } = useMatchPageStore() |
|
||||||
|
|
||||||
const params = useMemo(() => ( |
|
||||||
reduce<PlayersStats, Record<string, HeaderParam>>( |
|
||||||
playersStats[teamId], |
|
||||||
(acc, curr) => { |
|
||||||
forEach(values(curr), ({ |
|
||||||
id, |
|
||||||
lexic, |
|
||||||
lexica_short, |
|
||||||
}) => { |
|
||||||
acc[id] = acc[id] || { |
|
||||||
id, |
|
||||||
lexic, |
|
||||||
lexica_short, |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
return acc |
|
||||||
}, |
|
||||||
{}, |
|
||||||
) |
|
||||||
), [playersStats, teamId]) |
|
||||||
|
|
||||||
const lexics = useMemo(() => ( |
|
||||||
reduce<HeaderParam, Array<number>>( |
|
||||||
values(params), |
|
||||||
(acc, { lexic, lexica_short }) => { |
|
||||||
if (lexic) acc.push(lexic) |
|
||||||
if (lexica_short) acc.push(lexica_short) |
|
||||||
|
|
||||||
return acc |
|
||||||
}, |
|
||||||
[], |
|
||||||
) |
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
), [map(params, 'id').sort().join('')]) |
|
||||||
|
|
||||||
useLexicsConfig(lexics) |
|
||||||
|
|
||||||
const paramsCount = size(params) |
|
||||||
|
|
||||||
const getParamColumnWidth = () => { |
|
||||||
const rest = ( |
|
||||||
(containerRef.current?.clientWidth || 0) - FIRST_COLUMN_WIDTH_DEFAULT - SCROLLBAR_WIDTH |
|
||||||
) |
|
||||||
const desktopWith = PARAM_COLUMN_WIDTH |
|
||||||
const mobileWidth = paramsCount < DISPLAYED_PARAMS_COLUMNS ? 0 : rest / DISPLAYED_PARAMS_COLUMNS |
|
||||||
|
|
||||||
return isMobileDevice ? mobileWidth : desktopWith |
|
||||||
} |
|
||||||
|
|
||||||
const getFirstColumnWidth = () => { |
|
||||||
if (isExpanded) return 0 |
|
||||||
|
|
||||||
return paramsCount < DISPLAYED_PARAMS_COLUMNS ? 0 : FIRST_COLUMN_WIDTH_DEFAULT |
|
||||||
} |
|
||||||
|
|
||||||
const paramColumnWidth = getParamColumnWidth() |
|
||||||
const firstColumnWidth = getFirstColumnWidth() |
|
||||||
|
|
||||||
const slideLeft = () => tableWrapperRef.current?.scrollBy(-paramColumnWidth, 0) |
|
||||||
const slideRight = () => tableWrapperRef.current?.scrollBy(paramColumnWidth, 0) |
|
||||||
|
|
||||||
const getDisplayedValue = ({ val }: PlayerParam) => (isNil(val) ? '-' : round(val, 2)) |
|
||||||
|
|
||||||
const handleScroll = (e: SyntheticEvent<HTMLDivElement>) => { |
|
||||||
const { |
|
||||||
clientWidth, |
|
||||||
scrollLeft, |
|
||||||
scrollWidth, |
|
||||||
} = e.currentTarget |
|
||||||
|
|
||||||
const scrollRight = scrollWidth - (scrollLeft + clientWidth) |
|
||||||
|
|
||||||
setShowLeftArrow(scrollLeft > 0) |
|
||||||
setShowRightArrow(scrollRight > 0) |
|
||||||
} |
|
||||||
|
|
||||||
const handleSortClick = (paramId: number) => () => { |
|
||||||
setSortCondition((curr) => ({ |
|
||||||
dir: curr.dir === 'asc' || curr.paramId !== paramId ? 'desc' : 'asc', |
|
||||||
paramId, |
|
||||||
})) |
|
||||||
} |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
const { |
|
||||||
clientWidth = 0, |
|
||||||
scrollLeft = 0, |
|
||||||
scrollWidth = 0, |
|
||||||
} = tableWrapperRef.current || {} |
|
||||||
|
|
||||||
const scrollRight = scrollWidth - (scrollLeft + clientWidth) |
|
||||||
|
|
||||||
setShowRightArrow(scrollRight > 0) |
|
||||||
}, [isExpanded]) |
|
||||||
|
|
||||||
return { |
|
||||||
containerRef, |
|
||||||
firstColumnWidth, |
|
||||||
getDisplayedValue, |
|
||||||
handleScroll, |
|
||||||
handleSortClick, |
|
||||||
isExpanded, |
|
||||||
paramColumnWidth, |
|
||||||
params, |
|
||||||
showExpandButton: !isMobileDevice && paramsCount > DISPLAYED_PARAMS_COLUMNS, |
|
||||||
showLeftArrow, |
|
||||||
showRightArrow, |
|
||||||
slideLeft, |
|
||||||
slideRight, |
|
||||||
tableWrapperRef, |
|
||||||
toggleIsExpanded, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,166 +1,243 @@ |
|||||||
import { Fragment } from 'react' |
|
||||||
|
|
||||||
import map from 'lodash/map' |
|
||||||
import includes from 'lodash/includes' |
|
||||||
|
|
||||||
import { PlayerParam } from 'requests' |
|
||||||
|
|
||||||
import { T9n } from 'features/T9n' |
|
||||||
|
|
||||||
import type { PlayersTableProps } from './types' |
|
||||||
import { usePlayersTable } from './hooks' |
|
||||||
import { |
import { |
||||||
Container, |
|
||||||
TableWrapper, |
|
||||||
Table, |
Table, |
||||||
FirstColumn, |
Thead, |
||||||
Cell, |
Th, |
||||||
Row, |
Tbody, |
||||||
|
Tr, |
||||||
|
Td, |
||||||
PlayerNum, |
PlayerNum, |
||||||
PlayerNameWrapper, |
|
||||||
PlayerName, |
|
||||||
ParamShortTitle, |
ParamShortTitle, |
||||||
ArrowButtonRight, |
|
||||||
ArrowButtonLeft, |
|
||||||
Arrow, |
|
||||||
ExpandButton, |
|
||||||
Tooltip, |
|
||||||
} from './styled' |
} from './styled' |
||||||
|
|
||||||
export const PlayersTable = (props: PlayersTableProps) => { |
export const PlayersTable = () => ( |
||||||
const { |
<Table> |
||||||
containerRef, |
<Thead> |
||||||
firstColumnWidth, |
<Th /> |
||||||
getDisplayedValue, |
<Th> |
||||||
getFullName, |
<ParamShortTitle>Min</ParamShortTitle> |
||||||
getPlayerParams, |
</Th> |
||||||
handleScroll, |
<Th sorted> |
||||||
handleSortClick, |
<ParamShortTitle>Pt</ParamShortTitle> |
||||||
isExpanded, |
</Th> |
||||||
paramColumnWidth, |
<Th> |
||||||
params, |
<ParamShortTitle>Reb</ParamShortTitle> |
||||||
players, |
</Th> |
||||||
showExpandButton, |
<Th> |
||||||
showLeftArrow, |
<ParamShortTitle>Ass</ParamShortTitle> |
||||||
showRightArrow, |
</Th> |
||||||
slideLeft, |
<Th> |
||||||
slideRight, |
<ParamShortTitle>To</ParamShortTitle> |
||||||
sortCondition, |
</Th> |
||||||
tableWrapperRef, |
</Thead> |
||||||
toggleIsExpanded, |
<Tbody> |
||||||
} = usePlayersTable(props) |
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
return ( |
<Td clickable>97</Td> |
||||||
<Container |
<Td sorted>12</Td> |
||||||
ref={containerRef} |
<Td>2</Td> |
||||||
isExpanded={isExpanded} |
<Td>1</Td> |
||||||
> |
<Td>4</Td> |
||||||
<TableWrapper |
</Tr> |
||||||
ref={tableWrapperRef} |
<Tr> |
||||||
isExpanded={isExpanded} |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
onScroll={handleScroll} |
<Td clickable>97</Td> |
||||||
> |
<Td sorted>12</Td> |
||||||
{!isExpanded && ( |
<Td>2</Td> |
||||||
<Fragment> |
<Td>1</Td> |
||||||
{showLeftArrow && ( |
<Td>4</Td> |
||||||
<ArrowButtonLeft |
</Tr> |
||||||
aria-label='Scroll to left' |
<Tr> |
||||||
onClick={slideLeft} |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
> |
<Td clickable>97</Td> |
||||||
<Arrow direction='left' /> |
<Td sorted>12</Td> |
||||||
</ArrowButtonLeft> |
<Td>2</Td> |
||||||
)} |
<Td>1</Td> |
||||||
{showRightArrow && ( |
<Td>4</Td> |
||||||
<ArrowButtonRight |
</Tr> |
||||||
aria-label='Scroll to right' |
<Tr> |
||||||
onClick={slideRight} |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
> |
<Td clickable>97</Td> |
||||||
<Arrow direction='right' /> |
<Td sorted>12</Td> |
||||||
</ArrowButtonRight> |
<Td>2</Td> |
||||||
)} |
<Td>1</Td> |
||||||
</Fragment> |
<Td>4</Td> |
||||||
)} |
</Tr> |
||||||
<FirstColumn columnWidth={firstColumnWidth}> |
<Tr> |
||||||
<Row> |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
<Cell> |
<Td clickable>97</Td> |
||||||
{showExpandButton && ( |
<Td sorted>12</Td> |
||||||
<ExpandButton |
<Td>2</Td> |
||||||
aria-label={isExpanded ? 'Reduce' : 'Expand'} |
<Td>1</Td> |
||||||
onClick={toggleIsExpanded} |
<Td>4</Td> |
||||||
> |
</Tr> |
||||||
<Arrow direction={isExpanded ? 'right' : 'left'} /> |
<Tr> |
||||||
<Arrow direction={isExpanded ? 'right' : 'left'} /> |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
</ExpandButton> |
<Td clickable>97</Td> |
||||||
)} |
<Td sorted>12</Td> |
||||||
</Cell> |
<Td>2</Td> |
||||||
</Row> |
<Td>1</Td> |
||||||
{map(players, (player) => { |
<Td>4</Td> |
||||||
const fullName = getFullName(player) |
</Tr> |
||||||
|
<Tr> |
||||||
return ( |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
<Row key={player.id}> |
<Td clickable>97</Td> |
||||||
<Cell> |
<Td sorted>12</Td> |
||||||
<PlayerNum> |
<Td>2</Td> |
||||||
{player.club_shirt_num} |
<Td>1</Td> |
||||||
</PlayerNum>{' '} |
<Td>4</Td> |
||||||
<PlayerNameWrapper> |
</Tr> |
||||||
<PlayerName columnWidth={firstColumnWidth}> |
<Tr> |
||||||
{fullName} |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
</PlayerName> |
<Td clickable>97</Td> |
||||||
<Tooltip> |
<Td sorted>12</Td> |
||||||
<PlayerName>{fullName}</PlayerName> |
<Td>2</Td> |
||||||
</Tooltip> |
<Td>1</Td> |
||||||
</PlayerNameWrapper> |
<Td>4</Td> |
||||||
</Cell> |
</Tr> |
||||||
</Row> |
<Tr> |
||||||
) |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
})} |
<Td clickable>97</Td> |
||||||
</FirstColumn> |
<Td sorted>12</Td> |
||||||
<Table> |
<Td>2</Td> |
||||||
<Row> |
<Td>1</Td> |
||||||
{map(params, ({ |
<Td>4</Td> |
||||||
id, |
</Tr> |
||||||
lexic, |
<Tr> |
||||||
lexica_short, |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
}) => ( |
<Td clickable>97</Td> |
||||||
<Cell |
<Td sorted>12</Td> |
||||||
key={id} |
<Td>2</Td> |
||||||
columnWidth={paramColumnWidth} |
<Td>1</Td> |
||||||
onClick={handleSortClick(id)} |
<Td>4</Td> |
||||||
sorted={sortCondition.paramId === id} |
</Tr> |
||||||
headerCell |
<Tr> |
||||||
> |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
<ParamShortTitle t={lexica_short || ''} /> |
<Td clickable>97</Td> |
||||||
<Tooltip> |
<Td sorted>12</Td> |
||||||
<T9n t={lexic} /> |
<Td>2</Td> |
||||||
</Tooltip> |
<Td>1</Td> |
||||||
</Cell> |
<Td>4</Td> |
||||||
))} |
</Tr> |
||||||
</Row> |
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
{map(players, (player) => ( |
<Td clickable>97</Td> |
||||||
<Row key={player.id}> |
<Td sorted>12</Td> |
||||||
{map(params, ({ id }) => { |
<Td>2</Td> |
||||||
const playerParam = getPlayerParams(player.id)[id] as PlayerParam | undefined |
<Td>1</Td> |
||||||
const value = playerParam ? getDisplayedValue(playerParam) : '-' |
<Td>4</Td> |
||||||
const clickable = Boolean(playerParam?.clickable) && !includes([0, '-'], value) |
</Tr> |
||||||
const sorted = sortCondition.paramId === id |
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
return ( |
<Td clickable>97</Td> |
||||||
<Cell |
<Td sorted>12</Td> |
||||||
columnWidth={paramColumnWidth} |
<Td>2</Td> |
||||||
key={id} |
<Td>1</Td> |
||||||
clickable={clickable} |
<Td>4</Td> |
||||||
sorted={sorted} |
</Tr> |
||||||
> |
<Tr> |
||||||
{value} |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
</Cell> |
<Td clickable>97</Td> |
||||||
) |
<Td sorted>12</Td> |
||||||
})} |
<Td>2</Td> |
||||||
</Row> |
<Td>1</Td> |
||||||
))} |
<Td>4</Td> |
||||||
</Table> |
</Tr> |
||||||
</TableWrapper> |
<Tr> |
||||||
</Container> |
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
) |
<Td clickable>97</Td> |
||||||
} |
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
<Tr> |
||||||
|
<Td><PlayerNum>57</PlayerNum> Selikhov</Td> |
||||||
|
<Td clickable>97</Td> |
||||||
|
<Td sorted>12</Td> |
||||||
|
<Td>2</Td> |
||||||
|
<Td>1</Td> |
||||||
|
<Td>4</Td> |
||||||
|
</Tr> |
||||||
|
</Tbody> |
||||||
|
</Table> |
||||||
|
) |
||||||
|
|||||||
@ -1,8 +0,0 @@ |
|||||||
export type PlayersTableProps = { |
|
||||||
teamId: number, |
|
||||||
} |
|
||||||
|
|
||||||
export type SortCondition = { |
|
||||||
dir: 'asc' | 'desc', |
|
||||||
paramId: number | null, |
|
||||||
} |
|
||||||
@ -1,68 +0,0 @@ |
|||||||
import { useEffect, useState } from 'react' |
|
||||||
|
|
||||||
import isEmpty from 'lodash/isEmpty' |
|
||||||
|
|
||||||
import { useMatchPageStore } from 'features/MatchPage/store' |
|
||||||
|
|
||||||
import { StatsType, Tabs } from './config' |
|
||||||
|
|
||||||
export const useTabStats = () => { |
|
||||||
const [selectedTab, setSelectedTab] = useState<Tabs>(Tabs.TEAMS) |
|
||||||
|
|
||||||
const { |
|
||||||
isEmptyPlayersStats, |
|
||||||
profile: matchProfile, |
|
||||||
setStatsType, |
|
||||||
statsType, |
|
||||||
teamsStats, |
|
||||||
} = useMatchPageStore() |
|
||||||
|
|
||||||
const isFinalStatsType = statsType === StatsType.FINAL_STATS |
|
||||||
|
|
||||||
const switchTitleLexic = isFinalStatsType ? 'final_stats' : 'current_stats' |
|
||||||
const tooltipLexic = isFinalStatsType ? 'display_all_stats' : 'display_stats_according_to_video' |
|
||||||
|
|
||||||
const isVisibleTeamsTab = !isEmpty(teamsStats) |
|
||||||
const isVisibleTeam1PlayersTab = Boolean( |
|
||||||
matchProfile && !isEmptyPlayersStats(matchProfile.team1.id), |
|
||||||
) |
|
||||||
const isVisibleTeam2PlayersTab = Boolean( |
|
||||||
matchProfile && !isEmptyPlayersStats(matchProfile.team2.id), |
|
||||||
) |
|
||||||
|
|
||||||
const toggleStatsType = () => { |
|
||||||
const newStatsType = isFinalStatsType ? StatsType.CURRENT_STATS : StatsType.FINAL_STATS |
|
||||||
|
|
||||||
setStatsType(newStatsType) |
|
||||||
} |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
switch (true) { |
|
||||||
case isVisibleTeamsTab: |
|
||||||
setSelectedTab(Tabs.TEAMS) |
|
||||||
break |
|
||||||
|
|
||||||
case isVisibleTeam1PlayersTab: |
|
||||||
setSelectedTab(Tabs.TEAM1) |
|
||||||
break |
|
||||||
|
|
||||||
case isVisibleTeam2PlayersTab: |
|
||||||
setSelectedTab(Tabs.TEAM2) |
|
||||||
break |
|
||||||
|
|
||||||
default: |
|
||||||
} |
|
||||||
}, [isVisibleTeam1PlayersTab, isVisibleTeam2PlayersTab, isVisibleTeamsTab]) |
|
||||||
|
|
||||||
return { |
|
||||||
isFinalStatsType, |
|
||||||
isVisibleTeam1PlayersTab, |
|
||||||
isVisibleTeam2PlayersTab, |
|
||||||
isVisibleTeamsTab, |
|
||||||
selectedTab, |
|
||||||
setSelectedTab, |
|
||||||
switchTitleLexic, |
|
||||||
toggleStatsType, |
|
||||||
tooltipLexic, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,276 @@ |
|||||||
|
import { |
||||||
|
Container, |
||||||
|
Row, |
||||||
|
TeamShortName, |
||||||
|
ParamValueContainer, |
||||||
|
ParamValue, |
||||||
|
ParamTitle, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
export const TeamsStats = () => ( |
||||||
|
<Container> |
||||||
|
<Row> |
||||||
|
<TeamShortName>DIN</TeamShortName> |
||||||
|
<TeamShortName>SPA</TeamShortName> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue clickable>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue clickable>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<ParamValueContainer> |
||||||
|
<ParamValue>90</ParamValue> |
||||||
|
</ParamValueContainer> |
||||||
|
<ParamTitle>Points</ParamTitle> |
||||||
|
<ParamValue>123</ParamValue> |
||||||
|
</Row> |
||||||
|
</Container> |
||||||
|
) |
||||||
@ -1,31 +0,0 @@ |
|||||||
import isNumber from 'lodash/isNumber' |
|
||||||
import find from 'lodash/find' |
|
||||||
import round from 'lodash/round' |
|
||||||
|
|
||||||
import type { Param } from 'requests' |
|
||||||
|
|
||||||
import { useMatchPageStore } from 'features/MatchPage/store' |
|
||||||
|
|
||||||
export const useTeamsStatsTable = () => { |
|
||||||
const { profile, teamsStats } = useMatchPageStore() |
|
||||||
|
|
||||||
const getDisplayedValue = (val: any) => ( |
|
||||||
isNumber(val) ? round(val, 2) : '-' |
|
||||||
) |
|
||||||
|
|
||||||
const getStatItemById = (paramId: number) => { |
|
||||||
if (!profile) return null |
|
||||||
|
|
||||||
return find(teamsStats[profile?.team2.id], ({ param1 }) => param1.id === paramId) || null |
|
||||||
} |
|
||||||
|
|
||||||
const isClickable = (param: Param) => ( |
|
||||||
Boolean(param.val) && param.clickable |
|
||||||
) |
|
||||||
|
|
||||||
return { |
|
||||||
getDisplayedValue, |
|
||||||
getStatItemById, |
|
||||||
isClickable, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,93 +0,0 @@ |
|||||||
import { Fragment } from 'react' |
|
||||||
|
|
||||||
import map from 'lodash/map' |
|
||||||
|
|
||||||
import { useMatchPageStore } from 'features/MatchPage/store' |
|
||||||
import { useLexicsStore } from 'features/LexicsStore' |
|
||||||
|
|
||||||
import { useTeamsStatsTable } from './hooks' |
|
||||||
import { |
|
||||||
Container, |
|
||||||
Row, |
|
||||||
TeamShortName, |
|
||||||
ParamValueContainer, |
|
||||||
ParamValue, |
|
||||||
StatItemTitle, |
|
||||||
Divider, |
|
||||||
} from './styled' |
|
||||||
|
|
||||||
export const TeamsStatsTable = () => { |
|
||||||
const { profile, teamsStats } = useMatchPageStore() |
|
||||||
const { |
|
||||||
getDisplayedValue, |
|
||||||
getStatItemById, |
|
||||||
isClickable, |
|
||||||
} = useTeamsStatsTable() |
|
||||||
const { lang } = useLexicsStore() |
|
||||||
|
|
||||||
if (!profile) return null |
|
||||||
|
|
||||||
return ( |
|
||||||
<Container> |
|
||||||
<Row> |
|
||||||
<TeamShortName |
|
||||||
nameObj={profile.team1} |
|
||||||
prefix='abbrev_' |
|
||||||
/> |
|
||||||
<TeamShortName |
|
||||||
nameObj={profile.team2} |
|
||||||
prefix='abbrev_' |
|
||||||
/> |
|
||||||
</Row> |
|
||||||
|
|
||||||
{map(teamsStats[profile.team1.id], (team1StatItem) => { |
|
||||||
const team2StatItem = getStatItemById(team1StatItem.param1.id) |
|
||||||
const statItemTitle = team1StatItem[`name_${lang === 'ru' ? 'ru' : 'en'}`] |
|
||||||
|
|
||||||
return ( |
|
||||||
<Row key={team1StatItem.param1.id}> |
|
||||||
<ParamValueContainer> |
|
||||||
<ParamValue |
|
||||||
clickable={isClickable(team1StatItem.param1)} |
|
||||||
> |
|
||||||
{getDisplayedValue(team1StatItem.param1.val)} |
|
||||||
</ParamValue> |
|
||||||
{team1StatItem.param2 && ( |
|
||||||
<Fragment> |
|
||||||
<Divider>/</Divider> |
|
||||||
<ParamValue |
|
||||||
clickable={isClickable(team1StatItem.param2)} |
|
||||||
> |
|
||||||
{getDisplayedValue(team1StatItem.param2.val)} |
|
||||||
</ParamValue> |
|
||||||
</Fragment> |
|
||||||
)} |
|
||||||
</ParamValueContainer> |
|
||||||
|
|
||||||
<StatItemTitle>{statItemTitle}</StatItemTitle> |
|
||||||
|
|
||||||
{team2StatItem && ( |
|
||||||
<ParamValueContainer> |
|
||||||
<ParamValue |
|
||||||
clickable={isClickable(team2StatItem.param1)} |
|
||||||
> |
|
||||||
{getDisplayedValue(team2StatItem.param1.val)} |
|
||||||
</ParamValue> |
|
||||||
{team2StatItem.param2 && ( |
|
||||||
<Fragment> |
|
||||||
<Divider>/</Divider> |
|
||||||
<ParamValue |
|
||||||
clickable={isClickable(team2StatItem.param2)} |
|
||||||
> |
|
||||||
{getDisplayedValue(team2StatItem.param2.val)} |
|
||||||
</ParamValue> |
|
||||||
</Fragment> |
|
||||||
)} |
|
||||||
</ParamValueContainer> |
|
||||||
)} |
|
||||||
</Row> |
|
||||||
) |
|
||||||
})} |
|
||||||
</Container> |
|
||||||
) |
|
||||||
} |
|
||||||
@ -1,25 +0,0 @@ |
|||||||
import toUpper from 'lodash/toUpper' |
|
||||||
import split from 'lodash/split' |
|
||||||
import size from 'lodash/size' |
|
||||||
|
|
||||||
import pipe from 'lodash/fp/pipe' |
|
||||||
import take from 'lodash/fp/take' |
|
||||||
import join from 'lodash/fp/join' |
|
||||||
import map from 'lodash/fp/map' |
|
||||||
|
|
||||||
export const getTeamAbbr = (teamName: string) => { |
|
||||||
const nameParts = split(teamName, ' ') |
|
||||||
|
|
||||||
return size(nameParts) > 1 |
|
||||||
? pipe( |
|
||||||
map(take(1)), |
|
||||||
join(''), |
|
||||||
toUpper, |
|
||||||
)(nameParts) |
|
||||||
|
|
||||||
: pipe( |
|
||||||
take(3), |
|
||||||
join(''), |
|
||||||
toUpper, |
|
||||||
)(nameParts[0]) |
|
||||||
} |
|
||||||
@ -1,65 +0,0 @@ |
|||||||
import isUndefined from 'lodash/isUndefined' |
|
||||||
|
|
||||||
import { SportTypes } from 'config' |
|
||||||
|
|
||||||
import { callApi } from 'helpers' |
|
||||||
|
|
||||||
export type Player = { |
|
||||||
birthday: string | null, |
|
||||||
c_country: number, |
|
||||||
c_gender: number, |
|
||||||
club_f_team: number, |
|
||||||
club_shirt_num: number, |
|
||||||
firstname_eng: string, |
|
||||||
firstname_national: string | null, |
|
||||||
firstname_rus: string, |
|
||||||
height: number | null, |
|
||||||
id: number, |
|
||||||
is_gk: boolean, |
|
||||||
lastname_eng: string, |
|
||||||
lastname_national: string | null, |
|
||||||
lastname_rus: string, |
|
||||||
national_f_team: number | null, |
|
||||||
national_shirt_num: number, |
|
||||||
nickname_eng: string | null, |
|
||||||
nickname_rus: string | null, |
|
||||||
weight: number | null, |
|
||||||
} |
|
||||||
|
|
||||||
type DataItem = { |
|
||||||
players: Array<Player>, |
|
||||||
team_id: number, |
|
||||||
} |
|
||||||
|
|
||||||
type Response = { |
|
||||||
data?: Array<DataItem>, |
|
||||||
error?: { |
|
||||||
code: string, |
|
||||||
message: string, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
type GetMatchParticipantsArgs = { |
|
||||||
matchId: number, |
|
||||||
second?: number, |
|
||||||
sportType: SportTypes, |
|
||||||
} |
|
||||||
|
|
||||||
export const getMatchParticipants = async ({ |
|
||||||
matchId, |
|
||||||
second, |
|
||||||
sportType, |
|
||||||
}: GetMatchParticipantsArgs) => { |
|
||||||
const config = { |
|
||||||
method: 'GET', |
|
||||||
} |
|
||||||
|
|
||||||
const response: Response = await callApi({ |
|
||||||
config, |
|
||||||
url: `http://136.243.17.103:8888/ask/participants?sport_id=${sportType}&match_id=${matchId}${isUndefined(second) ? '' : `&second=${second}`}`, |
|
||||||
}) |
|
||||||
|
|
||||||
if (response.error) Promise.reject(response) |
|
||||||
|
|
||||||
return Promise.resolve(response.data || []) |
|
||||||
} |
|
||||||
@ -1,54 +0,0 @@ |
|||||||
import isUndefined from 'lodash/isUndefined' |
|
||||||
|
|
||||||
import { callApi } from 'helpers' |
|
||||||
|
|
||||||
export type PlayerParam = { |
|
||||||
clickable: boolean, |
|
||||||
data_type: string, |
|
||||||
id: number, |
|
||||||
lexic: number, |
|
||||||
lexica_short: number | null, |
|
||||||
markers: Array<number> | null, |
|
||||||
name_en: string, |
|
||||||
name_ru: string, |
|
||||||
val: number | null, |
|
||||||
} |
|
||||||
|
|
||||||
export type PlayersStats = { |
|
||||||
[playerId: string]: { |
|
||||||
[paramId: string]: PlayerParam, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
type Response = { |
|
||||||
data?: PlayersStats, |
|
||||||
error?: string, |
|
||||||
message?: string, |
|
||||||
} |
|
||||||
|
|
||||||
type GetPlayersStatsArgs = { |
|
||||||
matchId: number, |
|
||||||
second?: number, |
|
||||||
sportName: string, |
|
||||||
teamId: number, |
|
||||||
} |
|
||||||
|
|
||||||
export const getPlayersStats = async ({ |
|
||||||
matchId, |
|
||||||
second, |
|
||||||
sportName, |
|
||||||
teamId, |
|
||||||
}: GetPlayersStatsArgs) => { |
|
||||||
const config = { |
|
||||||
method: 'GET', |
|
||||||
} |
|
||||||
|
|
||||||
const response: Response = await callApi({ |
|
||||||
config, |
|
||||||
url: `http://136.243.17.103:8888/${sportName}/matches/${matchId}/teams/${teamId}/players/stats${isUndefined(second) ? '' : `?second=${second}`}`, |
|
||||||
}) |
|
||||||
|
|
||||||
if (response.error) Promise.reject(response) |
|
||||||
|
|
||||||
return Promise.resolve(response.data || {}) |
|
||||||
} |
|
||||||
@ -1,56 +0,0 @@ |
|||||||
import isUndefined from 'lodash/isUndefined' |
|
||||||
|
|
||||||
import { callApi } from 'helpers' |
|
||||||
|
|
||||||
export type Param = { |
|
||||||
clickable: boolean, |
|
||||||
data_type: string, |
|
||||||
id: number, |
|
||||||
lexic: number, |
|
||||||
markers: Array<number>, |
|
||||||
name_en: string, |
|
||||||
name_ru: string, |
|
||||||
val: number | null, |
|
||||||
} |
|
||||||
|
|
||||||
export type TeamStatItem = { |
|
||||||
lexic: number, |
|
||||||
name_en: string, |
|
||||||
name_ru: string, |
|
||||||
order: number, |
|
||||||
param1: Param, |
|
||||||
param2: Param | null, |
|
||||||
} |
|
||||||
|
|
||||||
type Response = { |
|
||||||
data?: { |
|
||||||
[teamId: string]: Array<TeamStatItem>, |
|
||||||
}, |
|
||||||
error?: string, |
|
||||||
message?: string, |
|
||||||
} |
|
||||||
|
|
||||||
type GetTeamsStatsArgs = { |
|
||||||
matchId: number, |
|
||||||
second?: number, |
|
||||||
sportName: string, |
|
||||||
} |
|
||||||
|
|
||||||
export const getTeamsStats = async ({ |
|
||||||
matchId, |
|
||||||
second, |
|
||||||
sportName, |
|
||||||
}: GetTeamsStatsArgs) => { |
|
||||||
const config = { |
|
||||||
method: 'GET', |
|
||||||
} |
|
||||||
|
|
||||||
const response: Response = await callApi({ |
|
||||||
config, |
|
||||||
url: `http://136.243.17.103:8888/${sportName}/matches/${matchId}/teams/stats?group_num=0${isUndefined(second) ? '' : `&second=${second}`}`, |
|
||||||
}) |
|
||||||
|
|
||||||
if (response.error) Promise.reject(response) |
|
||||||
|
|
||||||
return Promise.resolve(response.data || {}) |
|
||||||
} |
|
||||||
Loading…
Reference in new issue