Ott 693 popup live mathes copy (#269)
* feat: 🎸 OTT-693 add popup * feat: 🎸 OTT-693 fix style * feat: 🎸 OTT-693 fix style * feat: 🎸 OTT-693 some fix Co-authored-by: Zoia <zizi2405@yandex.ru>keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
parent
bc277fa65d
commit
f6fe9d217b
@ -0,0 +1,52 @@ |
|||||||
|
import { Fragment } from 'react' |
||||||
|
|
||||||
|
import { Background } from 'features/Background' |
||||||
|
import { MediaQuery } from 'features/MediaQuery' |
||||||
|
import { useMatchPopupStore } from 'features/MatchPopup' |
||||||
|
|
||||||
|
import { SettingsPage } from '../../components/SettingsPage' |
||||||
|
import { FinishedPlaylistPage } from '../../components/FinishedPlaylistPage' |
||||||
|
import { PopupPages } from '../../types' |
||||||
|
import { Modal } from './styled' |
||||||
|
|
||||||
|
export * from '../../store' |
||||||
|
|
||||||
|
export const FinishedMatchPopup = () => { |
||||||
|
const { |
||||||
|
closePopup, |
||||||
|
isOpen, |
||||||
|
matchPlaylists, |
||||||
|
page, |
||||||
|
} = useMatchPopupStore() |
||||||
|
|
||||||
|
const showPopup = isOpen && Boolean(matchPlaylists) |
||||||
|
|
||||||
|
const pageElement = page === PopupPages.PLAYLIST |
||||||
|
? <FinishedPlaylistPage /> |
||||||
|
: <SettingsPage /> |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<MediaQuery minDevice='tablet'> |
||||||
|
<Modal |
||||||
|
close={closePopup} |
||||||
|
isOpen={showPopup} |
||||||
|
withCloseButton={false} |
||||||
|
> |
||||||
|
{pageElement} |
||||||
|
</Modal> |
||||||
|
</MediaQuery> |
||||||
|
|
||||||
|
<MediaQuery maxDevice='mobile'> |
||||||
|
<Modal |
||||||
|
isOpen={showPopup} |
||||||
|
withCloseButton={false} |
||||||
|
> |
||||||
|
<Background> |
||||||
|
{pageElement} |
||||||
|
</Background> |
||||||
|
</Modal> |
||||||
|
</MediaQuery> |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { devices } from 'config' |
||||||
|
|
||||||
|
import { Modal as BaseModal } from 'features/Modal' |
||||||
|
import { ModalWindow } from 'features/Modal/styled' |
||||||
|
|
||||||
|
export const Modal = styled(BaseModal)` |
||||||
|
background-color: rgba(0, 0, 0, 0.7); |
||||||
|
|
||||||
|
${ModalWindow} { |
||||||
|
width: 1222px; |
||||||
|
height: 818px; |
||||||
|
padding: 20px 0; |
||||||
|
background-color: #3F3F3F; |
||||||
|
border-radius: 5px; |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
width: 100vw; |
||||||
|
height: 100vh; |
||||||
|
padding: 0; |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
} |
||||||
|
` |
||||||
@ -0,0 +1,73 @@ |
|||||||
|
import { useState, useEffect } from 'react' |
||||||
|
|
||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { devices, PAGES } from 'config' |
||||||
|
import { getSportLexic } from 'helpers' |
||||||
|
import { getMatchLastWatchSeconds, LastPlayPosition } from 'requests' |
||||||
|
|
||||||
|
import { useMatchPopupStore } from 'features/MatchPopup/store' |
||||||
|
|
||||||
|
import { SimplePlaylistButton } from '../SimplePlaylistButton' |
||||||
|
|
||||||
|
const List = styled.ul` |
||||||
|
margin: 40px auto 0px auto; |
||||||
|
width: 100%; |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
margin: 12px auto; |
||||||
|
padding: 0 12px; |
||||||
|
} |
||||||
|
` |
||||||
|
const Item = styled.li` |
||||||
|
margin-bottom: 15px; |
||||||
|
width: 100%; |
||||||
|
height: 50px; |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
height: 36px; |
||||||
|
margin-bottom: 12px; |
||||||
|
} |
||||||
|
` |
||||||
|
export const LiveMatchPlaylist = () => { |
||||||
|
const [lastPlayPosition, setLastPlayPosition] = useState<LastPlayPosition | null>(null) |
||||||
|
const { match, matchPlaylists } = useMatchPopupStore() |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (match) { |
||||||
|
getMatchLastWatchSeconds(match?.sportType, match?.id) |
||||||
|
.then((lastPlayPositionSecond) => setLastPlayPosition(lastPlayPositionSecond)) |
||||||
|
} |
||||||
|
}, [match]) |
||||||
|
|
||||||
|
if (!match || !matchPlaylists) return null |
||||||
|
|
||||||
|
const sport = getSportLexic(match.sportType) |
||||||
|
return ( |
||||||
|
<List> |
||||||
|
<Item> |
||||||
|
<SimplePlaylistButton |
||||||
|
to={`${sport}${PAGES.match}/${match.id}`} |
||||||
|
title='watch_live_stream' |
||||||
|
/> |
||||||
|
</Item> |
||||||
|
<Item> |
||||||
|
<SimplePlaylistButton |
||||||
|
to={`${sport}${PAGES.match}/${match.id}`} |
||||||
|
title='watch_from_beginning' |
||||||
|
/> |
||||||
|
</Item> |
||||||
|
{lastPlayPosition?.second |
||||||
|
? ( |
||||||
|
<Item> |
||||||
|
<SimplePlaylistButton |
||||||
|
to={`${sport}${PAGES.match}/${match.id}`} |
||||||
|
title='watch_from' |
||||||
|
startWatch={lastPlayPosition?.second} |
||||||
|
/> |
||||||
|
</Item> |
||||||
|
) |
||||||
|
: null} |
||||||
|
</List> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
import { Fragment } from 'react' |
||||||
|
|
||||||
|
import { Background } from 'features/Background' |
||||||
|
import { MediaQuery } from 'features/MediaQuery' |
||||||
|
import { useMatchPopupStore } from 'features/MatchPopup' |
||||||
|
|
||||||
|
import { LivePlaylistPage } from '../LivePlaylistPage' |
||||||
|
|
||||||
|
import { Modal } from './styled' |
||||||
|
|
||||||
|
export const LiveMatchPopup = () => { |
||||||
|
const { |
||||||
|
closePopup, |
||||||
|
isOpen, |
||||||
|
} = useMatchPopupStore() |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<MediaQuery minDevice='tablet'> |
||||||
|
<Modal |
||||||
|
close={closePopup} |
||||||
|
isOpen={isOpen} |
||||||
|
withCloseButton={false} |
||||||
|
> |
||||||
|
<LivePlaylistPage /> |
||||||
|
</Modal> |
||||||
|
</MediaQuery> |
||||||
|
|
||||||
|
<MediaQuery maxDevice='mobile'> |
||||||
|
<Modal |
||||||
|
isOpen={isOpen} |
||||||
|
withCloseButton={false} |
||||||
|
> |
||||||
|
<Background> |
||||||
|
<LivePlaylistPage /> |
||||||
|
</Background> |
||||||
|
</Modal> |
||||||
|
</MediaQuery> |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { devices } from 'config' |
||||||
|
|
||||||
|
import { Modal as BaseModal } from 'features/Modal' |
||||||
|
import { ModalWindow } from 'features/Modal/styled' |
||||||
|
|
||||||
|
export const Modal = styled(BaseModal)` |
||||||
|
background-color: rgba(0, 0, 0, 0.7); |
||||||
|
|
||||||
|
${ModalWindow} { |
||||||
|
width: 565px; |
||||||
|
min-height: 310px; |
||||||
|
padding: 20px 35px; |
||||||
|
background-color: #3F3F3F; |
||||||
|
border-radius: 5px; |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
width: 100vw; |
||||||
|
height: 100vh; |
||||||
|
padding: 0; |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
} |
||||||
|
` |
||||||
@ -0,0 +1,39 @@ |
|||||||
|
import { Name } from 'features/Name' |
||||||
|
import { useMatchPopupStore } from 'features/MatchPopup' |
||||||
|
|
||||||
|
import { CloseButton } from '../CloseButton' |
||||||
|
import { LiveMatchPlaylist } from '../LiveMatchPlaylist' |
||||||
|
|
||||||
|
import { |
||||||
|
Content, |
||||||
|
Header, |
||||||
|
HeaderActions, |
||||||
|
HeaderTitle, |
||||||
|
} from './styled' |
||||||
|
|
||||||
|
export const LivePlaylistPage = () => { |
||||||
|
const { match, matchPlaylists } = useMatchPopupStore() |
||||||
|
if (!match) return null |
||||||
|
|
||||||
|
const { team1, team2 } = match |
||||||
|
|
||||||
|
return ( |
||||||
|
<Content> |
||||||
|
<Header> |
||||||
|
<HeaderTitle> |
||||||
|
<Name nameObj={team1} /> |
||||||
|
{' '} — {' '} |
||||||
|
<Name nameObj={team2} /> |
||||||
|
</HeaderTitle> |
||||||
|
|
||||||
|
<HeaderActions> |
||||||
|
<CloseButton /> |
||||||
|
</HeaderActions> |
||||||
|
</Header> |
||||||
|
|
||||||
|
{ |
||||||
|
matchPlaylists && <LiveMatchPlaylist /> |
||||||
|
} |
||||||
|
</Content> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,39 @@ |
|||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { customScrollbar } from 'features/Common' |
||||||
|
|
||||||
|
export const Content = styled.div` |
||||||
|
width: 495px; |
||||||
|
height: 100%; |
||||||
|
overflow-y: auto; |
||||||
|
${customScrollbar} |
||||||
|
` |
||||||
|
|
||||||
|
export const Header = styled.div` |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
` |
||||||
|
|
||||||
|
export const HeaderActions = styled.div` |
||||||
|
position: absolute; |
||||||
|
display: flex; |
||||||
|
top: 20px; |
||||||
|
right: 20px; |
||||||
|
` |
||||||
|
|
||||||
|
export const HeaderTitle = styled.h2` |
||||||
|
margin: 0 auto; |
||||||
|
width: 70%; |
||||||
|
font-weight: 600; |
||||||
|
font-size: 24px; |
||||||
|
line-height: 42px; |
||||||
|
color: #FFFFFF; |
||||||
|
text-align: center; |
||||||
|
` |
||||||
|
|
||||||
|
export const BlockTitle = styled.h3` |
||||||
|
font-weight: normal; |
||||||
|
font-size: 24px; |
||||||
|
line-height: 50px; |
||||||
|
text-transform: capitalize; |
||||||
|
` |
||||||
@ -0,0 +1,88 @@ |
|||||||
|
import type { MouseEvent } from 'react' |
||||||
|
import { Link } from 'react-router-dom' |
||||||
|
|
||||||
|
import styled from 'styled-components/macro' |
||||||
|
|
||||||
|
import { devices } from 'config' |
||||||
|
import { secondsToHms } from 'helpers' |
||||||
|
|
||||||
|
import { T9n } from 'features/T9n' |
||||||
|
|
||||||
|
const StyledLink = styled(Link)` |
||||||
|
border: none; |
||||||
|
cursor: pointer; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
padding: 0 25px; |
||||||
|
background: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.1) 0%, |
||||||
|
rgba(255, 255, 255, 0) 100% |
||||||
|
), |
||||||
|
#5c5c5c; |
||||||
|
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); |
||||||
|
border-radius: 2px; |
||||||
|
|
||||||
|
:hover { |
||||||
|
background-color: #555555; |
||||||
|
} |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
justify-content: center; |
||||||
|
border-radius: 5px; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
const Title = styled.span` |
||||||
|
font-weight: 500; |
||||||
|
font-size: 20px; |
||||||
|
line-height: 50px; |
||||||
|
letter-spacing: 0.03em; |
||||||
|
color: #ffffff; |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
font-size: 17px; |
||||||
|
line-height: 16px; |
||||||
|
margin-right: 16px; |
||||||
|
text-transform: none; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
const Duration = styled(Title)` |
||||||
|
font-weight: 300; |
||||||
|
font-size: 24px; |
||||||
|
letter-spacing: 0.05em; |
||||||
|
|
||||||
|
@media ${devices.mobile} { |
||||||
|
font-size: 17px; |
||||||
|
line-height: 16px; |
||||||
|
text-transform: none; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
const stopPropagation = (e: MouseEvent<HTMLAnchorElement>) => e.stopPropagation() |
||||||
|
|
||||||
|
type Props = { |
||||||
|
duration?: number, |
||||||
|
startWatch?: number, |
||||||
|
title: string, |
||||||
|
to: string, |
||||||
|
} |
||||||
|
|
||||||
|
export const SimplePlaylistButton = ({ |
||||||
|
duration, |
||||||
|
startWatch, |
||||||
|
title, |
||||||
|
to, |
||||||
|
}: Props) => ( |
||||||
|
<StyledLink to={to} onClick={stopPropagation}> |
||||||
|
<Title> |
||||||
|
<T9n t={title} /> {startWatch && secondsToHms(startWatch)} |
||||||
|
</Title> |
||||||
|
{duration && <Duration>{secondsToHms(duration)}</Duration>} |
||||||
|
</StyledLink> |
||||||
|
) |
||||||
@ -1,52 +1,12 @@ |
|||||||
import { Fragment } from 'react' |
|
||||||
|
|
||||||
import { Background } from 'features/Background' |
|
||||||
import { MediaQuery } from 'features/MediaQuery' |
|
||||||
import { useMatchPopupStore } from 'features/MatchPopup' |
import { useMatchPopupStore } from 'features/MatchPopup' |
||||||
|
|
||||||
import { SettingsPage } from './components/SettingsPage' |
import { FinishedMatchPopup } from './components/FinishedMatchPopup' |
||||||
import { PlaylistPage } from './components/PlaylistPage' |
import { LiveMatchPopup } from './components/LiveMatchPopup' |
||||||
import { PopupPages } from './types' |
|
||||||
import { Modal } from './styled' |
|
||||||
|
|
||||||
export * from './store' |
export * from './store' |
||||||
|
|
||||||
export const MatchPopup = () => { |
export const MatchPopup = () => { |
||||||
const { |
const { match } = useMatchPopupStore() |
||||||
closePopup, |
|
||||||
isOpen, |
|
||||||
matchPlaylists, |
|
||||||
page, |
|
||||||
} = useMatchPopupStore() |
|
||||||
|
|
||||||
const showPopup = isOpen && Boolean(matchPlaylists) |
|
||||||
|
|
||||||
const pageElement = page === PopupPages.PLAYLIST |
|
||||||
? <PlaylistPage /> |
|
||||||
: <SettingsPage /> |
|
||||||
|
|
||||||
return ( |
|
||||||
<Fragment> |
|
||||||
<MediaQuery minDevice='tablet'> |
|
||||||
<Modal |
|
||||||
close={closePopup} |
|
||||||
isOpen={showPopup} |
|
||||||
withCloseButton={false} |
|
||||||
> |
|
||||||
{pageElement} |
|
||||||
</Modal> |
|
||||||
</MediaQuery> |
|
||||||
|
|
||||||
<MediaQuery maxDevice='mobile'> |
return match?.live ? <LiveMatchPopup /> : <FinishedMatchPopup /> |
||||||
<Modal |
|
||||||
isOpen={showPopup} |
|
||||||
withCloseButton={false} |
|
||||||
> |
|
||||||
<Background> |
|
||||||
{pageElement} |
|
||||||
</Background> |
|
||||||
</Modal> |
|
||||||
</MediaQuery> |
|
||||||
</Fragment> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
|||||||
Loading…
Reference in new issue