import { h, Fragment } from 'preact' import { zonedTimeToUtc, utcToZonedTime, format } from 'date-fns-tz' import { bool, func, instanceOf, string } from 'prop-types' import styled from 'styled-components' import { colours, textSizes } from '../../assets/theme' import config from '../../data/config' import Markdown from '../../components/Markdown' import Logo from '../../components/Logo' import translations from '../../data/strings' import CrossSvg from '../../components/Svg/Cross' import { H1, H2, Span, Label } from '../../components/Text' import Link from '../../components/Link' import Button from '../../components/Button' import { slugify } from '../../helpers/string' import { ButtonsRows } from '../../components/EpisodeCard' export const TrailerContainer = styled.div` height: 22em; 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; flex-wrap: ${props => props.$wrap ? 'wrap' : 'nowrap'}; a { display: block; width: 50%; &:not(:last-of-type) { margin-right: 16px; } } ` 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; } ` 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; margin: 0 0 0 2px; padding-bottom: 3em; button { margin-top: 16px; } p { margin-left: 2px; } ` const VCImg = styled.img` width: 100%; margin-bottom: 8px; ` const ItemTitleWrapper = styled.div` margin-bottom: 1em; ` 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>) export const EpisodeCard = ({ title, image, description, beginsOn, endsOn, url, hasPassed, videoUrl, onClickButton, tzShort, theme, peertubeReplay, id }) => { const startDate = new Date(beginsOn) const utcDate = zonedTimeToUtc(startDate, 'Europe/Berlin') const { timeZone } = Intl.DateTimeFormat().resolvedOptions() const zonedDate = utcToZonedTime(utcDate, timeZone) return ( <VCWrapper id={id}> <DateLabel size={textSizes.lg} colour={theme.foreground}> {`${hasPassed ? translations.en.streamDatePast : ''}`} <Span bold colour={theme.foreground}> {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> <VCImg src={image} alt="" /> </LinkBlock> ) : ( <Fragment> <ItemTitleWrapper>{renderTitles(title)}</ItemTitleWrapper> <VCImg src={image} alt="" /> </Fragment> )} <Markdown theme={theme}>{description}</Markdown> {hasPassed ? ( <a href={peertubeReplay.url || url}><Button>{peertubeReplay.url ? translations.en.watchEpisode : translations.en.eventDetails}</Button></a> ) : ( <ButtonsRows title={title} description={description} beginsOn={beginsOn} endsOn={endsOn} url={url} /> )} </VCWrapper> ) } EpisodeCard.propTypes = { description: string, beginsOn: instanceOf(Date), onClickButton: func, tzShort: string, hasPassed: bool, videoUrl: string, }