diff --git a/src/config/lexics/indexLexics.tsx b/src/config/lexics/indexLexics.tsx index 10eeccb5..a75b8e28 100644 --- a/src/config/lexics/indexLexics.tsx +++ b/src/config/lexics/indexLexics.tsx @@ -73,6 +73,7 @@ export const indexLexics = { player: 630, players_video: 13032, round_highilights: 13050, + save: 828, search_results: 9014, select_language: 1005, sport: 12993, diff --git a/src/features/MatchPage/components/SettingsDesktop/index.tsx b/src/features/MatchPage/components/SettingsDesktop/index.tsx new file mode 100644 index 00000000..d9cf8685 --- /dev/null +++ b/src/features/MatchPage/components/SettingsDesktop/index.tsx @@ -0,0 +1,94 @@ +import { Fragment } from 'react' + +import styled from 'styled-components/macro' + +import type { Actions } from 'requests' + +import { + EpisodeDuration, + PlayerPlaylistFormats, + SelectedActions, + Settings, +} from 'features/MatchPopup' +import { ButtonSolid } from 'features/Common' +import { T9n } from 'features/T9n' +import { PlaylistFormats } from 'features/MatchPopup/components/PlaylistFormats' +import { EpisodeDurationInputs } from 'features/MatchPopup/components/EpisodeDurationInputs' +import { PlayerActions } from 'features/MatchPopup/components/PlayerActions' + +import { useSettingsDesktop } from './useDesktopSettings' + +const ButtonsWrapper = styled.div` + display: flex; + justify-content: center; + margin: 45px 0 15px 0; +` + +const WatchButton = styled(ButtonSolid)` + width: auto; + padding: 0 20px; +` + +type Props = { + actions: Actions, + episodeDuration: EpisodeDuration, + isMatchPlaylist?: boolean, + onWatchEpisodesClick: (values: Settings) => void, + selectedActions: SelectedActions, + selectedPlaylistFormat: PlayerPlaylistFormats, +} + +export const SettingsDesktop = ({ + actions, + episodeDuration, + isMatchPlaylist, + onWatchEpisodesClick, + selectedActions, + selectedPlaylistFormat, +}: Props) => { + const { + actionsValue, + episodeDurationValue, + selectedPlaylistFormatValue, + setActionsValue, + setEpisodeDurationValue, + setSelectedPlaylistFormatValue, + } = useSettingsDesktop({ + episodeDuration, + selectedActions, + selectedPlaylistFormat, + }) + const marginTop = isMatchPlaylist ? 0 : 62 + return ( + + + + {selectedPlaylistFormatValue === PlayerPlaylistFormats.SELECTED_ACTIONS && ( + + )} + + onWatchEpisodesClick({ + episodeDuration: episodeDurationValue, + selectedActions: actionsValue, + selectedFormat: selectedPlaylistFormatValue, + })} + > + {isMatchPlaylist + ? + : } + + + + ) +} diff --git a/src/features/MatchPage/components/SettingsDesktop/useDesktopSettings.tsx b/src/features/MatchPage/components/SettingsDesktop/useDesktopSettings.tsx new file mode 100644 index 00000000..0bd6e8a9 --- /dev/null +++ b/src/features/MatchPage/components/SettingsDesktop/useDesktopSettings.tsx @@ -0,0 +1,37 @@ +import { useState } from 'react' + +import type { + EpisodeDuration, + PlayerPlaylistFormats, + SelectedActions, +} from 'features/MatchPopup' + +type Args = { + episodeDuration: EpisodeDuration, + selectedActions: SelectedActions, + selectedPlaylistFormat: PlayerPlaylistFormats, +} + +export const useSettingsDesktop = ({ + episodeDuration, + selectedActions, + selectedPlaylistFormat, +}: Args) => { + const [actionsValue, setActionsValue] = useState(selectedActions) + const [ + episodeDurationValue, + setEpisodeDurationValue] = useState(episodeDuration) + const [ + selectedPlaylistFormatValue, + setSelectedPlaylistFormatValue, + ] = useState(selectedPlaylistFormat) + + return { + actionsValue, + episodeDurationValue, + selectedPlaylistFormatValue, + setActionsValue, + setEpisodeDurationValue, + setSelectedPlaylistFormatValue, + } +} diff --git a/src/features/MatchPage/components/SettingsPopup/index.tsx b/src/features/MatchPage/components/SettingsPopup/index.tsx new file mode 100644 index 00000000..fa7b98f3 --- /dev/null +++ b/src/features/MatchPage/components/SettingsPopup/index.tsx @@ -0,0 +1,103 @@ +import { MDASH } from 'config' + +import styled from 'styled-components/macro' + +import type { Actions, MatchInfo } from 'requests' +import type { PlaylistOption } from 'features/MatchPage/types' +import type { Settings } from 'features/MatchPopup' +import { PlaylistTypes } from 'features/MatchPage/types' +import { MediaQuery } from 'features/MediaQuery' +import { Name } from 'features/Name' +import { T9n } from 'features/T9n' +import { + CloseButton, + Header, + HeaderActions, + HeaderTitle, +} from 'features/PopupComponents' + +import { SettingsDesktop } from '../SettingsDesktop' + +const TitleWrapper = styled(HeaderTitle)` + display: flex; + flex-direction: column; + line-height: 32px; +` + +const TeamNames = styled.span` + font-weight: normal; +` + +type ContentProps = { + height?: number, +} + +const Content = styled.div` + width: 100%; +` + +type Props = { + actions: Actions, + closePopup: () => void, + onWatchEpisodesClick: (values: Settings) => void, + profile: MatchInfo, + selectedPlaylist?: PlaylistOption, + settings: Settings, +} +export const SettingsPopup = ({ + actions, + closePopup, + onWatchEpisodesClick, + profile, + selectedPlaylist, + settings, +}: Props) => { + if (!profile || !selectedPlaylist) return null + + const isMatchPlaylist = selectedPlaylist.type === PlaylistTypes.MATCH + + return ( + + {!isMatchPlaylist + ? ( +
+ + + + + + + + + + + {selectedPlaylist && } + + + {` ${MDASH} `} + + + + +
+ ) + : ( +
+ + + +
+ )} + + + +
+ ) +} diff --git a/src/features/MatchPage/hooks/useEpisodes.tsx b/src/features/MatchPage/hooks/useEpisodes.tsx index a7dc994f..ff514a8d 100644 --- a/src/features/MatchPage/hooks/useEpisodes.tsx +++ b/src/features/MatchPage/hooks/useEpisodes.tsx @@ -4,6 +4,8 @@ import { useEffect, } from 'react' +import type { Settings } from 'features/MatchPopup' + import { getPlayerPlaylists, Episodes } from 'requests' import { usePageId, useSportNameParam } from 'hooks' @@ -20,13 +22,17 @@ export const useEpisodes = ({ initialEpisodes, initialSelectedPlaylist }: Args) const { sportType } = useSportNameParam() const matchId = usePageId() - const fetchEpisodes = useCallback((selectedPlaylist: PlaylistOption) => { + const fetchEpisodes = useCallback(( + selectedPlaylist: PlaylistOption, + settings?: Settings, + ) => { if (!selectedPlaylist) return if (selectedPlaylist.type === PlaylistTypes.PLAYER) { getPlayerPlaylists({ matchId, playerId: selectedPlaylist.id, + settings, sportType, }).then(setEpisodes) } else if (selectedPlaylist.type === PlaylistTypes.MATCH) { diff --git a/src/features/MatchPage/hooks/useMatchPage.tsx b/src/features/MatchPage/hooks/useMatchPage.tsx index c1a7b9a6..786e726b 100644 --- a/src/features/MatchPage/hooks/useMatchPage.tsx +++ b/src/features/MatchPage/hooks/useMatchPage.tsx @@ -1,24 +1,61 @@ import { useEffect, useState } from 'react' +import isEqual from 'lodash/isEqual' + import type { LiveVideos } from 'requests' import { getLiveVideos } from 'requests' - -import { useSportNameParam, usePageId } from 'hooks' - -import { useMatchPopupStore } from 'features/MatchPopup' +import { + useSportNameParam, + usePageId, + useToggle, +} from 'hooks' +import { Settings, useMatchPopupStore } from 'features/MatchPopup' import { useLastPlayPosition } from './useLastPlayPosition' import { usePlaylists } from './usePlaylists' import { useChapters } from './useChapters' import { useRouteState } from './useRouteState' +import { useMatchProfile } from './useMatchProfile' export const useMatchPage = () => { - const { closePopup } = useMatchPopupStore() 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, + setMatch, + setSettings, + settings, + } = useMatchPopupStore() + + const { + close, + isOpen, + open, + } = useToggle() + + useEffect(() => { + if (profile) { + const match = { + calc: false, + id: matchId, + live: false, + sportType, + team1: profile.team1, + team2: profile.team2, + } + setMatch(match) + } + }, [ + matchId, + profile, + setMatch, + sportType, + ]) const { episodes, @@ -31,6 +68,17 @@ export const useMatchPage = () => { isFinishedMatch, }) + const setEpisodesSettings = (values: Settings) => { + const isSettingsChanged = !isEqual(values, settings) + if (isSettingsChanged) { + setSettings({ + episodeDuration: values.episodeDuration, + selectedActions: values.selectedActions, + selectedFormat: values.selectedFormat, + }) + } + close() + } useEffect(() => { if (!isFinishedMatch) { getLiveVideos(sportType, matchId) @@ -49,9 +97,16 @@ export const useMatchPage = () => { }, [closePopup]) return { + actions, + closeSettingsPopup: close, + isOpen, onPlaylistSelect, + openSettingsPopup: open, playlists, + profile, selectedPlaylist, + setEpisodesSettings, + settings, url: liveVideos[0] || '', ...useChapters({ episodes, diff --git a/src/features/MatchPage/hooks/usePlaylists.tsx b/src/features/MatchPage/hooks/usePlaylists.tsx index 362e3cee..b9888d57 100644 --- a/src/features/MatchPage/hooks/usePlaylists.tsx +++ b/src/features/MatchPage/hooks/usePlaylists.tsx @@ -9,6 +9,7 @@ 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' @@ -37,6 +38,7 @@ export const usePlaylists = ({ const { sportType } = useSportNameParam() const { fetchLexics } = usePlaylistLexics() const matchId = usePageId() + const { settings } = useMatchPopupStore() const { episodes, @@ -45,6 +47,15 @@ export const usePlaylists = ({ initialEpisodes, initialSelectedPlaylist, }) + useEffect(() => { + if (selectedPlaylist) { + fetchEpisodes(selectedPlaylist, settings) + } + }, [ + fetchEpisodes, + selectedPlaylist, + settings, + ]) useEffect(() => { if (isFinishedMatch) { @@ -72,7 +83,6 @@ export const usePlaylists = ({ const onPlaylistSelect = (option: PlaylistOption) => { if (option === selectedPlaylist) return setSelectedPlaylist(option) - fetchEpisodes(option) } return { diff --git a/src/features/MatchPage/index.tsx b/src/features/MatchPage/index.tsx index 2118f25a..97a39f1d 100644 --- a/src/features/MatchPage/index.tsx +++ b/src/features/MatchPage/index.tsx @@ -9,26 +9,35 @@ import { MultiSourcePlayer } from 'features/MultiSourcePlayer' import { StreamPlayer } from 'features/StreamPlayer' import { MatchProfileCard } from './components/MatchProfileCard' -import { useMatchProfile } from './hooks/useMatchProfile' import { MainWrapper as Wrapper, + Modal, Container, } from './styled' + import { useMatchPage } from './hooks/useMatchPage' import { usePlayerProgressReporter } from './hooks/usePlayerProgressReporter' +import { SettingsPopup } from './components/SettingsPopup' const MatchPage = () => { - const profile = useMatchProfile() const { + actions, chapters, + closeSettingsPopup, isLastPlayPositionFetching, + isOpen, lastPlayPosition, onPlaylistSelect, + openSettingsPopup, playlists, + profile, selectedPlaylist, + setEpisodesSettings, + settings, url, } = useMatchPage() + const { onPlayerProgressChange, onPlayingChange } = usePlayerProgressReporter() const isLiveMatch = Boolean(url) && !isLastPlayPositionFetching @@ -36,6 +45,20 @@ const MatchPage = () => { return ( + + + @@ -69,6 +92,7 @@ const MatchPage = () => { selectedPlaylist={selectedPlaylist} onSelect={onPlaylistSelect} profile={profile} + openPopup={openSettingsPopup} /> diff --git a/src/features/MatchPage/styled.tsx b/src/features/MatchPage/styled.tsx index 48765b9b..36474138 100644 --- a/src/features/MatchPage/styled.tsx +++ b/src/features/MatchPage/styled.tsx @@ -2,6 +2,9 @@ import styled from 'styled-components/macro' import { devices } from 'config/devices' +import { Modal as BaseModal } from 'features/Modal' +import { ModalWindow } from 'features/Modal/styled' + export const MainWrapper = styled.div` margin: 63px 0px 0 22px; display: flex; @@ -35,3 +38,24 @@ export const Container = styled.div` max-width: 100%; } ` + +export const Modal = styled(BaseModal)` + background-color: rgba(0, 0, 0, 0.7); + + ${ModalWindow} { + width: 1222px; + padding: 20px 0; + background-color: #3F3F3F; + border-radius: 5px; + + @media ${devices.tablet} { + width: 100vw; + } + + @media ${devices.mobile} { + height: 100vh; + padding: 0; + background-color: transparent; + } + } +` diff --git a/src/features/MatchPopup/components/PlaylistFormats/index.tsx b/src/features/MatchPopup/components/PlaylistFormats/index.tsx index 4f07c65b..3ab469d6 100644 --- a/src/features/MatchPopup/components/PlaylistFormats/index.tsx +++ b/src/features/MatchPopup/components/PlaylistFormats/index.tsx @@ -10,15 +10,17 @@ import { } from './styled' type Props = { + marginTop?: number, onFormatSelect: (format: PlayerPlaylistFormats) => void, selectedFormat: PlayerPlaylistFormats, } export const PlaylistFormats = ({ + marginTop, onFormatSelect, selectedFormat, }: Props) => ( - + diff --git a/src/features/MatchPopup/components/PlaylistFormats/styled.tsx b/src/features/MatchPopup/components/PlaylistFormats/styled.tsx index d3b51e60..b266c367 100644 --- a/src/features/MatchPopup/components/PlaylistFormats/styled.tsx +++ b/src/features/MatchPopup/components/PlaylistFormats/styled.tsx @@ -6,19 +6,23 @@ import { Radio as BaseRadio } from 'features/Common' import { Label } from 'features/Common/Radio/styled' import { RadioSvg } from 'features/Common/Radio/Icon' -export const Wrapper = styled.div` +type Props = { + marginTop?: number, +} + +export const Wrapper = styled.div` display: flex; flex-direction: column; margin-top: 62px; padding-left: 35px; padding-right: 20px; + margin-top: ${({ marginTop }) => `${marginTop ?? 62}px`}; @media ${devices.mobile} { margin-top: 14px; padding: 0 12px; } ` - export const List = styled.ul` display: flex; flex-direction: column; diff --git a/src/features/MatchPopup/store/hooks/index.tsx b/src/features/MatchPopup/store/hooks/index.tsx index b847a165..df43bb17 100644 --- a/src/features/MatchPopup/store/hooks/index.tsx +++ b/src/features/MatchPopup/store/hooks/index.tsx @@ -36,6 +36,7 @@ export const useMatchPopup = () => { setEpisodeDuration, setSelectedActions, setSelectedPlaylistFormat, + setSettings, settings, } = useSettingsState(match?.sportType) @@ -112,6 +113,8 @@ export const useMatchPopup = () => { selectedActions, selectedPlaylistFormat, setMatch, + setSettings, + settings, ...usePlayerClickHandler({ goTo, match, diff --git a/src/features/MatchPopup/store/hooks/useSettingsState.tsx b/src/features/MatchPopup/store/hooks/useSettingsState.tsx index 060db25d..95008191 100644 --- a/src/features/MatchPopup/store/hooks/useSettingsState.tsx +++ b/src/features/MatchPopup/store/hooks/useSettingsState.tsx @@ -66,6 +66,7 @@ export const useSettingsState = (sportType?: SportTypes) => { setEpisodeDuration, setSelectedActions, setSelectedPlaylistFormat, + setSettings, settings, } } diff --git a/src/features/MatchSidePlaylists/index.tsx b/src/features/MatchSidePlaylists/index.tsx index 318a374c..cda34d7a 100644 --- a/src/features/MatchSidePlaylists/index.tsx +++ b/src/features/MatchSidePlaylists/index.tsx @@ -10,14 +10,17 @@ import { SideInterviews } from './components/SideInterviews' import { PlayersPlaylists } from './components/PlayersPlaylists' import { + ButtonBox, Container, DropdownWrapper, List, + SettingsButton, Wrapper, } from './styled' type Props = { onSelect: (option: PlaylistOption) => void, + openPopup: () => void, playlists: Playlists, profile: MatchInfo, selectedPlaylist?: PlaylistOption, @@ -29,6 +32,7 @@ export const isEqual = (target: PlaylistOption, selected?: PlaylistOption) => ( export const MatchSidePlaylists = ({ onSelect, + openPopup, playlists, profile, selectedPlaylist, @@ -54,6 +58,9 @@ export const MatchSidePlaylists = ({ onSelect={onSelect} /> + + + { const actions = isEmpty(settings.selectedActions) ? null : settings.selectedActions + const config = { body: { params: {