]> git.localhorst.tv Git - alttp.git/blob - resources/js/components/protocol/Item.js
tracker items as svg
[alttp.git] / resources / js / components / protocol / Item.js
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';
6
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';
12
13 const getEntryDate = entry => {
14         const dateStr = moment(entry.created_at).fromNow();
15         return entry.user
16                 ? `${entry.user.username} ${dateStr}`
17                 : dateStr;
18 };
19
20 const getEntryDetailsUsername = entry => {
21         if (!entry || !entry.details || !entry.details.user) return 'Anonymous';
22         return getUserName(entry.details.user);
23 };
24
25 const getEntryRoundNumber = entry =>
26         (entry && entry.details && entry.details.round && entry.details.round.number) || '?';
27
28 const getEntryResultComment = entry => {
29         if (!entry || !entry.details || !entry.details.result || !entry.details.result.comment) {
30                 return '';
31         }
32         return entry.details.result.comment;
33 };
34
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);
40 };
41
42 const getEntryDescription = entry => {
43         switch (entry.type) {
44                 case 'application.accepted':
45                 case 'application.received':
46                 case 'application.rejected':
47                         return i18n.t(
48                                 `protocol.description.${entry.type}`,
49                                 {
50                                         ...entry,
51                                         username: getEntryDetailsUsername(entry),
52                                 },
53                         );
54                 case 'result.comment': {
55                         const comment = getEntryResultComment(entry);
56                         const number = getEntryRoundNumber(entry);
57                         return <Trans i18nKey={`protocol.description.${entry.type}`}>
58                                 {{number}}
59                                 <Spoiler>{{comment}}</Spoiler>,
60                         </Trans>;
61                 }
62                 case 'result.report': {
63                         const number = getEntryRoundNumber(entry);
64                         const time = getEntryResultTime(entry);
65                         return <Trans i18nKey={`protocol.description.${entry.type}`}>
66                                 {{number}}
67                                 <Spoiler>{{time}}</Spoiler>,
68                         </Trans>;
69                 }
70                 case 'round.create':
71                 case 'round.edit':
72                 case 'round.lock':
73                 case 'round.seed':
74                 case 'round.unlock':
75                         return i18n.t(
76                                 `protocol.description.${entry.type}`,
77                                 {
78                                         ...entry,
79                                         number: getEntryRoundNumber(entry),
80                                 },
81                         );
82                 case 'tournament.close':
83                 case 'tournament.discord':
84                 case 'tournament.lock':
85                 case 'tournament.open':
86                 case 'tournament.settings':
87                 case 'tournament.unlock':
88                         return i18n.t(
89                                 `protocol.description.${entry.type}`,
90                                 entry,
91                         );
92                 default:
93                         return i18n.t('protocol.description.unknown', entry);
94         }
95 };
96
97 const getEntryIcon = entry => {
98         switch (entry.type) {
99                 case 'result.report':
100                         return <Icon.RESULT />;
101                 case 'round.create':
102                         return <Icon.ADD />;
103                 case 'round.lock':
104                 case 'tournament.close':
105                 case 'tournament.lock':
106                         return <Icon.LOCKED />;
107                 case 'round.unlock':
108                 case 'tournament.open':
109                 case 'tournament.unlock':
110                         return <Icon.UNLOCKED />;
111                 case 'tournament.discord':
112                         return <Icon.DISCORD />;
113                 default:
114                         return <Icon.PROTOCOL />;
115         }
116 };
117
118 const Item = ({ entry }) =>
119         <ListGroup.Item className="d-flex align-items-center">
120                 <div className="pe-3 text-muted">
121                         {getEntryIcon(entry)}
122                 </div>
123                 <div>
124                         <div>
125                                 {getEntryDescription(entry)}
126                         </div>
127                         <div
128                                 className="text-muted"
129                                 title={moment(entry.created_at).format('LLLL')}
130                         >
131                                 {getEntryDate(entry)}
132                         </div>
133                 </div>
134         </ListGroup.Item>;
135
136 Item.propTypes = {
137         entry: PropTypes.shape({
138                 created_at: PropTypes.string,
139         }),
140 };
141
142 Item.defaultProps = {
143         entry: {},
144 };
145
146 export default withTranslation()(Item);