diff --git a/src/features/MatchCard/hooks.tsx b/src/features/MatchCard/hooks.tsx index f391d9fd..c8ccfd2c 100644 --- a/src/features/MatchCard/hooks.tsx +++ b/src/features/MatchCard/hooks.tsx @@ -2,14 +2,19 @@ import type { KeyboardEvent } from 'react' import { useCallback } from 'react' import { useHistory } from 'react-router-dom' +import { ProfileTypes } from 'config' + import type { Match } from 'features/Matches' import { useMatchPopupStore } from 'features/MatchPopup' import { useBuyMatchPopupStore } from 'features/BuyMatchPopup' -import { getProfileUrl } from '../ProfileLink/helpers' -import { ProfileTypes } from '../../config' +import { getProfileUrl } from 'features/ProfileLink/helpers' export const useCard = (match: Match) => { - const { openPopup, setMatch } = useMatchPopupStore() + const { + fetchMatchPlaylists, + openPopup, + setMatch, + } = useMatchPopupStore() const { open: openBuyMatchPopup } = useBuyMatchPopupStore() const history = useHistory() const redirectToMatchPage = useCallback(() => { @@ -28,6 +33,7 @@ export const useCard = (match: Match) => { if (match.isClickable && match.calc && match.hasVideo) { setMatch(match) openPopup() + fetchMatchPlaylists(match) } else if (match.calc && !match.hasVideo) { redirectToMatchPage() } else if (!match.accessibleBySubscription) { @@ -39,6 +45,7 @@ export const useCard = (match: Match) => { openBuyMatchPopup, setMatch, redirectToMatchPage, + fetchMatchPlaylists, ]) const onKeyPress = useCallback((e: KeyboardEvent) => { diff --git a/src/features/MatchPage/hooks/useEpisodes.tsx b/src/features/MatchPage/hooks/useEpisodes.tsx index ff514a8d..cdf90415 100644 --- a/src/features/MatchPage/hooks/useEpisodes.tsx +++ b/src/features/MatchPage/hooks/useEpisodes.tsx @@ -1,50 +1,69 @@ import { useCallback, - useState, useEffect, + useState, } from 'react' -import type { Settings } from 'features/MatchPopup' +import isEmpty from 'lodash/isEmpty' -import { getPlayerPlaylists, Episodes } from 'requests' +import type { Episodes } from 'requests' +import { getPlayerPlaylists } from 'requests' import { usePageId, useSportNameParam } from 'hooks' import { PlaylistOption, PlaylistTypes } from 'features/MatchPage/types' +import { + defaultSettings, + Settings, + useMatchPopupStore, +} from 'features/MatchPopup' -type Args = { - initialEpisodes?: Episodes, - initialSelectedPlaylist?: PlaylistOption, -} - -export const useEpisodes = ({ initialEpisodes, initialSelectedPlaylist }: Args) => { - const [episodes, setEpisodes] = useState(initialEpisodes || []) +export const useEpisodes = () => { + const { + handlePlaylistClick, + matchPlaylists: playlists, + selectedPlaylist, + settings, + } = useMatchPopupStore() + const [episodes, setEpisodes] = useState([]) const { sportType } = useSportNameParam() const matchId = usePageId() const fetchEpisodes = useCallback(( - selectedPlaylist: PlaylistOption, - settings?: Settings, + playlistOption: PlaylistOption, + popupSettings: Settings = defaultSettings, ) => { - if (!selectedPlaylist) return - - if (selectedPlaylist.type === PlaylistTypes.PLAYER) { + if (playlistOption.type === PlaylistTypes.PLAYER) { getPlayerPlaylists({ matchId, - playerId: selectedPlaylist.id, - settings, + playerId: playlistOption.id, + settings: popupSettings, sportType, }).then(setEpisodes) - } else if (selectedPlaylist.type === PlaylistTypes.MATCH) { - setEpisodes(selectedPlaylist.data) + } else if (playlistOption.type === PlaylistTypes.MATCH) { + setEpisodes(playlistOption.data) } }, [matchId, sportType]) useEffect(() => { - if (initialSelectedPlaylist?.type === PlaylistTypes.MATCH) { - fetchEpisodes(initialSelectedPlaylist) + if (!selectedPlaylist && playlists && !isEmpty(playlists.match)) { + handlePlaylistClick(playlists.match[0]) + } + }, [ + selectedPlaylist, + playlists, + handlePlaylistClick, + ]) + + useEffect(() => { + if (selectedPlaylist) { + fetchEpisodes(selectedPlaylist, settings) } - }, [initialSelectedPlaylist, fetchEpisodes]) + }, [ + settings, + selectedPlaylist, + fetchEpisodes, + ]) - return { episodes, fetchEpisodes } + return { episodes } } diff --git a/src/features/MatchPage/hooks/useMatchPage.tsx b/src/features/MatchPage/hooks/useMatchPage.tsx index 786e726b..5c1433fe 100644 --- a/src/features/MatchPage/hooks/useMatchPage.tsx +++ b/src/features/MatchPage/hooks/useMatchPage.tsx @@ -12,25 +12,27 @@ import { import { Settings, useMatchPopupStore } from 'features/MatchPopup' import { useLastPlayPosition } from './useLastPlayPosition' -import { usePlaylists } from './usePlaylists' +import { useEpisodes } from './useEpisodes' import { useChapters } from './useChapters' -import { useRouteState } from './useRouteState' import { useMatchProfile } from './useMatchProfile' export const useMatchPage = () => { - const { initialEpisodes, initialSelectedPlaylist } = useRouteState() - const [isFinishedMatch, setFinishedMatch] = useState(Boolean(initialSelectedPlaylist)) - const [liveVideos, setLiveVideos] = useState([]) - const profile = useMatchProfile() - const { sportType } = useSportNameParam() - const matchId = usePageId() const { actions, closePopup, + fetchMatchPlaylists, + handlePlaylistClick, + matchPlaylists, + selectedPlaylist, setMatch, setSettings, settings, } = useMatchPopupStore() + const [isFinishedMatch, setFinishedMatch] = useState(Boolean(selectedPlaylist)) + const [liveVideos, setLiveVideos] = useState([]) + const profile = useMatchProfile() + const { sportType } = useSportNameParam() + const matchId = usePageId() const { close, @@ -38,8 +40,23 @@ export const useMatchPage = () => { open, } = useToggle() + const { episodes } = useEpisodes() + + useEffect(() => { + if (!isFinishedMatch) { + getLiveVideos(sportType, matchId) + .then(setLiveVideos) + .catch(() => setFinishedMatch(true)) + } + }, + [ + isFinishedMatch, + sportType, + matchId, + ]) + useEffect(() => { - if (profile) { + if (profile && isFinishedMatch) { const match = { calc: false, id: matchId, @@ -49,24 +66,16 @@ export const useMatchPage = () => { team2: profile.team2, } setMatch(match) + fetchMatchPlaylists(match) } }, [ matchId, profile, setMatch, sportType, - ]) - - const { - episodes, - onPlaylistSelect, - playlists, - selectedPlaylist, - } = usePlaylists({ - initialEpisodes, - initialSelectedPlaylist, isFinishedMatch, - }) + fetchMatchPlaylists, + ]) const setEpisodesSettings = (values: Settings) => { const isSettingsChanged = !isEqual(values, settings) @@ -79,18 +88,6 @@ export const useMatchPage = () => { } close() } - useEffect(() => { - if (!isFinishedMatch) { - getLiveVideos(sportType, matchId) - .then(setLiveVideos) - .catch(() => setFinishedMatch(true)) - } - }, - [ - isFinishedMatch, - sportType, - matchId, - ]) useEffect(() => { closePopup() @@ -100,9 +97,9 @@ export const useMatchPage = () => { actions, closeSettingsPopup: close, isOpen, - onPlaylistSelect, + onPlaylistSelect: handlePlaylistClick, openSettingsPopup: open, - playlists, + playlists: matchPlaylists, profile, selectedPlaylist, setEpisodesSettings, diff --git a/src/features/MatchPage/hooks/usePlaylists.tsx b/src/features/MatchPage/hooks/usePlaylists.tsx deleted file mode 100644 index b9888d57..00000000 --- a/src/features/MatchPage/hooks/usePlaylists.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useEffect, useState } from 'react' - -import isEmpty from 'lodash/isEmpty' - -import { getMatchPlaylists, Episodes } from 'requests' - -import { usePageId, useSportNameParam } from 'hooks' - -import type { PlaylistOption, Playlists } from 'features/MatchPage/types' - -import { usePlaylistLexics } from 'features/MatchPopup/store/hooks/usePlaylistLexics' -import { useMatchPopupStore } from 'features/MatchPopup' -import { buildPlaylists } from '../helpers/buildPlaylists' -import { useEpisodes } from './useEpisodes' - -const initialPlaylists: Playlists = { - interview: [], - match: [], - players: { - team1: [], - team2: [], - }, -} - -type Args = { - initialEpisodes?: Episodes, - initialSelectedPlaylist?: PlaylistOption, - isFinishedMatch: boolean, -} - -export const usePlaylists = ({ - initialEpisodes, - initialSelectedPlaylist, - isFinishedMatch, -}: Args) => { - const [playlists, setPlaylists] = useState(initialPlaylists) - const [selectedPlaylist, setSelectedPlaylist] = useState(initialSelectedPlaylist) - const { sportType } = useSportNameParam() - const { fetchLexics } = usePlaylistLexics() - const matchId = usePageId() - const { settings } = useMatchPopupStore() - - const { - episodes, - fetchEpisodes, - } = useEpisodes({ - initialEpisodes, - initialSelectedPlaylist, - }) - useEffect(() => { - if (selectedPlaylist) { - fetchEpisodes(selectedPlaylist, settings) - } - }, [ - fetchEpisodes, - selectedPlaylist, - settings, - ]) - - useEffect(() => { - if (isFinishedMatch) { - getMatchPlaylists({ - matchId, - selectedActions: [], - sportType, - }).then(fetchLexics) - .then(buildPlaylists) - .then(setPlaylists) - } - }, [ - fetchLexics, - isFinishedMatch, - matchId, - sportType, - ]) - - useEffect(() => { - if (!selectedPlaylist && !isEmpty(playlists.match)) { - setSelectedPlaylist(playlists.match[0]) - } - }, [selectedPlaylist, playlists]) - - const onPlaylistSelect = (option: PlaylistOption) => { - if (option === selectedPlaylist) return - setSelectedPlaylist(option) - } - - return { - episodes, - onPlaylistSelect, - playlists, - selectedPlaylist, - } -} diff --git a/src/features/MatchPage/hooks/useRouteState.tsx b/src/features/MatchPage/hooks/useRouteState.tsx deleted file mode 100644 index 63791f44..00000000 --- a/src/features/MatchPage/hooks/useRouteState.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { useEffect } from 'react' -import { useHistory, useLocation } from 'react-router' - -import type { Episodes } from 'requests' - -import type { PlaylistOption } from 'features/MatchPage/types' - -export type RouteState = { - /** - * Данные плейлиста если был выбран игрок - */ - episodes?: Episodes, - - /** - * Выбранный плейлист на попапе матчей - */ - selectedPlaylist: PlaylistOption, -} - -export const useRouteState = () => { - // считываем стейт из роутера - // если есть стейт то на этот матч мы переходили - // из попапа матчей и статус матча Завершенный - // и запрос на получение ссылки лив матча можно пропустить - const { state } = useLocation() - const history = useHistory() - - useEffect(() => { - // сбрасываем роут стейт - history.replace(history.location.pathname) - }, [history]) - - return { - initialEpisodes: state?.episodes, - initialSelectedPlaylist: state?.selectedPlaylist, - } -} diff --git a/src/features/MatchPage/index.tsx b/src/features/MatchPage/index.tsx index 97a39f1d..f9affba5 100644 --- a/src/features/MatchPage/index.tsx +++ b/src/features/MatchPage/index.tsx @@ -87,13 +87,17 @@ const MatchPage = () => { ) } - + { + playlists && ( + + ) + } ) diff --git a/src/features/MatchPopup/components/PlayerSettingsPage/index.tsx b/src/features/MatchPopup/components/PlayerSettingsPage/index.tsx index 842cd11f..3a4df718 100644 --- a/src/features/MatchPopup/components/PlayerSettingsPage/index.tsx +++ b/src/features/MatchPopup/components/PlayerSettingsPage/index.tsx @@ -21,7 +21,7 @@ export const PlayerSettingsPage = () => { const { closePopup, match, - selectedPlayer, + selectedPlaylist, } = useMatchPopupStore() if (!match) return null @@ -44,7 +44,7 @@ export const PlayerSettingsPage = () => { - {selectedPlayer && } + {selectedPlaylist && } {` ${MDASH} `} diff --git a/src/features/MatchPopup/components/PlaylistButton/index.tsx b/src/features/MatchPopup/components/PlaylistButton/index.tsx index 39b882ab..3dde38a4 100644 --- a/src/features/MatchPopup/components/PlaylistButton/index.tsx +++ b/src/features/MatchPopup/components/PlaylistButton/index.tsx @@ -1,4 +1,3 @@ -import type { MouseEvent } from 'react' import { Link } from 'react-router-dom' import styled, { css } from 'styled-components/macro' @@ -9,6 +8,8 @@ import { secondsToHms } from 'helpers' import { T9n } from 'features/T9n' import { MatchPlaylistOption } from 'features/MatchPage/types' +import { useMatchPopupStore } from '../../store' + type ButtonsStypesProps = { disabled?: boolean, } @@ -91,8 +92,6 @@ export const Duration = styled(Title)` } ` -const stopPropagation = (e: MouseEvent) => e.stopPropagation() - type Props = { playlist: MatchPlaylistOption, to: string, @@ -101,19 +100,19 @@ type Props = { export const PlaylistButton = ({ playlist, to, -}: Props) => ( - - - <T9n t={playlist.lexic} /> - - {playlist.duration && {secondsToHms(playlist.duration)}} - -) +}: Props) => { + const { handlePlaylistClick } = useMatchPopupStore() + return ( + handlePlaylistClick(playlist, e)} + disabled={!playlist.duration} + tabIndex={!playlist.duration ? -1 : 0} + > + + <T9n t={playlist.lexic} /> + + {playlist.duration && {secondsToHms(playlist.duration)}} + + ) +} diff --git a/src/features/MatchPopup/components/SettingsDesktop/index.tsx b/src/features/MatchPopup/components/SettingsDesktop/index.tsx index 34f903d4..5b7a893d 100644 --- a/src/features/MatchPopup/components/SettingsDesktop/index.tsx +++ b/src/features/MatchPopup/components/SettingsDesktop/index.tsx @@ -2,8 +2,11 @@ import { Fragment } from 'react' import styled from 'styled-components/macro' +import { ProfileTypes } from 'config' + import { useMatchPopupStore } from 'features/MatchPopup' -import { ButtonSolid } from 'features/Common' +import { solidButtonStyles } from 'features/Common' +import { ProfileLink } from 'features/ProfileLink' import { T9n } from 'features/T9n' import { PlaylistFormats } from '../PlaylistFormats' @@ -17,22 +20,29 @@ const ButtonsWrapper = styled.div` margin: 45px 0 15px 0; ` -const WatchButton = styled(ButtonSolid)` +const WatchButton = styled(ProfileLink)` + ${solidButtonStyles} + width: auto; padding: 0 20px; + display: flex; + align-items: center; ` export const SettingsDesktop = () => { const { actions, episodeDuration, - handleWatchEpisodesClick, + match, onActionClick, onDurationChange, onFormatSelect, selectedActions, selectedPlaylistFormat, } = useMatchPopupStore() + + if (!match) return null + return ( { )} - + diff --git a/src/features/MatchPopup/store/hooks/index.tsx b/src/features/MatchPopup/store/hooks/index.tsx index df43bb17..ae257982 100644 --- a/src/features/MatchPopup/store/hooks/index.tsx +++ b/src/features/MatchPopup/store/hooks/index.tsx @@ -1,6 +1,7 @@ import { useState, useEffect, + useCallback, } from 'react' import isEmpty from 'lodash/isEmpty' @@ -14,7 +15,7 @@ import { useSettingsState } from './useSettingsState' import { useSportActions } from './useSportActions' import { usePopupNavigation } from './usePopupNavigation' -import type { MatchData } from '../../types' +import type { MatchData, SelectedActions } from '../../types' import { PopupPages, PlayerPlaylistFormats } from '../../types' import { usePlayerClickHandler } from './usePlayerClickHandler' import { usePlaylistLexics } from './usePlaylistLexics' @@ -50,56 +51,51 @@ export const useMatchPopup = () => { const { fetchLexics } = usePlaylistLexics() + const isFormatSelectedActions = selectedPlaylistFormat === PlayerPlaylistFormats.SELECTED_ACTIONS useEffect(() => { - if (selectedPlaylistFormat === PlayerPlaylistFormats.SELECTED_ACTIONS) { + if (isFormatSelectedActions) { fetchSportActions() } else { setSelectedActions([]) } }, [ - selectedPlaylistFormat, + isFormatSelectedActions, fetchSportActions, setSelectedActions, ]) - useEffect(() => { - if (!isOpen) { - setMatch(null) - setMatchPlaylists(null) - } - }, [isOpen]) - useEffect(() => { const isPlaylistPage = page === PopupPages.PLAYLIST - const actionsFormatSelected = ( - selectedPlaylistFormat === PlayerPlaylistFormats.SELECTED_ACTIONS - ) - if (isPlaylistPage && actionsFormatSelected && isEmpty(selectedActions)) { + if (isPlaylistPage && isFormatSelectedActions && isEmpty(selectedActions)) { setSelectedPlaylistFormat(PlayerPlaylistFormats.ALL_MATCH_TIME) } }, [ selectedActions, - selectedPlaylistFormat, + isFormatSelectedActions, page, setSelectedPlaylistFormat, ]) - useEffect(() => { - if (!match) return + const fetchMatchPlaylists = useCallback(( + matchData: MatchData, + selected: SelectedActions = [], + ) => { + if (!matchData) return getMatchPlaylists({ - matchId: match.id, - selectedActions: [], - sportType: match.sportType, + matchId: matchData.id, + selectedActions: selected, + sportType: matchData.sportType, }).then(fetchLexics) .then(buildPlaylists) .then(setMatchPlaylists) - }, [match, fetchLexics]) + }, [fetchLexics]) return { actions, closePopup, episodeDuration, + fetchMatchPlaylists, goBack, goTo, isOpen, @@ -117,8 +113,6 @@ export const useMatchPopup = () => { settings, ...usePlayerClickHandler({ goTo, - match, - settings, }), } } diff --git a/src/features/MatchPopup/store/hooks/usePlayerClickHandler.tsx b/src/features/MatchPopup/store/hooks/usePlayerClickHandler.tsx index d21e718e..b5eebcf2 100644 --- a/src/features/MatchPopup/store/hooks/usePlayerClickHandler.tsx +++ b/src/features/MatchPopup/store/hooks/usePlayerClickHandler.tsx @@ -1,65 +1,31 @@ import type { MouseEvent } from 'react' -import { useCallback, useState } from 'react' -import { useHistory } from 'react-router' +import { useState } from 'react' -import { ProfileTypes } from 'config' -import { getPlayerPlaylists } from 'requests' - -import type { PlayerPlaylistOption } from 'features/MatchPage/types' -import type { MatchData, Settings } from 'features/MatchPopup/types' -import type { RouteState } from 'features/MatchPage/hooks/useRouteState' +import type { PlaylistOption, PlayerPlaylistOption } from 'features/MatchPage/types' import { PopupPages } from 'features/MatchPopup/types' -import { getProfileUrl } from 'features/ProfileLink/helpers' type Args = { goTo: (page: PopupPages) => void, - match: MatchData, - settings: Settings, } export const usePlayerClickHandler = ({ goTo, - match, - settings, }: Args) => { - const history = useHistory() - const [selectedPlayer, setSelectedPlayer] = useState(null) - const handlePlayerClick = (player: PlayerPlaylistOption, e: MouseEvent) => { - e.stopPropagation() - setSelectedPlayer(player) + const [selectedPlaylist, setSelectedPlaylist] = useState() + const handlePlaylistClick = (playlist: PlaylistOption, e?: MouseEvent) => { + e?.stopPropagation() + if (playlist !== selectedPlaylist) { + setSelectedPlaylist(playlist) + } + } + const handlePlayerClick = (player: PlayerPlaylistOption, e?: MouseEvent) => { + handlePlaylistClick(player, e) goTo(PopupPages.PLAYER_SETTINGS) } - const handleWatchEpisodesClick = useCallback(async () => { - if (!match || !selectedPlayer) return - const episodes = await getPlayerPlaylists({ - matchId: match.id, - playerId: selectedPlayer.id, - settings, - sportType: match.sportType, - }) - - const matchLink = getProfileUrl({ - id: match.id, - profileType: ProfileTypes.MATCHES, - sportType: match.sportType, - }) - - const routeState: RouteState = { - episodes, - selectedPlaylist: selectedPlayer, - } - history.push(matchLink, routeState) - }, [ - match, - selectedPlayer, - settings, - history, - ]) - return { handlePlayerClick, - handleWatchEpisodesClick, - selectedPlayer, + handlePlaylistClick, + selectedPlaylist, } }