gdq-archive/frontend/components/VideoListItem.tsx

167 lines
5.2 KiB
TypeScript

/**
* Copyright (C) 2019-2021 Carl Kittelberger <icedream@icedream.pw>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { ReactElement } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import ListGroup from 'react-bootstrap/ListGroup';
import Image from 'react-bootstrap/Image';
import Link from 'next/link';
import { RunInformation, Thumbnails } from 'util/datatypes/VideoList';
import { Runner as RunnerData, RunnerList } from 'util/datatypes/RunnerList';
import { Col, Row } from 'react-bootstrap';
import { getThumbnailURL } from '../util/thumbnail';
import FormattedDuration from './localization/FormattedDuration';
import style from './VideoListItem.module.scss';
import hourglassImage from '../images/hourglass.svg';
import Runner from './Runner';
export default function VideoListItem({
thumbnailServerURL,
duration,
id,
slug,
title,
sourceVideoStart,
sourceVideoEnd,
runData,
runners,
thumbnails,
}: {
thumbnailServerURL: string,
duration: number | string,
id: string,
slug: string,
title: string,
sourceVideoStart: number | string,
sourceVideoEnd: number | string,
runData: RunInformation,
runners: RunnerList,
thumbnails: Thumbnails,
}) {
let displayDuration = null;
if (duration !== null) {
if (typeof duration === 'string') {
displayDuration = parseFloat(duration);
} else {
displayDuration = duration;
}
} else if (
sourceVideoStart !== null
&& sourceVideoEnd !== null
&& sourceVideoStart !== sourceVideoEnd
) {
let videoEnd: number;
if (typeof sourceVideoEnd === 'string') {
videoEnd = parseFloat(sourceVideoEnd);
} else {
videoEnd = sourceVideoEnd;
}
let videoStart: number;
if (typeof sourceVideoStart === 'string') {
videoStart = parseFloat(sourceVideoStart);
} else {
videoStart = sourceVideoStart;
}
displayDuration = videoEnd - videoStart;
}
const listGroupItem = (
<ListGroup.Item>
<Row>
<Col sm={3} xs={3}>
<Link href="/[id]/[vslug]" as={`/${id}/${slug}`}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<Image
className={style.thumbnail}
src={
thumbnails.length > 0
? getThumbnailURL(thumbnailServerURL, id, thumbnails[0].fileName)
: hourglassImage
}
srcSet={
Array.isArray(thumbnails) && thumbnails.length > 0
? thumbnails
.map(({
sourceSize,
fileName,
}) => (
[
thumbnails.length > 0
? getThumbnailURL(thumbnailServerURL, id, fileName)
: hourglassImage,
sourceSize,
]
))
.map((item) => item.join(' '))
.join(', ')
: ''
}
alt={title}
/>
</Link>
</Col>
<Col sm={4} xs={9}>
<Link href="/[id]/[vslug]" as={`/${id}/${slug}`} className="text-reset text-decoration-none">
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<div>
<div className={style['run-name']}>{title}</div>
<div className={[style['run-category'], 'mt-0'].join(' ')}>{runData?.category}</div>
</div>
</Link>
</Col>
<Col sm={5} xs={12}>
{runners && runners.length > 0 ? (
<div className="mr-2">
<FontAwesomeIcon icon="running" />
{' '}
{runners.reduce((all: Array<ReactElement>, runner: RunnerData) => [
...all,
all.length > 0 ? ' / ' : null,
<Runner key={runner.fields.name} runner={runner.fields} />,
], [])}
</div>
) : ''}
{displayDuration !== null ? (
<span className="mr-2 text-nowrap">
<FontAwesomeIcon icon="clock" />
{' '}
<FormattedDuration
seconds={displayDuration}
format="{hours} {minutes} {seconds}"
unitDisplay="short"
/>
</span>
) : (
<span className="mr-2 text-nowrap">
<FontAwesomeIcon icon="hourglass" />
{' '}
Coming up
</span>
)}
</Col>
</Row>
</ListGroup.Item>
);
return listGroupItem;
}