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.
226 lines
6.0 KiB
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>
|
|
)
|
|
}
|
|
|