2021-10-11 13:50:24 +00:00
|
|
|
import { h, Fragment } from 'preact'
|
|
|
|
import { zonedTimeToUtc, utcToZonedTime, format } from 'date-fns-tz'
|
2021-10-11 17:15:09 +00:00
|
|
|
import { bool, func, instanceOf, string } from 'prop-types'
|
2021-10-11 13:50:24 +00:00
|
|
|
import styled from 'styled-components'
|
|
|
|
import { colours, textSizes } from '../../assets/theme'
|
|
|
|
import config from '../../data/config'
|
2021-10-11 17:15:09 +00:00
|
|
|
|
|
|
|
import Markdown from '../../components/Markdown'
|
2021-10-11 13:50:24 +00:00
|
|
|
import Logo from '../../components/Logo'
|
|
|
|
import translations from '../../data/strings'
|
|
|
|
import CrossSvg from '../../components/Svg/Cross'
|
|
|
|
|
2021-10-15 13:37:54 +00:00
|
|
|
import { H1, H2, Span, Label } from '../../components/Text'
|
|
|
|
import Link from '../../components/Link'
|
2021-10-11 13:50:24 +00:00
|
|
|
import Button from '../../components/Button'
|
2021-10-22 13:44:28 +00:00
|
|
|
import { slugify } from '../../helpers/string'
|
2021-10-25 14:56:04 +00:00
|
|
|
import { ButtonsRows } from '../../components/EpisodeCard'
|
2021-10-11 13:50:24 +00:00
|
|
|
|
|
|
|
export const TrailerContainer = styled.div`
|
2021-10-12 12:45:52 +00:00
|
|
|
height: 22em;
|
2021-10-11 13:50:24 +00:00
|
|
|
border: 1px solid ${colours.midnightDarker};
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
|
|
div {
|
|
|
|
padding: 1em 2em;
|
|
|
|
background-color: #ffffffba;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
label {
|
|
|
|
margin-left: 8px;
|
|
|
|
font-size: 20px;
|
|
|
|
}
|
|
|
|
|
|
|
|
:hover div {
|
|
|
|
background-color: #ffffff;
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
|
|
export const ActionButton = styled(Button)`
|
|
|
|
font-size: 18px;
|
|
|
|
`
|
|
|
|
|
|
|
|
export const Row = styled.div`
|
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
|
|
|
margin-bottom: 32px;
|
2021-11-01 22:34:29 +00:00
|
|
|
flex-wrap: ${props => props.$wrap ? 'wrap' : 'nowrap'};
|
2021-10-11 13:50:24 +00:00
|
|
|
|
|
|
|
a {
|
|
|
|
display: block;
|
|
|
|
width: 50%;
|
|
|
|
&:not(:last-of-type) {
|
|
|
|
margin-right: 16px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
2021-11-01 22:34:29 +00:00
|
|
|
export const LogosRow = styled(Row)`
|
|
|
|
align-items: center;
|
|
|
|
max-width: 600px;
|
|
|
|
justify-content: space-between;
|
|
|
|
padding: 32px 0 ;
|
|
|
|
|
|
|
|
a {
|
|
|
|
width: auto;
|
|
|
|
margin-right: 0;
|
|
|
|
|
|
|
|
&[href]:hover {
|
|
|
|
opacity: 0.7
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
img {
|
|
|
|
height: 64px;
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
2021-10-11 13:50:24 +00:00
|
|
|
export const InfoContent = styled.div`
|
|
|
|
max-width: 600px;
|
|
|
|
margin: 0 0 0em 2px;
|
|
|
|
padding-bottom: 1em;
|
|
|
|
|
|
|
|
h1 {
|
|
|
|
display: none;
|
|
|
|
|
|
|
|
&:last-of-type {
|
|
|
|
margin-bottom: 32px;
|
|
|
|
}
|
|
|
|
@media screen and (max-width: 1000px) {
|
|
|
|
display: block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
export const PositionedLogo = styled(Logo)`
|
|
|
|
margin-bottom: 64px;
|
|
|
|
`
|
|
|
|
|
|
|
|
export const TaglineContainer = styled.div`
|
|
|
|
h1 {
|
|
|
|
margin-top: 32px;
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
export const Title = styled(H1)`
|
|
|
|
margin: 0.3em 0;
|
|
|
|
`
|
|
|
|
|
|
|
|
export const PositionedCross = styled(CrossSvg)`
|
|
|
|
position: fixed;
|
|
|
|
right: 2.5em;
|
|
|
|
top: 2em;
|
|
|
|
cursor: pointer;
|
|
|
|
stroke: ${colours.midnightDarker};
|
|
|
|
z-index: 5;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
opacity: 0.5;
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
export const VCWrapper = styled.div`
|
|
|
|
max-width: 600px;
|
2021-10-15 13:37:54 +00:00
|
|
|
margin: 0 0 0 2px;
|
|
|
|
padding-bottom: 3em;
|
2021-10-11 13:50:24 +00:00
|
|
|
|
|
|
|
button {
|
|
|
|
margin-top: 16px;
|
|
|
|
}
|
|
|
|
|
|
|
|
p {
|
|
|
|
margin-left: 2px;
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
const VCImg = styled.img`
|
|
|
|
width: 100%;
|
|
|
|
margin-bottom: 8px;
|
|
|
|
`
|
|
|
|
|
|
|
|
const ItemTitleWrapper = styled.div`
|
2021-10-12 12:45:52 +00:00
|
|
|
margin-bottom: 1em;
|
2021-10-11 13:50:24 +00:00
|
|
|
`
|
|
|
|
|
|
|
|
const DateLabel = styled(Label)`
|
|
|
|
margin: 1em 0;
|
|
|
|
display: block;
|
|
|
|
`
|
|
|
|
|
|
|
|
const LinkBlock = styled(Link)`
|
|
|
|
display: block;
|
|
|
|
width: 100%;
|
|
|
|
`
|
|
|
|
|
|
|
|
const renderTitles = titles =>
|
|
|
|
titles.split('\\n').map(title => <H2 key={title}>{title}</H2>)
|
2021-10-11 17:15:09 +00:00
|
|
|
export const EpisodeCard = ({
|
2021-10-11 13:50:24 +00:00
|
|
|
title,
|
2021-10-15 13:37:54 +00:00
|
|
|
image,
|
2021-10-11 13:50:24 +00:00
|
|
|
description,
|
2021-10-11 17:15:09 +00:00
|
|
|
beginsOn,
|
2021-10-25 14:56:04 +00:00
|
|
|
endsOn,
|
|
|
|
url,
|
2021-10-11 13:50:24 +00:00
|
|
|
hasPassed,
|
|
|
|
videoUrl,
|
|
|
|
onClickButton,
|
|
|
|
tzShort,
|
2021-10-12 12:45:52 +00:00
|
|
|
theme,
|
2021-11-01 22:34:29 +00:00
|
|
|
peertubeReplay,
|
2021-10-22 13:44:28 +00:00
|
|
|
id
|
2021-10-11 13:50:24 +00:00
|
|
|
}) => {
|
2021-10-11 17:15:09 +00:00
|
|
|
const startDate = new Date(beginsOn)
|
2021-10-11 13:50:24 +00:00
|
|
|
const utcDate = zonedTimeToUtc(startDate, 'Europe/Berlin')
|
|
|
|
|
|
|
|
const { timeZone } = Intl.DateTimeFormat().resolvedOptions()
|
|
|
|
const zonedDate = utcToZonedTime(utcDate, timeZone)
|
|
|
|
return (
|
2021-10-22 13:44:28 +00:00
|
|
|
<VCWrapper id={id}>
|
2021-10-12 12:45:52 +00:00
|
|
|
<DateLabel size={textSizes.lg} colour={theme.foreground}>
|
2021-10-11 13:50:24 +00:00
|
|
|
{`${hasPassed ? translations.en.streamDatePast : ''}`}
|
2021-10-12 12:45:52 +00:00
|
|
|
<Span bold colour={theme.foreground}>
|
2021-10-11 13:50:24 +00:00
|
|
|
{hasPassed
|
|
|
|
? format(zonedDate, 'dd/MM/yy')
|
|
|
|
: `${format(zonedDate, 'do LLLL y // HH:mm')} ${tzShort}`}
|
|
|
|
</Span>
|
|
|
|
</DateLabel>
|
|
|
|
{videoUrl && hasPassed ? (
|
|
|
|
<LinkBlock href={videoUrl}>
|
|
|
|
<ItemTitleWrapper>{renderTitles(title)}</ItemTitleWrapper>
|
2021-10-11 17:15:09 +00:00
|
|
|
<VCImg src={image} alt="" />
|
2021-10-11 13:50:24 +00:00
|
|
|
</LinkBlock>
|
|
|
|
) : (
|
|
|
|
<Fragment>
|
|
|
|
<ItemTitleWrapper>{renderTitles(title)}</ItemTitleWrapper>
|
2021-10-11 17:15:09 +00:00
|
|
|
<VCImg src={image} alt="" />
|
2021-10-11 13:50:24 +00:00
|
|
|
</Fragment>
|
|
|
|
)}
|
2021-11-11 11:29:11 +00:00
|
|
|
<Markdown withLinebreaks theme={theme}>{description}</Markdown>
|
2021-10-11 13:50:24 +00:00
|
|
|
{hasPassed ? (
|
2021-11-01 22:34:29 +00:00
|
|
|
<a href={peertubeReplay.url || url}><Button>{peertubeReplay.url ? translations.en.watchEpisode : translations.en.eventDetails}</Button></a>
|
2021-10-11 13:50:24 +00:00
|
|
|
) : (
|
2021-10-25 14:56:04 +00:00
|
|
|
<ButtonsRows title={title} description={description} beginsOn={beginsOn} endsOn={endsOn} url={url} />
|
2021-10-11 13:50:24 +00:00
|
|
|
)}
|
|
|
|
</VCWrapper>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-10-11 17:15:09 +00:00
|
|
|
EpisodeCard.propTypes = {
|
2021-10-11 13:50:24 +00:00
|
|
|
description: string,
|
2021-10-11 17:15:09 +00:00
|
|
|
beginsOn: instanceOf(Date),
|
|
|
|
onClickButton: func,
|
|
|
|
tzShort: string,
|
2021-10-11 13:50:24 +00:00
|
|
|
hasPassed: bool,
|
|
|
|
videoUrl: string,
|
|
|
|
}
|