From c167d2dd77e959430fad6a8a7b757a2938787fb9 Mon Sep 17 00:00:00 2001 From: Zoia <43918051+zizi62@users.noreply.github.com> Date: Wed, 27 Jan 2021 09:39:20 -0500 Subject: [PATCH] Ott 701 videos panel (#278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: ๐ŸŽธ OTT-701-videos-panel add side panel * feat: ๐ŸŽธ OTT-701 add some styles * feat: ๐ŸŽธ OTT-701 delete // * feat: ๐ŸŽธ #701 hook deleted * fix(701): reset route state on mount * feat: ๐ŸŽธ OTT-701 fix comments * feat: ๐ŸŽธ OTT-701 fix names * fix: renamed dropdown * fix: renamed dropdown back * feat: ๐ŸŽธ OTT-701 fix height * feat: ๐ŸŽธ OTT-701 undo changes for isClickable * feat: ๐ŸŽธ OTT-701 fix comments Co-authored-by: Zoia Co-authored-by: Mirlan --- .../MatchPage/helpers/buildPlaylists.tsx | 1 + src/features/MatchPage/hooks/useMatchPage.tsx | 9 +- .../MatchPage/hooks/usePlaylistData.tsx | 10 ++- src/features/MatchPage/hooks/usePlaylists.tsx | 29 +++++-- .../MatchPage/hooks/useRouteState.tsx | 2 +- src/features/MatchPage/index.tsx | 10 ++- src/features/MatchPage/styled.tsx | 2 +- src/features/MatchPage/types.tsx | 3 +- .../components/DropdownSection/index.tsx | 53 ++++++++++++ .../components/DropdownSection/styled.tsx | 78 +++++++++++++++++ .../components/InterviewButton/index.tsx | 63 ++++++++++++++ .../components/MatchPlaylists/index.tsx | 45 ++++++++++ .../components/PlayButton/index.tsx | 37 ++++++++ .../components/PlayersPlaylists/index.tsx | 69 +++++++++++++++ .../components/SideInterviews/index.tsx | 53 ++++++++++++ src/features/MatchSidePlaylists/index.tsx | 85 +++++++++++++++++-- src/features/MatchSidePlaylists/styled.tsx | 62 ++++++++++++++ src/requests/getMatchPlaylists.tsx | 4 +- 18 files changed, 587 insertions(+), 28 deletions(-) create mode 100644 src/features/MatchSidePlaylists/components/DropdownSection/index.tsx create mode 100644 src/features/MatchSidePlaylists/components/DropdownSection/styled.tsx create mode 100644 src/features/MatchSidePlaylists/components/InterviewButton/index.tsx create mode 100644 src/features/MatchSidePlaylists/components/MatchPlaylists/index.tsx create mode 100644 src/features/MatchSidePlaylists/components/PlayButton/index.tsx create mode 100644 src/features/MatchSidePlaylists/components/PlayersPlaylists/index.tsx create mode 100644 src/features/MatchSidePlaylists/components/SideInterviews/index.tsx create mode 100644 src/features/MatchSidePlaylists/styled.tsx diff --git a/src/features/MatchPage/helpers/buildPlaylists.tsx b/src/features/MatchPage/helpers/buildPlaylists.tsx index d1d2e310..8bb99611 100644 --- a/src/features/MatchPage/helpers/buildPlaylists.tsx +++ b/src/features/MatchPage/helpers/buildPlaylists.tsx @@ -45,6 +45,7 @@ const getPlayerPlaylists = (players?: Players): PlayerPlaylistOptions => ( export const buildPlaylists = (matchPlaylists: MatchPlaylists | null) => { const playlists: Playlists = { interview: [], + lexics: matchPlaylists?.lexics, match: getMatchPlaylists(matchPlaylists), players: { team1: getPlayerPlaylists(matchPlaylists?.players1), diff --git a/src/features/MatchPage/hooks/useMatchPage.tsx b/src/features/MatchPage/hooks/useMatchPage.tsx index b7cac190..e2c9087c 100644 --- a/src/features/MatchPage/hooks/useMatchPage.tsx +++ b/src/features/MatchPage/hooks/useMatchPage.tsx @@ -14,7 +14,7 @@ import { useRouteState } from './useRouteState' export const useMatchPage = () => { const { closePopup } = useMatchPopupStore() - const { initialSelectedPlaylist } = useRouteState() + const { initialPlaylistData, initialSelectedPlaylist } = useRouteState() const [isFinishedMatch, setFinishedMatch] = useState(Boolean(initialSelectedPlaylist)) const [liveVideos, setLiveVideos] = useState([]) const { sportType } = useSportNameParam() @@ -25,7 +25,11 @@ export const useMatchPage = () => { playlistData, playlists, selectedPlaylist, - } = usePlaylists(isFinishedMatch) + } = usePlaylists({ + initialPlaylistData, + initialSelectedPlaylist, + isFinishedMatch, + }) useEffect(() => { if (!isFinishedMatch) { @@ -45,7 +49,6 @@ export const useMatchPage = () => { }, [closePopup]) return { - isFinishedMatch, onPlaylistSelect, playlists, selectedPlaylist, diff --git a/src/features/MatchPage/hooks/usePlaylistData.tsx b/src/features/MatchPage/hooks/usePlaylistData.tsx index 04b725ea..470952d4 100644 --- a/src/features/MatchPage/hooks/usePlaylistData.tsx +++ b/src/features/MatchPage/hooks/usePlaylistData.tsx @@ -4,16 +4,18 @@ import { useEffect, } from 'react' -import { getPlayerPlaylists } from 'requests' +import { getPlayerPlaylists, PlaylistData } from 'requests' import { usePageId, useSportNameParam } from 'hooks' import { PlaylistOption, PlaylistTypes } from 'features/MatchPage/types' -import { useRouteState } from './useRouteState' +type Args = { + initialPlaylistData?: PlaylistData, + initialSelectedPlaylist?: PlaylistOption, +} -export const usePlaylistsData = () => { - const { initialPlaylistData, initialSelectedPlaylist } = useRouteState() +export const usePlaylistsData = ({ initialPlaylistData, initialSelectedPlaylist }: Args) => { const [playlistData, setPlaylistData] = useState(initialPlaylistData || []) const { sportType } = useSportNameParam() const matchId = usePageId() diff --git a/src/features/MatchPage/hooks/usePlaylists.tsx b/src/features/MatchPage/hooks/usePlaylists.tsx index f4f223c6..ad9379f9 100644 --- a/src/features/MatchPage/hooks/usePlaylists.tsx +++ b/src/features/MatchPage/hooks/usePlaylists.tsx @@ -2,14 +2,14 @@ import { useEffect, useState } from 'react' import isEmpty from 'lodash/isEmpty' -import { getMatchPlaylists } from 'requests' +import { getMatchPlaylists, PlaylistData } from 'requests' import { usePageId, useSportNameParam } from 'hooks' import type { PlaylistOption, Playlists } from 'features/MatchPage/types' +import { usePlaylistLexics } from 'features/MatchPopup/store/hooks/usePlaylistLexics' import { buildPlaylists } from '../helpers/buildPlaylists' -import { useRouteState } from './useRouteState' import { usePlaylistsData } from './usePlaylistData' const initialPlaylists: Playlists = { @@ -21,28 +21,43 @@ const initialPlaylists: Playlists = { }, } -export const usePlaylists = (isFinishedMatch: boolean) => { - const { initialSelectedPlaylist } = useRouteState() +type Args = { + initialPlaylistData?: PlaylistData, + initialSelectedPlaylist?: PlaylistOption, + isFinishedMatch: boolean, +} + +export const usePlaylists = ({ + initialPlaylistData, + initialSelectedPlaylist, + isFinishedMatch, +}: Args) => { const [playlists, setPlaylists] = useState(initialPlaylists) const [selectedPlaylist, setSelectedPlaylist] = useState(initialSelectedPlaylist) const { sportType } = useSportNameParam() + const { fetchLexics } = usePlaylistLexics() const matchId = usePageId() const { fetchPlaylists, playlistData, - } = usePlaylistsData() + } = usePlaylistsData({ + initialPlaylistData, + initialSelectedPlaylist, + }) useEffect(() => { if (isFinishedMatch) { getMatchPlaylists({ matchId, - selectedActions: [1, 2, 3], + selectedActions: [], sportType, - }).then(buildPlaylists) + }).then(fetchLexics) + .then(buildPlaylists) .then(setPlaylists) } }, [ + fetchLexics, isFinishedMatch, matchId, sportType, diff --git a/src/features/MatchPage/hooks/useRouteState.tsx b/src/features/MatchPage/hooks/useRouteState.tsx index 6688ef9f..f397e6ea 100644 --- a/src/features/MatchPage/hooks/useRouteState.tsx +++ b/src/features/MatchPage/hooks/useRouteState.tsx @@ -25,7 +25,7 @@ export const useRouteState = () => { const { state } = useLocation() const history = useHistory() - useEffect(() => () => { + useEffect(() => { // ัะฑั€ะฐัั‹ะฒะฐะตะผ ั€ะพัƒั‚ ัั‚ะตะนั‚ history.replace(history.location.pathname) }, [history]) diff --git a/src/features/MatchPage/index.tsx b/src/features/MatchPage/index.tsx index dfb47eb5..46cb5974 100644 --- a/src/features/MatchPage/index.tsx +++ b/src/features/MatchPage/index.tsx @@ -24,6 +24,9 @@ export const MatchPage = () => { chapters, isLastPlayPositionFetching, lastPlayPosition, + onPlaylistSelect, + playlists, + selectedPlaylist, url, } = useMatchPage() const { onPlayerProgressChange, onPlayingChange } = usePlayerProgressReporter() @@ -61,7 +64,12 @@ export const MatchPage = () => { ) } - + ) diff --git a/src/features/MatchPage/styled.tsx b/src/features/MatchPage/styled.tsx index 0347af2f..33945f01 100644 --- a/src/features/MatchPage/styled.tsx +++ b/src/features/MatchPage/styled.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components/macro' import { devices } from 'config/devices' export const MainWrapper = styled.div` - margin: 63px 16px 0 16px; + margin: 63px 0px 0 16px; display: flex; @media ${devices.laptop} { diff --git a/src/features/MatchPage/types.tsx b/src/features/MatchPage/types.tsx index c5ad23ca..8746de39 100644 --- a/src/features/MatchPage/types.tsx +++ b/src/features/MatchPage/types.tsx @@ -1,4 +1,4 @@ -import type { PlaylistData } from 'requests' +import type { Lexics, PlaylistData } from 'requests' export enum PlaylistTypes { MATCH, @@ -40,6 +40,7 @@ export type PlayerPlaylistOptions = Array export type Playlists = { interview: InterviewPlaylistOptions, + lexics?: Lexics, match: MatchPlaylistOptions, players: { team1: PlayerPlaylistOptions, diff --git a/src/features/MatchSidePlaylists/components/DropdownSection/index.tsx b/src/features/MatchSidePlaylists/components/DropdownSection/index.tsx new file mode 100644 index 00000000..2b7e7224 --- /dev/null +++ b/src/features/MatchSidePlaylists/components/DropdownSection/index.tsx @@ -0,0 +1,53 @@ +import { ReactNode } from 'react' + +import { useToggle } from 'hooks' +import { T9n } from 'features/T9n' + +import { + Amount, + Arrows, + DropdownButton, + Title, + SectionWrapper, + Wrapper, +} from './styled' + +type Props = { + children: ReactNode, + itemsCount: number, + title?: string | number, +} + +export const DropdownSection = (props: Props) => { + const { + isOpen, + toggle, + } = useToggle() + + const { + children, + itemsCount, + title, + } = props + if (!title) return null + + return ( + + + + <T9n t={title} /> + + + {itemsCount} + + + + + {children} + + + ) +} diff --git a/src/features/MatchSidePlaylists/components/DropdownSection/styled.tsx b/src/features/MatchSidePlaylists/components/DropdownSection/styled.tsx new file mode 100644 index 00000000..c85b92f8 --- /dev/null +++ b/src/features/MatchSidePlaylists/components/DropdownSection/styled.tsx @@ -0,0 +1,78 @@ +import styled from 'styled-components/macro' + +type Props = { + active?: boolean, +} + +export const Wrapper = styled.div` + margin-bottom: 10px; +` + +export const Item = styled.li` + margin-top: 15px; + width: 100%; + height: 50px; +` + +export const SectionWrapper = styled.div` + overflow: hidden; + transition: .3s; + + ${({ active }) => ( + active + ? 'height: auto;' + : 'height: 0;' + )} +` + +export const DropdownButton = styled.button` + position: relative; + height: 100%; + width: 100%; + padding-right: 40px; + padding-left: 0px; + outline: none; + border: none; + border-radius: 2px; + display: flex; + justify-content: space-between; + align-items: center; + background-color: transparent; + font-weight: 600; + font-size: 18px; + cursor: pointer; +` + +export const Arrows = styled.span` + position: absolute; + right: 19px; + display: inline-block; + width: 12px; + height: 12px; + background-repeat: no-repeat; + background-position: center; + + ${({ active }) => ( + active + ? 'background-image: url(/images/arrowUp.svg);' + : 'background-image: url(/images/arrowDown.svg);' + )} +` + +export const Title = styled.span` + font-weight: 500; + font-size: 20px; + line-height: 45px; + letter-spacing: 0.03em; + text-align: start; + color: #ffffff; + text-transform: uppercase; +` + +export const Amount = styled.span` + font-weight: 300; + font-size: 20px; + line-height: 50px; + letter-spacing: 0.03em; + color: #ffffff; +` diff --git a/src/features/MatchSidePlaylists/components/InterviewButton/index.tsx b/src/features/MatchSidePlaylists/components/InterviewButton/index.tsx new file mode 100644 index 00000000..8af3d611 --- /dev/null +++ b/src/features/MatchSidePlaylists/components/InterviewButton/index.tsx @@ -0,0 +1,63 @@ +import { ReactNode } from 'react' + +import styled, { css } from 'styled-components/macro' + +import { Button, Title } from '../../styled' + +type InterviewProps = { + overlength?: boolean, +} + +const InterviewTitle = styled(Title)` + white-space: normal; + text-align: start; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + + ${({ overlength }) => ( + overlength + ? css` + font-size: 18px; + line-height: 26px; + ` + : css` + font-size: 20px; + line-height: 50px; + ` + )} +` + +const InterviewButton = styled(Button)` + ${({ overlength }) => ( + overlength + ? 'padding: 16px 25px;' + : 'padding: 0px 25px;' + )} +` + +type Props = { + active?: boolean, + children: ReactNode, + onClick: () => void, + overlength?: boolean, +} + +export const InterviewPlayButton = ({ + active, + children, + onClick, + overlength, +}: Props) => ( + + + {children} + + +) diff --git a/src/features/MatchSidePlaylists/components/MatchPlaylists/index.tsx b/src/features/MatchSidePlaylists/components/MatchPlaylists/index.tsx new file mode 100644 index 00000000..c4e0cad5 --- /dev/null +++ b/src/features/MatchSidePlaylists/components/MatchPlaylists/index.tsx @@ -0,0 +1,45 @@ +import styled from 'styled-components/macro' + +import map from 'lodash/map' + +import type { MatchPlaylistOptions, PlaylistOption } from 'features/MatchPage/types' + +import { T9n } from 'features/T9n' +import { isEqual } from 'features/MatchSidePlaylists' + +import { PlayButton } from '../PlayButton' +import { Item } from '../../styled' + +type Props = { + onSelect: (selectedMathPlaylist: PlaylistOption) => void, + playlists?: MatchPlaylistOptions, + selectedMathPlaylist?: PlaylistOption, +} + +const List = styled.ul`` + +export const MatchPlaylists = (props: Props) => { + const { + onSelect, + playlists, + selectedMathPlaylist, + } = props + + return ( + + { + map(playlists, (playlist) => ( + + onSelect(playlist)} + > + + + + )) + } + + ) +} diff --git a/src/features/MatchSidePlaylists/components/PlayButton/index.tsx b/src/features/MatchSidePlaylists/components/PlayButton/index.tsx new file mode 100644 index 00000000..840dacf0 --- /dev/null +++ b/src/features/MatchSidePlaylists/components/PlayButton/index.tsx @@ -0,0 +1,37 @@ +import { ReactNode } from 'react' + +import styled from 'styled-components/macro' + +import { secondsToHms } from 'helpers' + +import { Button, Title } from '../../styled' + +type Props = { + active?: boolean, + children: ReactNode, + duration?: number, + onClick: () => void, +} + +const Duration = styled(Title)` + font-weight: 300; + font-size: 16px; + letter-spacing: 0.05em; +` + +export const PlayButton = ({ + active, + children, + duration, + onClick, +}: Props) => ( + +) diff --git a/src/features/MatchSidePlaylists/components/PlayersPlaylists/index.tsx b/src/features/MatchSidePlaylists/components/PlayersPlaylists/index.tsx new file mode 100644 index 00000000..b2dc3ba5 --- /dev/null +++ b/src/features/MatchSidePlaylists/components/PlayersPlaylists/index.tsx @@ -0,0 +1,69 @@ +import styled from 'styled-components/macro' + +import map from 'lodash/map' + +import type { Team } from 'requests' +import type { PlaylistOption } from 'features/MatchPage/types' + +import { Name } from 'features/Name' +import { isEqual } from 'features/MatchSidePlaylists' + +import { PlayButton } from '../PlayButton' +import { Item } from '../DropdownSection/styled' + +type Props = { + onSelect: (selectedMathPlaylist: PlaylistOption) => void, + players: Array, + selectedMathPlaylist?: PlaylistOption, + teamName?: Team, +} + +const Wrapper = styled.div` + margin-bottom: 15px; +` + +const List = styled.ul`` + +const PlayersItem = styled(Item)` + margin-top: 10px +` +const Title = styled.span` + font-weight: 300; + font-size: 16px; + line-height: 20px; + letter-spacing: 0.03em; + color: #ffffff; +` + +export const PlayersPlaylists = (props: Props) => { + const { + onSelect, + players, + selectedMathPlaylist, + teamName, + } = props + + if (!selectedMathPlaylist || !teamName) return null + + return ( + + + <Name nameObj={teamName} /> + + + { + map(players, (player) => ( + + onSelect(player)} + active={isEqual(player, selectedMathPlaylist)} + > + + + + )) + } + + + ) +} diff --git a/src/features/MatchSidePlaylists/components/SideInterviews/index.tsx b/src/features/MatchSidePlaylists/components/SideInterviews/index.tsx new file mode 100644 index 00000000..1231791e --- /dev/null +++ b/src/features/MatchSidePlaylists/components/SideInterviews/index.tsx @@ -0,0 +1,53 @@ +import map from 'lodash/map' +import size from 'lodash/size' + +import styled from 'styled-components/macro' + +import type { InterviewPlaylistOptions, PlaylistOption } from 'features/MatchPage/types' + +import { isEqual } from 'features/MatchSidePlaylists' +import { Name } from 'features/Name' + +import { InterviewPlayButton } from '../InterviewButton' + +type Props = { + interviews: InterviewPlaylistOptions, + onSelect: (selectedMathPlaylist: PlaylistOption) => void, + selectedMathPlaylist?: PlaylistOption, +} + +const List = styled.ul`` + +const InterviewItem = styled.li` + min-height: 50px; + margin-bottom: 10px; + width: 100%; +` + +export const SideInterviews = (props: Props) => { + const { + interviews, + onSelect, + selectedMathPlaylist, + } = props + return ( + + { + map(interviews, (interview) => { + const overLength = (size(interview.name_eng) > 16 || size(interview.name_rus) > 16) + return ( + + onSelect(interview)} + overlength={overLength} + > + + + + ) + }) + } + + ) +} diff --git a/src/features/MatchSidePlaylists/index.tsx b/src/features/MatchSidePlaylists/index.tsx index a5b2fdcb..23743346 100644 --- a/src/features/MatchSidePlaylists/index.tsx +++ b/src/features/MatchSidePlaylists/index.tsx @@ -1,12 +1,79 @@ -import React from 'react' +import size from 'lodash/size' -import styled from 'styled-components/macro' +import type { PlaylistOption, Playlists } from 'features/MatchPage/types' +import type { MatchInfo } from 'requests' -const Wrapper = styled.div` - width: 288px; - height: 100px; - margin-top: 42px; - margin-left: 14px; -` +import { DropdownSection } from './components/DropdownSection' +import { MatchPlaylists } from './components/MatchPlaylists' +import { SideInterviews } from './components/SideInterviews' +import { PlayersPlaylists } from './components/PlayersPlaylists' -export const MatchSidePlaylists = () => +import { + Container, + DropdownWrapper, + List, + Wrapper, +} from './styled' + +type Props = { + onSelect: (option: PlaylistOption) => void, + playlists: Playlists, + profile: MatchInfo, + selectedPlaylist?: PlaylistOption, +} + +export const isEqual = (target: PlaylistOption, selected?: PlaylistOption) => ( + target.id === selected?.id && target.type === selected.type +) + +export const MatchSidePlaylists = ({ + onSelect, + playlists, + profile, + selectedPlaylist, +}: Props) => { + const playersCount = size(playlists.players.team1) + size(playlists.players.team2) + + return ( + + + + + + + + + + + + + + + + + ) +} diff --git a/src/features/MatchSidePlaylists/styled.tsx b/src/features/MatchSidePlaylists/styled.tsx new file mode 100644 index 00000000..42f6f723 --- /dev/null +++ b/src/features/MatchSidePlaylists/styled.tsx @@ -0,0 +1,62 @@ +import styled, { css } from 'styled-components/macro' + +import { customScrollbar } from 'features/Common' +import { buttonStyles } from 'features/MatchPopup/components/PlaylistButton' + +export const Wrapper = styled.div` + margin-top: 42px; + max-height: 86vh; + overflow-y: scroll; + ${customScrollbar} +` + +export const Container = styled.div` + width: 288px; + margin-left: 14px; + margin-right: 14px; +` + +export const DropdownWrapper = styled.div` + padding-top: 10px; +` + +export const List = styled.div`` + +type ButtonProps = { + active?: boolean, +} + +export const Button = styled.button` + ${buttonStyles} + + min-height: 50px; + outline: none; + + ${({ active }) => ( + active + ? css` + background-color: #294FC4; + &:hover { + background-color: #0c3ccc; + } + ` + : '' + )} +` + +export const Item = styled.li` + margin-bottom: 10px; + width: 100%; + height: 50px; +` + +export const Title = styled.span` + font-weight: 500; + font-size: 20px; + line-height: 50px; + letter-spacing: 0.05em; + color: #ffffff; + overflow: hidden; + white-space: nowrap; + text-overflow:ellipsis; +` diff --git a/src/requests/getMatchPlaylists.tsx b/src/requests/getMatchPlaylists.tsx index a23d98b3..f0c53773 100644 --- a/src/requests/getMatchPlaylists.tsx +++ b/src/requests/getMatchPlaylists.tsx @@ -44,11 +44,13 @@ type Player = { export type Players = Array -type Lexics = { +export type Lexics = { ball_in_play: number, full_game: number, goals: number, highlights: number, + interview: number, + players: number, } export type MatchPlaylists = {