diff --git a/src/config/lexics/indexLexics.tsx b/src/config/lexics/indexLexics.tsx index e44e4d09..545eea28 100644 --- a/src/config/lexics/indexLexics.tsx +++ b/src/config/lexics/indexLexics.tsx @@ -9,8 +9,12 @@ const matchPopupLexics = { apply: 13491, choose_fav_team: 19776, commentators: 15424, + current_stats: 19592, + display_all_stats: 19932, + display_stats_according_to_video: 19931, episode_duration: 13410, events: 1020, + final_stats: 19591, from_end_match: 15396, from_price: 3992, from_start_match: 15395, @@ -160,6 +164,7 @@ export const indexLexics = { no_match_access_body: 13419, no_match_access_title: 13418, player: 14975, + players: 164, players_video: 13032, privacy_policy_and_statement: 15404, round_highilights: 13050, diff --git a/src/features/MatchPage/store/hooks/index.tsx b/src/features/MatchPage/store/hooks/index.tsx index 8b472265..8320833d 100644 --- a/src/features/MatchPage/store/hooks/index.tsx +++ b/src/features/MatchPage/store/hooks/index.tsx @@ -65,10 +65,12 @@ export const useMatchPage = () => { const { events, + fetchTeamsStats, handlePlaylistClick, matchPlaylists, selectedPlaylist, setFullMatchPlaylistDuration, + teamsStats, } = useMatchData(matchProfile) const profile = matchProfile @@ -156,6 +158,7 @@ export const useMatchPage = () => { countOfFilters, disablePlayingEpisodes, events, + fetchTeamsStats, filteredEvents, handlePlaylistClick, hideProfileCard, @@ -183,6 +186,7 @@ export const useMatchPage = () => { setUnreversed, setWatchAllEpisodesTimer, showProfileCard, + teamsStats, toggleActiveEvents, toggleActivePlayers, togglePopup, diff --git a/src/features/MatchPage/store/hooks/useMatchData.tsx b/src/features/MatchPage/store/hooks/useMatchData.tsx index 4cee0488..3f732f7c 100644 --- a/src/features/MatchPage/store/hooks/useMatchData.tsx +++ b/src/features/MatchPage/store/hooks/useMatchData.tsx @@ -6,7 +6,7 @@ import { import debounce from 'lodash/debounce' -import { MatchInfo } from 'requests/getMatchInfo' +import type { MatchInfo } from 'requests/getMatchInfo' import { usePageParams } from 'hooks/usePageParams' import { useInterval } from 'hooks/useInterval' @@ -16,6 +16,7 @@ import { useMatchPopupStore } from 'features/MatchPopup' import { useMatchPlaylists } from './useMatchPlaylists' import { useEvents } from './useEvents' +import { useTeamsStats } from './useTeamsStats' const MATCH_DATA_POLL_INTERVAL = 60000 const MATCH_PLAYLISTS_DELAY = 5000 @@ -33,6 +34,7 @@ export const useMatchData = (profile: MatchInfo) => { setSelectedPlaylist, } = useMatchPlaylists(profile) const { events, fetchMatchEvents } = useEvents() + const { fetchTeamsStats, teamsStats } = useTeamsStats(profile) const fetchPlaylistsDebounced = useMemo( () => debounce(fetchMatchPlaylists, MATCH_PLAYLISTS_DELAY), @@ -92,9 +94,11 @@ export const useMatchData = (profile: MatchInfo) => { return { events, + fetchTeamsStats, handlePlaylistClick, matchPlaylists, selectedPlaylist, setFullMatchPlaylistDuration, + teamsStats, } } diff --git a/src/features/MatchPage/store/hooks/useTeamsStats.tsx b/src/features/MatchPage/store/hooks/useTeamsStats.tsx new file mode 100644 index 00000000..dd4a979a --- /dev/null +++ b/src/features/MatchPage/store/hooks/useTeamsStats.tsx @@ -0,0 +1,58 @@ +import { + useEffect, + useState, + useMemo, + useCallback, +} from 'react' + +import flatMap from 'lodash/flatMap' +import reduce from 'lodash/reduce' +import includes from 'lodash/includes' + +import type { MatchInfo } from 'requests' +import { getTeamsStats, TeamStatItem } from 'requests' + +import { usePageParams } from 'hooks/usePageParams' + +import { useLexicsConfig } from 'features/LexicsStore' + +export const useTeamsStats = (matchProfile: MatchInfo) => { + const [teamsStats, setTeamsStats] = useState<{ + [teamId: string]: Array, + }>({}) + + const { profileId: matchId, sportName } = usePageParams() + + const lexics = useMemo(() => reduce>( + flatMap(teamsStats), + (acc, curr) => { + if (curr.param1?.lexic && !includes(acc, curr.param1.lexic)) { + acc.push(curr.param1.lexic) + } + + return acc + }, + [], + ), [teamsStats]) + + useLexicsConfig(lexics) + + const fetchTeamsStats = useCallback((second?: number) => { + if (!sportName) return + + getTeamsStats({ + matchId, + second, + sportName, + }).then(setTeamsStats) + }, [matchId, sportName]) + + useEffect(() => { + fetchTeamsStats() + }, [fetchTeamsStats]) + + return { + fetchTeamsStats, + teamsStats, + } +} diff --git a/src/features/MatchSidePlaylists/components/PlayersPlaylists/index.tsx b/src/features/MatchSidePlaylists/components/PlayersPlaylists/index.tsx index d05ac36e..22b69298 100644 --- a/src/features/MatchSidePlaylists/components/PlayersPlaylists/index.tsx +++ b/src/features/MatchSidePlaylists/components/PlayersPlaylists/index.tsx @@ -15,12 +15,10 @@ import type { } from 'features/MatchPage/types' import { Name } from 'features/Name' -import { T9n } from 'features/T9n' import { isEqual } from '../../helpers' import { PlayButton } from '../PlayButton' -import { BlockTitle } from '../../styled' import { Wrapper, List, @@ -58,9 +56,6 @@ export const PlayersPlaylists = ({ return ( - - - ` position: relative; border: none; - height: 34px; padding: 0; background-color: transparent; font-size: 12px; diff --git a/src/features/MatchSidePlaylists/components/PlayersTable/config.tsx b/src/features/MatchSidePlaylists/components/PlayersTable/config.tsx new file mode 100644 index 00000000..095cfcbe --- /dev/null +++ b/src/features/MatchSidePlaylists/components/PlayersTable/config.tsx @@ -0,0 +1 @@ +export const CELL_WIDTH = 47 diff --git a/src/features/MatchSidePlaylists/components/PlayersTable/hooks.tsx b/src/features/MatchSidePlaylists/components/PlayersTable/hooks.tsx new file mode 100644 index 00000000..811ddda6 --- /dev/null +++ b/src/features/MatchSidePlaylists/components/PlayersTable/hooks.tsx @@ -0,0 +1,61 @@ +import type { SyntheticEvent } from 'react' +import { + useRef, + useState, + useEffect, +} from 'react' + +import { isMobileDevice } from 'config/userAgent' + +import { CELL_WIDTH } from './config' + +export const usePlayersTable = () => { + const containerRef = useRef(null) + const tableWrapperRef = useRef(null) + + const [showLeftArrow, setShowLeftArrow] = useState(false) + const [showRightArrow, setShowRightArrow] = useState(false) + + const cellWidth = isMobileDevice + ? ((containerRef.current?.clientWidth || 0) - 98) / 4 + : CELL_WIDTH + + const slideLeft = () => tableWrapperRef.current!.scrollBy(-cellWidth, 0) + const slideRight = () => tableWrapperRef.current!.scrollBy(cellWidth, 0) + + const handleScroll = (e: SyntheticEvent) => { + const { + clientWidth, + scrollLeft, + scrollWidth, + } = e.currentTarget + + const scrollRight = scrollWidth - (scrollLeft + clientWidth) + + setShowLeftArrow(scrollLeft > 1) + setShowRightArrow(scrollRight > 1) + } + + useEffect(() => { + const { + clientWidth = 0, + scrollLeft = 0, + scrollWidth = 0, + } = tableWrapperRef.current || {} + + const scrollRight = scrollWidth - (scrollLeft + clientWidth) + + setShowRightArrow(scrollRight > 1) + }, []) + + return { + cellWidth, + containerRef, + handleScroll, + showLeftArrow, + showRightArrow, + slideLeft, + slideRight, + tableWrapperRef, + } +} diff --git a/src/features/MatchSidePlaylists/components/PlayersTable/index.tsx b/src/features/MatchSidePlaylists/components/PlayersTable/index.tsx index 46520e1b..0be29a9c 100644 --- a/src/features/MatchSidePlaylists/components/PlayersTable/index.tsx +++ b/src/features/MatchSidePlaylists/components/PlayersTable/index.tsx @@ -1,4 +1,7 @@ +import { usePlayersTable } from './hooks' import { + Container, + TableWrapper, Table, Thead, Th, @@ -7,237 +10,1721 @@ import { Td, PlayerNum, ParamShortTitle, + ArrowButtonRight, + ArrowButtonLeft, + Arrow, } from './styled' -export const PlayersTable = () => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Min - - Pt - - Reb - - Ass - - To -
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
57 Selikhov9712214
-) +export const PlayersTable = () => { + const { + cellWidth, + containerRef, + handleScroll, + showLeftArrow, + showRightArrow, + slideLeft, + slideRight, + tableWrapperRef, + } = usePlayersTable() + + return ( + + + {showLeftArrow && ( + + + + )} + {showRightArrow && ( + + + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Min + + Pt + + Reb + + Ass + + To + + Min + + Pt + + Reb + + Ass + + To + + Min + + Pt + + Reb + + Ass + + + To + + + Min + + Pt + + Reb + + Ass + + To +
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
57 Selikhov9712214971221497122149712214
+
+
+ ) +} diff --git a/src/features/MatchSidePlaylists/components/PlayersTable/styled.tsx b/src/features/MatchSidePlaylists/components/PlayersTable/styled.tsx index 3d88c1f6..303332dd 100644 --- a/src/features/MatchSidePlaylists/components/PlayersTable/styled.tsx +++ b/src/features/MatchSidePlaylists/components/PlayersTable/styled.tsx @@ -1,16 +1,33 @@ import styled, { css } from 'styled-components/macro' +import { isMobileDevice } from 'config/userAgent' + import { customScrollbar } from 'features/Common' +import { + ArrowButton as ArrowButtonBase, + Arrow as ArrowBase, +} from 'features/HeaderFilters/components/DateFilter/styled' + +import { CELL_WIDTH } from './config' + +export const Container = styled.div` + position: relative; +` + +export const TableWrapper = styled.div` + max-height: calc(100vh - 235px); + border-radius: 5px; + overflow-x: auto; + scroll-behavior: smooth; + ${customScrollbar} +` export const Table = styled.table` width: 100%; border-radius: 5px; border-collapse: collapse; letter-spacing: -0.078px; - background-color: #333333; table-layout: fixed; - - ${customScrollbar} ` export const Thead = styled.thead` @@ -20,21 +37,33 @@ export const Thead = styled.thead` type ThProps = { sorted?: boolean, + width?: number, } -export const Th = styled.th` +export const Th = styled.th.attrs({ tabIndex: 0 })` + position: sticky; + left: 0; + top: 0; + width: ${({ width }) => width || CELL_WIDTH}px; font-size: 11px; color: ${({ theme }) => theme.colors.white}; text-transform: uppercase; + cursor: pointer; + background-color: #333333; + z-index: 2; :first-child { - width: 115px; + width: 90px; + z-index: 3; + cursor: default; } ${({ sorted }) => (sorted ? '' : css` - opacity: 0.5; + ${ParamShortTitle} { + opacity: 0.5; + } `)} ` @@ -56,18 +85,26 @@ type TdProps = { sorted?: boolean, } -export const Td = styled.td` +export const Td = styled.td.attrs(({ clickable }: TdProps) => ({ + ...clickable && { tabIndex: 0 }, +}))` font-size: 11px; text-align: center; color: ${({ clickable, theme }) => (clickable ? '#5EB2FF' : theme.colors.white)}; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + background-color: #333333; :first-child { + position: sticky; + left: 0; + z-index: 1; padding-left: 13px; text-align: left; color: ${({ theme }) => theme.colors.white}; } - ${({ sorted }) => (sorted ? css` font-weight: bold; @@ -84,3 +121,29 @@ export const Td = styled.td` export const PlayerNum = styled.span` color: rgba(255, 255, 255, 0.5); ` + +const ArrowButton = styled(ArrowButtonBase)` + position: absolute; + margin-top: 2px; + z-index: 4; + + ${isMobileDevice + ? css` + height: 45px; + margin-top: 0; + ` + : ''}; +` + +export const ArrowButtonRight = styled(ArrowButton)` + right: 0; +` + +export const ArrowButtonLeft = styled(ArrowButton)` + left: 75px; +` + +export const Arrow = styled(ArrowBase)` + width: 10px; + height: 10px; +` diff --git a/src/features/MatchSidePlaylists/components/TabStats/config.tsx b/src/features/MatchSidePlaylists/components/TabStats/config.tsx index 099a117f..3c14e7ff 100644 --- a/src/features/MatchSidePlaylists/components/TabStats/config.tsx +++ b/src/features/MatchSidePlaylists/components/TabStats/config.tsx @@ -3,3 +3,8 @@ export enum Tabs { TEAM1, TEAM2, } + +export enum StatsType { + FINAL_STATS, + CURRENT_STATS, +} diff --git a/src/features/MatchSidePlaylists/components/TabStats/hooks.tsx b/src/features/MatchSidePlaylists/components/TabStats/hooks.tsx new file mode 100644 index 00000000..f481f1ec --- /dev/null +++ b/src/features/MatchSidePlaylists/components/TabStats/hooks.tsx @@ -0,0 +1,32 @@ +import { useState } from 'react' + +import { useMatchPageStore } from 'features/MatchPage/store' + +import { StatsType, Tabs } from './config' + +export const useTabStats = () => { + const [statsType, setStatsType] = useState(StatsType.FINAL_STATS) + const [selectedTab, setSelectedTab] = useState(Tabs.TEAMS) + + const { fetchTeamsStats, teamsStats } = useMatchPageStore() + + const isFinalStatsType = statsType === StatsType.FINAL_STATS + + const switchTitleLexic = isFinalStatsType ? 'final_stats' : 'current_stats' + const tooltipLexic = isFinalStatsType ? 'display_stats_according_to_video' : 'display_all_stats' + + const toggleStatsType = () => { + const newStatsType = isFinalStatsType ? StatsType.CURRENT_STATS : StatsType.FINAL_STATS + + setStatsType(newStatsType) + } + + return { + isFinalStatsType, + selectedTab, + setSelectedTab, + switchTitleLexic, + toggleStatsType, + tooltipLexic, + } +} diff --git a/src/features/MatchSidePlaylists/components/TabStats/index.tsx b/src/features/MatchSidePlaylists/components/TabStats/index.tsx index c43592bb..1487e01f 100644 --- a/src/features/MatchSidePlaylists/components/TabStats/index.tsx +++ b/src/features/MatchSidePlaylists/components/TabStats/index.tsx @@ -1,5 +1,8 @@ import { Tooltip } from 'features/Tooltip' +import { T9n } from 'features/T9n' +import { Tabs } from './config' +import { useTabStats } from './hooks' import { PlayersTable } from '../PlayersTable' import { TeamsStats } from '../TeamsStats' @@ -13,22 +16,58 @@ import { SwitchButton, } from './styled' -export const TabStats = () => ( - -
- - Teams - DIN - SPA - - - Final Stats - - - - -
- - {/* */} -
-) +const tabPanes = { + [Tabs.TEAMS]: TeamsStats, + [Tabs.TEAM1]: PlayersTable, + [Tabs.TEAM2]: PlayersTable, +} + +export const TabStats = () => { + const { + isFinalStatsType, + selectedTab, + setSelectedTab, + switchTitleLexic, + toggleStatsType, + tooltipLexic, + } = useTabStats() + + const TabPane = tabPanes[selectedTab] + + return ( + +
+ + setSelectedTab(Tabs.TEAMS)} + > + + + {/* setSelectedTab(Tabs.TEAM1)} + > + DIN + */} + {/* setSelectedTab(Tabs.TEAM2)} + > + SPA + */} + + + + + + + +
+ +
+ ) +} diff --git a/src/features/MatchSidePlaylists/components/TabStats/styled.tsx b/src/features/MatchSidePlaylists/components/TabStats/styled.tsx index f2f58203..477a56c0 100644 --- a/src/features/MatchSidePlaylists/components/TabStats/styled.tsx +++ b/src/features/MatchSidePlaylists/components/TabStats/styled.tsx @@ -1,6 +1,7 @@ import styled, { css } from 'styled-components/macro' import { TooltipWrapper } from 'features/Tooltip' +import { T9n } from 'features/T9n' export const Container = styled.div`` @@ -14,42 +15,40 @@ export const TabList = styled.div.attrs({ role: 'tablist' })` display: flex; ` -type TabProps = { - selected?: boolean, -} - -export const Tab = styled.div.attrs(({ selected }: TabProps) => ({ - 'aria-pressed': selected, - role: 'tab', -}))` +export const Tab = styled.button.attrs({ role: 'tab' })` display: flex; justify-content: space-between; align-items: center; - padding: 0 15px 10px; + padding: 0 10px 10px; font-size: 12px; color: ${({ theme }) => theme.colors.white}; - opacity: ${({ selected }) => (selected ? '1' : '0.4')}; + opacity: 0.4; cursor: pointer; + border: none; + background: none; border-bottom: 2px solid transparent; - - ${({ selected, theme }) => (selected - ? css` - border-color: ${theme.colors.white}; - ` - : '')} + &[aria-pressed="true"] { + opacity: 1; + border-color: currentColor; + } ` export const Switch = styled.div` display: flex; ` -export const SwitchTitle = styled.span` +export const SwitchTitle = styled(T9n)` font-size: 12px; color: ${({ theme }) => theme.colors.white}; + white-space: nowrap; ` -export const SwitchButton = styled.button` +type SwitchButtonProps = { + isFinalStatsType: boolean, +} + +export const SwitchButton = styled.button` position: relative; width: 20px; height: 7px; @@ -66,6 +65,8 @@ export const SwitchButton = styled.button` padding: 2px 10px; border-radius: 6px; transform: none; + font-size: 11px; + line-height: 1; ::before { display: none; @@ -78,7 +79,7 @@ export const SwitchButton = styled.button` } } - ${({ theme }) => (true // Позже будет добавлен пропс + ${({ isFinalStatsType, theme }) => (!isFinalStatsType ? css` background-image: linear-gradient( to right, diff --git a/src/features/MatchSidePlaylists/components/TeamsStats/styled.tsx b/src/features/MatchSidePlaylists/components/TeamsStats/styled.tsx index 222b9918..166f5c2f 100644 --- a/src/features/MatchSidePlaylists/components/TeamsStats/styled.tsx +++ b/src/features/MatchSidePlaylists/components/TeamsStats/styled.tsx @@ -1,13 +1,8 @@ import styled, { css } from 'styled-components/macro' -import { customScrollbar } from 'features/Common' - export const Container = styled.div` width: 100%; font-size: 11px; - background-color: #333333; - - ${customScrollbar} ` export const TeamShortName = styled.span` @@ -25,6 +20,7 @@ export const Row = styled.div` height: 45px; padding: 0 12px; border-bottom: 0.5px solid rgba(255, 255, 255, 0.5); + background-color: #333333; :last-child { border-bottom: none; diff --git a/src/features/MatchSidePlaylists/hooks.tsx b/src/features/MatchSidePlaylists/hooks.tsx index 689c6fe5..6a4b303c 100644 --- a/src/features/MatchSidePlaylists/hooks.tsx +++ b/src/features/MatchSidePlaylists/hooks.tsx @@ -5,6 +5,8 @@ import { } from 'react' import reduce from 'lodash/reduce' +import isEmpty from 'lodash/isEmpty' +import compact from 'lodash/compact' import { useMatchPageStore } from 'features/MatchPage/store' @@ -15,6 +17,7 @@ export const useMatchSidePlaylists = () => { closePopup, events, matchPlaylists: playlists, + teamsStats, } = useMatchPageStore() const [selectedTab, setSelectedTab] = useState(Tabs.WATCH) const isWatchTabVisible = useMemo(() => { @@ -34,6 +37,21 @@ export const useMatchSidePlaylists = () => { events.length > 0 ), [events]) + const isPlayersTabVisible = useMemo(() => ( + !isEmpty(playlists.players.team1) + ), [playlists.players.team1]) + + const isStatsTabVisible = useMemo(() => ( + !isEmpty(teamsStats) + ), [teamsStats]) + + const hasLessThanFourTabs = compact([ + isWatchTabVisible, + isEventTabVisible, + isPlayersTabVisible, + isStatsTabVisible, + ]).length < 4 + useEffect(() => { switch (true) { case isWatchTabVisible: @@ -42,16 +60,29 @@ export const useMatchSidePlaylists = () => { case isEventTabVisible: setSelectedTab(Tabs.EVENTS) break + case isPlayersTabVisible: + setSelectedTab(Tabs.PLAYERS) + break + case isStatsTabVisible: + setSelectedTab(Tabs.STATS) + break } - }, [isEventTabVisible, isWatchTabVisible]) + }, [ + isEventTabVisible, + isPlayersTabVisible, + isStatsTabVisible, + isWatchTabVisible, + ]) useEffect(() => { if (selectedTab !== Tabs.EVENTS) closePopup() }, [selectedTab, closePopup]) return { + hasLessThanFourTabs, isEventTabVisible, - isStatsTabVisible: true, + isPlayersTabVisible, + isStatsTabVisible, isWatchTabVisible, onTabClick: setSelectedTab, selectedTab, diff --git a/src/features/MatchSidePlaylists/index.tsx b/src/features/MatchSidePlaylists/index.tsx index 25b08a12..b3ae4097 100644 --- a/src/features/MatchSidePlaylists/index.tsx +++ b/src/features/MatchSidePlaylists/index.tsx @@ -42,8 +42,6 @@ type Props = { setCircleAnimation?: TSetCircleAnimation, } -const hasLessThanFourTabs = false - export const MatchSidePlaylists = ({ circleAnimation, onSelect, @@ -59,7 +57,9 @@ export const MatchSidePlaylists = ({ } = useMatchPageStore() const { + hasLessThanFourTabs, isEventTabVisible, + isPlayersTabVisible, isStatsTabVisible, isWatchTabVisible, onTabClick, @@ -108,7 +108,7 @@ export const MatchSidePlaylists = ({ {isWatchTabVisible ? ( onTabClick(Tabs.WATCH)} > @@ -117,25 +117,25 @@ export const MatchSidePlaylists = ({ ) : null} {isEventTabVisible ? ( onTabClick(Tabs.EVENTS)} > ) : null} - {isStatsTabVisible ? ( + {isPlayersTabVisible ? ( onTabClick(Tabs.PLAYERS)} > - + ) : null} {isStatsTabVisible ? ( onTabClick(Tabs.STATS)} > diff --git a/src/features/MatchSidePlaylists/styled.tsx b/src/features/MatchSidePlaylists/styled.tsx index 1a8a9e36..eec58e2d 100644 --- a/src/features/MatchSidePlaylists/styled.tsx +++ b/src/features/MatchSidePlaylists/styled.tsx @@ -43,7 +43,7 @@ export const TabsGroup = styled.div.attrs({ role: 'tablist' })` height: 40px; ${Tab} { - justify-content: initial; + justify-content: center; flex-direction: row; gap: 5px; } @@ -56,23 +56,18 @@ export const TabsGroup = styled.div.attrs({ role: 'tablist' })` : ''}; ` -type TabProps = { - selected?: boolean, -} - -export const Tab = styled.div.attrs(({ selected }: TabProps) => ({ - 'aria-pressed': selected, - role: 'tab', -}))` +export const Tab = styled.button.attrs({ role: 'tab' })` display: flex; flex-direction: column; justify-content: space-between; align-items: center; flex: 1; - opacity: ${({ selected }) => (selected ? '1' : '0.4')}; + opacity: 0.4; cursor: pointer; + border: none; + background: none; - :hover { + &[aria-pressed="true"], :hover { opacity: 1; } ` @@ -103,6 +98,7 @@ export const TabTitle = styled(T9n)` ` type TContainer = { + forVideoTab?: boolean, hasScroll: boolean, } diff --git a/src/hooks/usePageParams.tsx b/src/hooks/usePageParams.tsx index 4810663c..4d1df1c7 100644 --- a/src/hooks/usePageParams.tsx +++ b/src/hooks/usePageParams.tsx @@ -22,6 +22,7 @@ export const usePageParams = () => { return { profileId: Number(pageId), profileType: ProfileTypes[toUpper(profileName) as keyof typeof ProfileTypes], + sportName, sportType: SportTypes[toUpper(sportName) as keyof typeof SportTypes], } } diff --git a/src/requests/getTeamsStats.tsx b/src/requests/getTeamsStats.tsx new file mode 100644 index 00000000..027598ff --- /dev/null +++ b/src/requests/getTeamsStats.tsx @@ -0,0 +1,56 @@ +import isUndefined from 'lodash/isUndefined' + +import { callApi } from 'helpers' + +type Param = { + clickable: boolean, + data_type: string, + id: number, + lexic: number, + markers: Array, + name_en: string, + name_ru: string, + val: number, +} + +export type TeamStatItem = { + lexic: number, + name_en: string, + name_ru: string, + order: number, + param1: Param, + param2: Param | null, +} + +type Response = { + data?: { + [teamId: string]: Array, + }, + 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://3.248.230.144:8888/${sportName}/matches/${matchId}/teams/stats?group_num=0${isUndefined(second) ? '' : `&second=${second}`}`, + }) + + if (response.error) Promise.reject(response) + + return Promise.resolve(response.data || {}) +} diff --git a/src/requests/index.tsx b/src/requests/index.tsx index b8074c36..50471756 100644 --- a/src/requests/index.tsx +++ b/src/requests/index.tsx @@ -25,3 +25,4 @@ export * from './getPlayerPlaylists' export * from './getSubscriptions' export * from './buySubscription' export * from './saveMatchStats' +export * from './getTeamsStats'