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

226 lines
6.0 KiB

import {
useEffect,
useRef,
useState,
} from 'react'
import { createPortal } from 'react-dom'
import { useTour } from '@reactour/tour'
import type { PlaylistOption } from 'features/MatchPage/types'
import { useMatchPageStore } from 'features/MatchPage/store'
import {
Spotlight,
Steps,
TOUR_COMPLETED_STORAGE_KEY,
} from 'features/MatchTour'
import { Overlay } from 'components/Overlay'
import { useEventListener, useModalRoot } from 'hooks'
import { isIOS, isMobileDevice } from 'config/userAgent'
import { getLocalStorageItem } from 'helpers/getLocalStorage'
import { MATCH_ADS } from 'components/Ads/types'
import { Tabs } from './config'
import { TabEvents } from './components/TabEvents'
import { TabWatch } from './components/TabWatch'
import { TabPlayers } from './components/TabPlayers'
import { TabStats } from './components/TabStats'
import { useMatchSidePlaylists } from './hooks'
import {
Wrapper,
TabsWrapper,
TabsGroup,
Tab,
TabIcon,
TabTitle,
Container,
TabButton,
EventsAdsWrapper,
} from './styled'
import { HeaderAds } from '../../components/Ads'
const tabPanes = {
[Tabs.WATCH]: TabWatch,
[Tabs.EVENTS]: TabEvents,
[Tabs.STATS]: TabStats,
[Tabs.PLAYERS]: TabPlayers,
}
type Props = {
onSelect: (option: PlaylistOption) => void,
selectedPlaylist?: PlaylistOption,
}
export const MatchSidePlaylists = ({
onSelect,
selectedPlaylist,
}: Props) => {
const {
ads,
hideProfileCard,
matchPlaylists: playlists,
profile,
profileCardShown,
selectedTab,
showProfileCard,
tournamentData,
} = useMatchPageStore()
const {
onTabClick,
showTabs,
} = useMatchSidePlaylists()
const {
currentStep,
isOpen,
setIsOpen,
} = useTour()
const modalRoot = useModalRoot()
const TabPane = tabPanes[selectedTab]
const containerRef = useRef<HTMLDivElement | null>(null)
const tabPaneContainerRef = useRef<HTMLDivElement | null>(null)
const [hasTabPaneScroll, setTabPaneScroll] = useState(false)
const { PLAYS_TOP, PLAYS_TOP_MOBILE } = MATCH_ADS
const adsPositionId = isMobileDevice ? PLAYS_TOP_MOBILE : PLAYS_TOP
useEffect(() => {
const {
clientHeight = 0,
scrollHeight = 0,
} = tabPaneContainerRef.current || {}
const hasScroll = scrollHeight > clientHeight
setTabPaneScroll(hasScroll)
}, [
playlists,
selectedTab,
tabPaneContainerRef.current?.clientHeight,
])
useEffect(() => {
if (
getLocalStorageItem(TOUR_COMPLETED_STORAGE_KEY) === 'true'
|| isOpen
|| !showTabs
|| Number(profile?.c_match_calc_status) < 2
) return undefined
const timer = setTimeout(() => setIsOpen(true), 1500)
return () => clearTimeout(timer)
}, [showTabs, setIsOpen, profile?.c_match_calc_status, isOpen])
useEventListener({
callback: () => {
const screenLandscape = isIOS ? window.orientation : window.screen.orientation.type
const yOffset = containerRef.current?.scrollTop
const isScreenLandscape = isIOS
? (screenLandscape === 90 || screenLandscape === -90)
: (screenLandscape === 'landscape-primary' || screenLandscape === 'landscape-secondary')
if (Number(yOffset) < 10) showProfileCard()
if (Number(yOffset) > 10 && !isScreenLandscape) hideProfileCard()
},
event: 'scroll',
target: containerRef,
})
return (
<Wrapper
ref={containerRef}
data-step={Steps.Welcome}
highlighted={Boolean(isOpen) && currentStep === Steps.Welcome}
isTourOpen={Boolean(isOpen)}
isHidden={!profileCardShown}
>
{showTabs
&& (
<TabsWrapper>
{selectedTab === Tabs.EVENTS
&& ads
&& (
<EventsAdsWrapper hasScroll={hasTabPaneScroll}>
<HeaderAds ads={ads.filter(({ position }) => position.id === adsPositionId)} />
</EventsAdsWrapper>
)}
<TabsGroup>
<Tab
aria-pressed={selectedTab === Tabs.WATCH}
onClick={() => onTabClick(Tabs.WATCH)}
id='match_watch'
>
<TabButton>
<TabIcon icon='watch' />
<TabTitle t='watch' />
</TabButton>
</Tab>
<Tab
aria-pressed={selectedTab === Tabs.EVENTS}
onClick={() => onTabClick(Tabs.EVENTS)}
id='match_plays'
>
<TabButton>
<TabIcon icon='plays' />
<TabTitle t='actions' />
</TabButton>
</Tab>
<Tab
aria-pressed={selectedTab === Tabs.PLAYERS}
onClick={() => onTabClick(Tabs.PLAYERS)}
id='match_players'
>
<TabButton>
<TabIcon icon='players' />
<TabTitle t='players' />
</TabButton>
</Tab>
<Tab
aria-pressed={selectedTab === Tabs.STATS}
onClick={() => onTabClick(Tabs.STATS)}
data-step={Steps.Start}
id='match_stats'
>
{Boolean(currentStep === Steps.Start && isOpen) && (
<Spotlight />
)}
<TabButton>
<TabIcon icon='stats' />
<TabTitle t='stats' />
</TabButton>
</Tab>
</TabsGroup>
</TabsWrapper>
)}
<Container
hasScroll={hasTabPaneScroll}
ref={tabPaneContainerRef}
forWatchTab={selectedTab === Tabs.WATCH}
highlighted={Boolean(isOpen)}
>
<TabPane
tournamentData={tournamentData}
onSelect={onSelect}
playlists={playlists}
profile={profile}
selectedPlaylist={selectedPlaylist}
/>
</Container>
{modalRoot.current && isOpen && createPortal(
<Overlay />,
modalRoot.current,
)}
</Wrapper>
)
}