diff --git a/public/images/sortUp.svg b/public/images/sortUp.svg
new file mode 100644
index 00000000..0f51e40c
--- /dev/null
+++ b/public/images/sortUp.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/config/routes.tsx b/src/config/routes.tsx
index 178b420b..130329b6 100644
--- a/src/config/routes.tsx
+++ b/src/config/routes.tsx
@@ -23,9 +23,16 @@ const VIEWS_APIS = {
staging: 'https://views.test.insports.tv',
}
+const STATS_APIS = {
+ preproduction: 'https://statistic.insports.tv',
+ production: 'https://statistic.insports.tv',
+ staging: 'https://statistic-stage.insports.tv',
+}
+
const env = isProduction ? ENV : readSelectedApi() ?? ENV
export const VIEWS_API = VIEWS_APIS[env]
export const AUTH_SERVICE = APIS[env].auth
export const API_ROOT = APIS[env].api
export const DATA_URL = `${API_ROOT}/data`
+export const STATS_API_URL = STATS_APIS[env]
diff --git a/src/features/MatchSidePlaylists/components/PlayersTable/hooks/index.tsx b/src/features/MatchSidePlaylists/components/PlayersTable/hooks/index.tsx
index 537e480a..554afdef 100644
--- a/src/features/MatchSidePlaylists/components/PlayersTable/hooks/index.tsx
+++ b/src/features/MatchSidePlaylists/components/PlayersTable/hooks/index.tsx
@@ -5,17 +5,20 @@ import { usePlayers } from './usePlayers'
import { useTable } from './useTable'
export const usePlayersTable = ({ teamId }: PlayersTableProps) => {
- const [sortCondition, setSortCondition] = useState({ dir: 'asc', paramId: null })
+ const [sortCondition, setSortCondition] = useState({
+ clicksCount: 0,
+ dir: 'asc',
+ paramId: null,
+ })
const {
- getFullName,
+ getPlayerName,
getPlayerParams,
players,
} = usePlayers({ sortCondition, teamId })
const {
containerRef,
- firstColumnWidth,
getDisplayedValue,
handleScroll,
handleSortClick,
@@ -36,9 +39,8 @@ export const usePlayersTable = ({ teamId }: PlayersTableProps) => {
return {
containerRef,
- firstColumnWidth,
getDisplayedValue,
- getFullName,
+ getPlayerName,
getPlayerParams,
handleScroll,
handleSortClick,
diff --git a/src/features/MatchSidePlaylists/components/PlayersTable/types.tsx b/src/features/MatchSidePlaylists/components/PlayersTable/types.tsx
index 85b9d054..7eae9005 100644
--- a/src/features/MatchSidePlaylists/components/PlayersTable/types.tsx
+++ b/src/features/MatchSidePlaylists/components/PlayersTable/types.tsx
@@ -1,8 +1,12 @@
+import { TCircleAnimation } from 'features/CircleAnimationBar'
+
export type PlayersTableProps = {
+ circleAnimation?: TCircleAnimation,
teamId: number,
}
export type SortCondition = {
+ clicksCount: number,
dir: 'asc' | 'desc',
paramId: number | null,
}
diff --git a/src/features/MatchSidePlaylists/components/TabPlayers/index.tsx b/src/features/MatchSidePlaylists/components/TabPlayers/index.tsx
index bd8244ac..f65c4b88 100644
--- a/src/features/MatchSidePlaylists/components/TabPlayers/index.tsx
+++ b/src/features/MatchSidePlaylists/components/TabPlayers/index.tsx
@@ -1,5 +1,3 @@
-import isEmpty from 'lodash/isEmpty'
-
import type { Playlists, PlaylistOption } from 'features/MatchPage/types'
import type { MatchInfo } from 'requests'
@@ -17,15 +15,11 @@ export const TabPlayers = ({
playlists,
profile,
selectedPlaylist,
-}: Props) => {
- if (isEmpty(playlists.players.team1)) return null
-
- return (
-
- )
-}
+}: Props) => (
+
+)
diff --git a/src/features/MatchSidePlaylists/components/TabStats/hooks.tsx b/src/features/MatchSidePlaylists/components/TabStats/hooks.tsx
index 1d621ce3..ea8df099 100644
--- a/src/features/MatchSidePlaylists/components/TabStats/hooks.tsx
+++ b/src/features/MatchSidePlaylists/components/TabStats/hooks.tsx
@@ -2,6 +2,8 @@ import { useEffect, useState } from 'react'
import isEmpty from 'lodash/isEmpty'
+import { useTooltip } from 'hooks'
+
import { useMatchPageStore } from 'features/MatchPage/store'
import { StatsType, Tabs } from './config'
@@ -12,15 +14,23 @@ export const useTabStats = () => {
const {
isEmptyPlayersStats,
profile: matchProfile,
- setStatsType,
statsType,
teamsStats,
+ toggleStatsType,
} = useMatchPageStore()
+ const {
+ isTooltipShown,
+ onMouseLeave,
+ onMouseOver,
+ tooltipStyle,
+ tooltipText,
+ } = useTooltip()
+
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 switchButtonTooltipLexic = isFinalStatsType ? 'display_all_stats' : 'display_stats_according_to_video'
const isVisibleTeamsTab = !isEmpty(teamsStats)
const isVisibleTeam1PlayersTab = Boolean(
@@ -30,12 +40,6 @@ export const useTabStats = () => {
matchProfile && !isEmptyPlayersStats(matchProfile.team2.id),
)
- const toggleStatsType = () => {
- const newStatsType = isFinalStatsType ? StatsType.CURRENT_STATS : StatsType.FINAL_STATS
-
- setStatsType(newStatsType)
- }
-
useEffect(() => {
switch (true) {
case isVisibleTeamsTab:
@@ -56,13 +60,18 @@ export const useTabStats = () => {
return {
isFinalStatsType,
+ isTooltipShown,
isVisibleTeam1PlayersTab,
isVisibleTeam2PlayersTab,
isVisibleTeamsTab,
+ onMouseLeave,
+ onMouseOver,
selectedTab,
setSelectedTab,
+ switchButtonTooltipLexic,
switchTitleLexic,
toggleStatsType,
- tooltipLexic,
+ tooltipStyle,
+ tooltipText,
}
}
diff --git a/src/features/MatchSidePlaylists/components/TabStats/index.tsx b/src/features/MatchSidePlaylists/components/TabStats/index.tsx
index d5b20d74..290139a6 100644
--- a/src/features/MatchSidePlaylists/components/TabStats/index.tsx
+++ b/src/features/MatchSidePlaylists/components/TabStats/index.tsx
@@ -1,11 +1,17 @@
-import { isMobileDevice } from 'config/userAgent'
+import type { ComponentProps } from 'react'
+import { createPortal } from 'react-dom'
+
+import { isMobileDevice } from 'config'
import { getTeamAbbr } from 'helpers'
-import { Tooltip } from 'features/Tooltip'
+import { useModalRoot } from 'hooks'
+
import { T9n } from 'features/T9n'
import { useMatchPageStore } from 'features/MatchPage/store'
import { Name } from 'features/Name'
+import { TCircleAnimation, TSetCircleAnimation } from 'features/CircleAnimationBar'
+import { useLexicsStore } from 'features/LexicsStore'
import { Tabs } from './config'
import { useTabStats } from './hooks'
@@ -20,27 +26,44 @@ import {
Switch,
SwitchTitle,
SwitchButton,
+ Tooltip,
+ TabTitle,
} from './styled'
const tabPanes = {
[Tabs.TEAMS]: TeamsStatsTable,
- [Tabs.TEAM1]: PlayersTable,
- [Tabs.TEAM2]: PlayersTable,
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ [Tabs.TEAM1]: (props: ComponentProps) => ,
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ [Tabs.TEAM2]: (props: ComponentProps) => ,
}
-export const TabStats = () => {
+type Props = {
+ circleAnimation?: TCircleAnimation,
+ setCircleAnimation?: TSetCircleAnimation,
+}
+
+export const TabStats = ({ circleAnimation, setCircleAnimation }: Props) => {
const {
isFinalStatsType,
+ isTooltipShown,
isVisibleTeam1PlayersTab,
isVisibleTeam2PlayersTab,
isVisibleTeamsTab,
+ onMouseLeave,
+ onMouseOver,
selectedTab,
setSelectedTab,
+ switchButtonTooltipLexic,
switchTitleLexic,
toggleStatsType,
- tooltipLexic,
+ tooltipStyle,
+ tooltipText,
} = useTabStats()
const { profile: matchProfile } = useMatchPageStore()
+ const { suffix, translate } = useLexicsStore()
+
+ const modalRoot = useModalRoot()
const TabPane = tabPanes[selectedTab]
@@ -57,7 +80,9 @@ export const TabStats = () => {
aria-pressed={selectedTab === Tabs.TEAMS}
onClick={() => setSelectedTab(Tabs.TEAMS)}
>
-
+
+
+
)}
{isVisibleTeam1PlayersTab && (
@@ -65,11 +90,25 @@ export const TabStats = () => {
aria-pressed={selectedTab === Tabs.TEAM1}
onClick={() => setSelectedTab(Tabs.TEAM1)}
>
-
+
+
+
)}
{isVisibleTeam2PlayersTab && (
@@ -77,27 +116,56 @@ export const TabStats = () => {
aria-pressed={selectedTab === Tabs.TEAM2}
onClick={() => setSelectedTab(Tabs.TEAM2)}
>
-
+
+
+
)}
- {!isMobileDevice && }
-
+ onMouseOver={isMobileDevice
+ ? undefined
+ : onMouseOver({
+ anchorId: 'switchButton',
+ horizontalPosition: 'right',
+ tooltipText: translate(switchButtonTooltipLexic),
+ })}
+ onMouseLeave={isMobileDevice ? undefined : onMouseLeave}
+ />
+ {isTooltipShown && modalRoot.current && createPortal(
+
+ {tooltipText}
+ ,
+ modalRoot.current,
+ )}
)
}
diff --git a/src/features/MatchSidePlaylists/components/TabStats/styled.tsx b/src/features/MatchSidePlaylists/components/TabStats/styled.tsx
index 13318a33..94355c8d 100644
--- a/src/features/MatchSidePlaylists/components/TabStats/styled.tsx
+++ b/src/features/MatchSidePlaylists/components/TabStats/styled.tsx
@@ -8,29 +8,51 @@ export const Container = styled.div``
export const Header = styled.div`
display: flex;
justify-content: space-between;
- margin-bottom: 23px;
+ margin-bottom: 6px;
`
export const TabList = styled.div.attrs({ role: 'tablist' })`
display: flex;
`
+export const Tooltip = styled(TooltipWrapper)`
+ display: block;
+ padding: 2px 10px;
+ border-radius: 6px;
+ transform: none;
+ font-size: 11px;
+ line-height: 1;
+ color: ${({ theme }) => theme.colors.black};
+ z-index: 999;
+
+ ::before {
+ display: none;
+ }
+`
+
+export const TabTitle = styled.span`
+ color: ${({ theme }) => theme.colors.white};
+ opacity: 0.4;
+`
+
export const Tab = styled.button.attrs({ role: 'tab' })`
+ position: relative;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px 10px;
font-size: 12px;
- color: ${({ theme }) => theme.colors.white};
- opacity: 0.4;
cursor: pointer;
border: none;
background: none;
border-bottom: 2px solid transparent;
&[aria-pressed="true"] {
- opacity: 1;
- border-color: currentColor;
+ border-color: ${({ theme }) => theme.colors.white};
+
+ ${TabTitle} {
+ opacity: 1;
+ }
}
`
@@ -49,7 +71,6 @@ type SwitchButtonProps = {
}
export const SwitchButton = styled.button`
- position: relative;
width: 20px;
height: 7px;
margin-left: 5px;
@@ -59,27 +80,6 @@ export const SwitchButton = styled.button`
border: 1px solid ${({ theme }) => theme.colors.white};
cursor: pointer;
- ${TooltipWrapper} {
- left: auto;
- right: 0;
- top: 15px;
- padding: 2px 10px;
- border-radius: 6px;
- transform: none;
- font-size: 11px;
- line-height: 1;
-
- ::before {
- display: none;
- }
- }
-
- :hover {
- ${TooltipWrapper} {
- display: block;
- }
- }
-
${({ isFinalStatsType, theme }) => (!isFinalStatsType
? css`
background-image: linear-gradient(
diff --git a/src/features/MatchSidePlaylists/components/TeamsStatsTable/styled.tsx b/src/features/MatchSidePlaylists/components/TeamsStatsTable/styled.tsx
index 39b3a3c7..9aa59d15 100644
--- a/src/features/MatchSidePlaylists/components/TeamsStatsTable/styled.tsx
+++ b/src/features/MatchSidePlaylists/components/TeamsStatsTable/styled.tsx
@@ -1,13 +1,27 @@
import styled, { css } from 'styled-components/macro'
import { Name } from 'features/Name'
+import { customScrollbar } from 'features/Common'
-export const Container = styled.div`
+export const Container = styled.div``
+
+export const TableWrapper = styled.div`
width: 100%;
+ max-height: calc(100vh - 203px);
+ overflow: auto;
font-size: 11px;
- overflow: hidden;
border-radius: 5px;
background-color: #333333;
+
+ ${customScrollbar}
+`
+
+export const Table = styled.table`
+ width: 100%;
+ border-spacing: 0;
+ border-collapse: collapse;
+ letter-spacing: -0.078px;
+ table-layout: fixed;
`
export const TeamShortName = styled(Name)`
@@ -18,16 +32,44 @@ export const TeamShortName = styled(Name)`
opacity: 0.5;
`
-export const Row = styled.div`
- display: flex;
- justify-content: space-between;
- align-items: center;
+export const Cell = styled.td`
height: 45px;
- padding: 0 12px;
border-bottom: 0.5px solid rgba(255, 255, 255, 0.5);
+ background-color: #333333;
+
+ :nth-child(2) {
+ text-align: center;
+ }
+
+ :first-child, :last-child {
+ width: 32px;
+ }
+
+ :first-child {
+ padding-left: 12px;
+ }
:last-child {
- border-bottom: none;
+ text-align: right;
+ padding-right: 12px;
+ }
+`
+
+export const Row = styled.tr`
+ :last-child:not(:first-child) {
+ ${Cell} {
+ border-bottom: none;
+ }
+ }
+`
+
+export const Header = styled.thead`
+ position: sticky;
+ top: 0;
+ z-index: 1;
+
+ ${Cell} {
+ background-color: #292929;
}
`
diff --git a/src/features/MatchSidePlaylists/components/TeamsStatsTable/types.tsx b/src/features/MatchSidePlaylists/components/TeamsStatsTable/types.tsx
new file mode 100644
index 00000000..7bfc8c82
--- /dev/null
+++ b/src/features/MatchSidePlaylists/components/TeamsStatsTable/types.tsx
@@ -0,0 +1,6 @@
+import { TCircleAnimation, TSetCircleAnimation } from 'features/CircleAnimationBar'
+
+export type Props = {
+ circleAnimation?: TCircleAnimation,
+ setCircleAnimation?: TSetCircleAnimation,
+}
diff --git a/src/features/MatchSidePlaylists/hooks.tsx b/src/features/MatchSidePlaylists/hooks.tsx
index 17e889c5..72296124 100644
--- a/src/features/MatchSidePlaylists/hooks.tsx
+++ b/src/features/MatchSidePlaylists/hooks.tsx
@@ -61,7 +61,7 @@ export const useMatchSidePlaylists = () => {
isWatchTabVisible,
isEventTabVisible,
isPlayersTabVisible,
- // isStatsTabVisible,
+ isStatsTabVisible,
]).length < 4
useEffect(() => {
@@ -75,14 +75,14 @@ export const useMatchSidePlaylists = () => {
case isPlayersTabVisible:
setSelectedTab(Tabs.PLAYERS)
break
- // case isStatsTabVisible:
- // setSelectedTab(Tabs.STATS)
- // break
+ case isStatsTabVisible:
+ setSelectedTab(Tabs.STATS)
+ break
}
}, [
isEventTabVisible,
isPlayersTabVisible,
- // isStatsTabVisible,
+ isStatsTabVisible,
isWatchTabVisible,
])
diff --git a/src/features/Name/index.tsx b/src/features/Name/index.tsx
index a93bc2ce..fcbbe3dd 100644
--- a/src/features/Name/index.tsx
+++ b/src/features/Name/index.tsx
@@ -10,6 +10,7 @@ export type ObjectWithName = {
type Props = {
className?: string,
+ id?: string,
nameObj: ObjectWithName,
prefix?: string,
}
@@ -42,9 +43,17 @@ export const useName = (
export const Name = ({
className,
+ id,
nameObj,
prefix,
}: Props) => {
const name = useName(nameObj, prefix)
- return {name}
+ return (
+
+ {name}
+
+ )
}
diff --git a/src/features/T9n/index.tsx b/src/features/T9n/index.tsx
index 85140c4f..35c3ea48 100644
--- a/src/features/T9n/index.tsx
+++ b/src/features/T9n/index.tsx
@@ -7,6 +7,7 @@ const Text = styled.span``
type Props = {
className?: string,
+ id?: string,
onClick?: () => void,
t: LexicsId,
values?: Values,
@@ -14,6 +15,7 @@ type Props = {
export const T9n = ({
className,
+ id,
onClick,
t,
values,
@@ -22,6 +24,7 @@ export const T9n = ({
return (
diff --git a/src/features/Tooltip/index.tsx b/src/features/Tooltip/index.tsx
index a436eb2d..b599709d 100644
--- a/src/features/Tooltip/index.tsx
+++ b/src/features/Tooltip/index.tsx
@@ -34,7 +34,10 @@ export const Tooltip = ({
lexic,
}: Props) => (
-
+
{children}
diff --git a/src/hooks/index.tsx b/src/hooks/index.tsx
index 8219ac0e..6e2f4ec7 100644
--- a/src/hooks/index.tsx
+++ b/src/hooks/index.tsx
@@ -5,3 +5,5 @@ export * from './useInterval'
export * from './useEventListener'
export * from './useObjectState'
export * from './usePageParams'
+export * from './useTooltip'
+export * from './useModalRoot'
diff --git a/src/requests/getMatchParticipants.tsx b/src/requests/getMatchParticipants.tsx
index 645c3c03..2869470f 100644
--- a/src/requests/getMatchParticipants.tsx
+++ b/src/requests/getMatchParticipants.tsx
@@ -1,6 +1,6 @@
import isUndefined from 'lodash/isUndefined'
-import { SportTypes } from 'config'
+import { SportTypes, STATS_API_URL } from 'config'
import { callApi } from 'helpers'
@@ -23,6 +23,7 @@ export type Player = {
national_shirt_num: number,
nickname_eng: string | null,
nickname_rus: string | null,
+ num: number | null,
weight: number | null,
}
@@ -56,7 +57,7 @@ export const getMatchParticipants = async ({
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}`}`,
+ url: `${STATS_API_URL}/ask/participants?sport_id=${sportType}&match_id=${matchId}${isUndefined(second) ? '' : `&second=${second}`}`,
})
if (response.error) Promise.reject(response)
diff --git a/src/requests/getPlayersStats.tsx b/src/requests/getPlayersStats.tsx
index 3fb5d93f..7bae6058 100644
--- a/src/requests/getPlayersStats.tsx
+++ b/src/requests/getPlayersStats.tsx
@@ -2,6 +2,8 @@ import isUndefined from 'lodash/isUndefined'
import { callApi } from 'helpers'
+import { STATS_API_URL } from 'config'
+
export type PlayerParam = {
clickable: boolean,
data_type: string,
@@ -45,7 +47,7 @@ export const getPlayersStats = async ({
const response: Response = await callApi({
config,
- url: `http://136.243.17.103:8888/${sportName}/matches/${matchId}/teams/${teamId}/players/stats${isUndefined(second) ? '' : `?second=${second}`}`,
+ url: `${STATS_API_URL}/${sportName}/matches/${matchId}/teams/${teamId}/players/stats${isUndefined(second) ? '' : `?second=${second}`}`,
})
if (response.error) Promise.reject(response)