Ott 701 videos panel (#278)
* 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 <zizi2405@yandex.ru> Co-authored-by: Mirlan <m.maksitaliev@gmail.com>keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
parent
537a38a79a
commit
c167d2dd77
@ -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 ( |
||||
<Wrapper> |
||||
<DropdownButton |
||||
active={isOpen} |
||||
onClick={toggle} |
||||
> |
||||
<Title> |
||||
<T9n t={title} /> |
||||
</Title> |
||||
<Amount> |
||||
{itemsCount} |
||||
</Amount> |
||||
<Arrows active={isOpen} /> |
||||
</DropdownButton> |
||||
<SectionWrapper active={isOpen}> |
||||
{children} |
||||
</SectionWrapper> |
||||
</Wrapper> |
||||
) |
||||
} |
||||
@ -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<Props>` |
||||
overflow: hidden; |
||||
transition: .3s; |
||||
|
||||
${({ active }) => ( |
||||
active |
||||
? 'height: auto;' |
||||
: 'height: 0;' |
||||
)} |
||||
` |
||||
|
||||
export const DropdownButton = styled.button<Props>` |
||||
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<Props>` |
||||
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; |
||||
` |
||||
@ -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)<InterviewProps>` |
||||
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)<InterviewProps>` |
||||
${({ 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) => ( |
||||
<InterviewButton |
||||
onClick={onClick} |
||||
active={active} |
||||
overlength={overlength} |
||||
> |
||||
<InterviewTitle |
||||
overlength={overlength} |
||||
> |
||||
{children} |
||||
</InterviewTitle> |
||||
</InterviewButton> |
||||
) |
||||
@ -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 ( |
||||
<List> |
||||
{ |
||||
map(playlists, (playlist) => ( |
||||
<Item key={playlist.id}> |
||||
<PlayButton |
||||
duration={playlist.duration} |
||||
active={isEqual(playlist, selectedMathPlaylist)} |
||||
onClick={() => onSelect(playlist)} |
||||
> |
||||
<T9n t={playlist.lexic} /> |
||||
</PlayButton> |
||||
</Item> |
||||
)) |
||||
} |
||||
</List> |
||||
) |
||||
} |
||||
@ -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) => ( |
||||
<Button |
||||
onClick={onClick} |
||||
active={active} |
||||
> |
||||
<Title> |
||||
{children} |
||||
</Title> |
||||
{duration && <Duration>{secondsToHms(duration)}</Duration>} |
||||
</Button> |
||||
) |
||||
@ -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<PlaylistOption>, |
||||
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 ( |
||||
<Wrapper> |
||||
<Title> |
||||
<Name nameObj={teamName} /> |
||||
</Title> |
||||
<List> |
||||
{ |
||||
map(players, (player) => ( |
||||
<PlayersItem key={player.id}> |
||||
<PlayButton |
||||
onClick={() => onSelect(player)} |
||||
active={isEqual(player, selectedMathPlaylist)} |
||||
> |
||||
<Name nameObj={player} /> |
||||
</PlayButton> |
||||
</PlayersItem> |
||||
)) |
||||
} |
||||
</List> |
||||
</Wrapper> |
||||
) |
||||
} |
||||
@ -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 ( |
||||
<List> |
||||
{ |
||||
map(interviews, (interview) => { |
||||
const overLength = (size(interview.name_eng) > 16 || size(interview.name_rus) > 16) |
||||
return ( |
||||
<InterviewItem key={interview.id}> |
||||
<InterviewPlayButton |
||||
active={isEqual(interview, selectedMathPlaylist)} |
||||
onClick={() => onSelect(interview)} |
||||
overlength={overLength} |
||||
> |
||||
<Name nameObj={interview} /> |
||||
</InterviewPlayButton> |
||||
</InterviewItem> |
||||
) |
||||
}) |
||||
} |
||||
</List> |
||||
) |
||||
} |
||||
@ -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 = () => <Wrapper /> |
||||
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 ( |
||||
<Wrapper> |
||||
<Container> |
||||
<MatchPlaylists |
||||
playlists={playlists.match} |
||||
selectedMathPlaylist={selectedPlaylist} |
||||
onSelect={onSelect} |
||||
/> |
||||
<DropdownWrapper> |
||||
<DropdownSection |
||||
itemsCount={size(playlists.interview)} |
||||
title={playlists.lexics?.interview} |
||||
> |
||||
<SideInterviews |
||||
interviews={playlists.interview} |
||||
selectedMathPlaylist={selectedPlaylist} |
||||
onSelect={onSelect} |
||||
/> |
||||
</DropdownSection> |
||||
<DropdownSection |
||||
itemsCount={playersCount} |
||||
title={playlists.lexics?.players} |
||||
> |
||||
<List> |
||||
<PlayersPlaylists |
||||
teamName={profile?.team1} |
||||
players={playlists.players.team1} |
||||
selectedMathPlaylist={selectedPlaylist} |
||||
onSelect={onSelect} |
||||
/> |
||||
<PlayersPlaylists |
||||
teamName={profile?.team2} |
||||
players={playlists.players.team2} |
||||
selectedMathPlaylist={selectedPlaylist} |
||||
onSelect={onSelect} |
||||
/> |
||||
</List> |
||||
</DropdownSection> |
||||
</DropdownWrapper> |
||||
</Container> |
||||
</Wrapper> |
||||
) |
||||
} |
||||
|
||||
@ -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<ButtonProps>` |
||||
${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; |
||||
` |
||||
Loading…
Reference in new issue