1 import PropTypes from 'prop-types';
2 import React from 'react';
3 import { Button } from 'react-bootstrap';
4 import { useTranslation } from 'react-i18next';
5 import { Link } from 'react-router-dom';
7 import Channels from './Channels';
8 import Crew from './Crew';
9 import MultiLink from './MultiLink';
10 import Players from './Players';
11 import Icon from '../common/Icon';
12 import { hasPassed, hasSGRestream, isActive } from '../../helpers/Episode';
13 import { getLink } from '../../helpers/Event';
14 import { canApplyForEpisode, canRestreamEpisode } from '../../helpers/permissions';
15 import { withUser } from '../../helpers/UserContext';
17 const Item = ({ episode, onAddRestream, onApply, onEditRestream, user }) => {
18 const { t } = useTranslation();
27 if (isActive(episode)) {
28 classNames.push('is-active');
31 const style = React.useMemo(() => {
32 if (episode.event && episode.event.corner) {
34 backgroundImage: `url(${episode.event.corner})`,
38 }, [episode.event && episode.event.corner]);
40 const hasChannels = episode.channels && episode.channels.length;
41 const hasPlayers = episode.players && episode.players.length;
43 return <div className={classNames.join(' ')} style={style}>
44 <div className="d-flex align-items-stretch">
45 <div className="episode-start me-3 fs-5 fs-md-4 text-end">
46 {t('schedule.startTime', { date: new Date(episode.start) })}
48 <div className="episode-titlebar">
49 {episode.title || episode.event ?
50 <div className="episode-title fs-5 fs-md-4">
51 {episode.title || episode.event.title}
55 <div className="episode-comment">
60 <div className="episode-channel-links ms-auto text-end">
63 channels={episode.channels}
65 onEditRestream={onEditRestream}
68 {!hasChannels && hasPlayers ?
69 <MultiLink players={episode.players} />
74 href={episode.raceroom}
76 title={t('episodes.raceroom')}
77 variant="outline-secondary"
79 <Icon.RACETIME title="" />
81 {t('episodes.raceroom')}
85 {onAddRestream && canRestreamEpisode(user, episode) ?
88 onClick={() => onAddRestream(episode)}
89 title={t('episodes.addRestream')}
90 variant="outline-secondary"
98 <div className="episode-body d-flex flex-column flex-fill">
100 <Players players={episode.players} />
102 {(episode.crew && episode.crew.length) || (!hasPassed(episode) && (
103 hasSGRestream(episode)
104 || canApplyForEpisode(user, episode, 'commentary')
105 || canApplyForEpisode(user, episode, 'tracking')
107 <div className="mb-3">
108 <Crew episode={episode} onApply={onApply} />
112 <div className="episode-event mt-auto">
113 {episode.event.description_id ?
114 <Link className="event-link" to={getLink(episode.event)}>
115 {episode.event.title}
127 episode: PropTypes.shape({
128 channels: PropTypes.arrayOf(PropTypes.shape({
130 comment: PropTypes.string,
131 crew: PropTypes.arrayOf(PropTypes.shape({
133 event: PropTypes.shape({
134 corner: PropTypes.string,
135 description_id: PropTypes.number,
136 name: PropTypes.string,
137 title: PropTypes.string,
139 players: PropTypes.arrayOf(PropTypes.shape({
141 raceroom: PropTypes.string,
142 start: PropTypes.string,
143 title: PropTypes.string,
145 onAddRestream: PropTypes.func,
146 onApply: PropTypes.func,
147 onEditRestream: PropTypes.func,
148 user: PropTypes.shape({
152 export default withUser(Item);