1 import moment from 'moment';
2 import PropTypes from 'prop-types';
3 import React from 'react';
4 import { ListGroup } from 'react-bootstrap';
5 import { Trans, withTranslation } from 'react-i18next';
7 import Icon from '../common/Icon';
8 import Spoiler from '../common/Spoiler';
9 import { formatTime } from '../../helpers/Result';
10 import { getUserName } from '../../helpers/User';
11 import i18n from '../../i18n';
13 const getEntryDate = entry => {
14 const dateStr = moment(entry.created_at).fromNow();
16 ? `${entry.user.username} ${dateStr}`
20 const getEntryDetailsUsername = entry => {
21 if (!entry || !entry.details || !entry.details.user) return 'Anonymous';
22 return getUserName(entry.details.user);
25 const getEntryRoundNumber = entry =>
26 (entry && entry.details && entry.details.round && entry.details.round.number) || '?';
28 const getEntryResultComment = entry => {
29 if (!entry || !entry.details || !entry.details.result || !entry.details.result.comment) {
32 return entry.details.result.comment;
35 const getEntryResultTime = entry => {
36 if (!entry || !entry.details || !entry.details.result) return 'ERROR';
37 const result = entry.details.result;
38 if (result.forfeit) return 'DNF XX';
39 return formatTime(result);
42 const getEntryDescription = entry => {
44 case 'application.accepted':
45 case 'application.received':
46 case 'application.rejected':
48 `protocol.description.${entry.type}`,
51 username: getEntryDetailsUsername(entry),
54 case 'result.comment': {
55 const comment = getEntryResultComment(entry);
56 const number = getEntryRoundNumber(entry);
57 return <Trans i18nKey={`protocol.description.${entry.type}`}>
59 <Spoiler>{{comment}}</Spoiler>,
62 case 'result.report': {
63 const number = getEntryRoundNumber(entry);
64 const time = getEntryResultTime(entry);
65 return <Trans i18nKey={`protocol.description.${entry.type}`}>
67 <Spoiler>{{time}}</Spoiler>,
76 `protocol.description.${entry.type}`,
79 number: getEntryRoundNumber(entry),
82 case 'tournament.close':
83 case 'tournament.discord':
84 case 'tournament.lock':
85 case 'tournament.open':
86 case 'tournament.settings':
87 case 'tournament.unlock':
89 `protocol.description.${entry.type}`,
93 return i18n.t('protocol.description.unknown', entry);
97 const getEntryIcon = entry => {
100 return <Icon.RESULT />;
104 case 'tournament.close':
105 case 'tournament.lock':
106 return <Icon.LOCKED />;
108 case 'tournament.open':
109 case 'tournament.unlock':
110 return <Icon.UNLOCKED />;
111 case 'tournament.discord':
112 return <Icon.DISCORD />;
114 return <Icon.PROTOCOL />;
118 const Item = ({ entry }) =>
119 <ListGroup.Item className="d-flex align-items-center">
120 <div className="pe-3 text-muted">
121 {getEntryIcon(entry)}
125 {getEntryDescription(entry)}
128 className="text-muted"
129 title={moment(entry.created_at).format('LLLL')}
131 {getEntryDate(entry)}
137 entry: PropTypes.shape({
138 created_at: PropTypes.string,
142 Item.defaultProps = {
146 export default withTranslation()(Item);