From 8d97d023740e438361e659c6e133418e33343178 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Wed, 6 Apr 2022 15:35:15 +0200 Subject: [PATCH] clickable results --- .../js/components/results/DetailDialog.js | 95 +++++++++++++++++++ resources/js/components/results/Item.js | 55 ++++------- resources/js/helpers/Result.js | 37 ++++++++ resources/js/i18n/de.js | 8 ++ resources/js/i18n/en.js | 8 ++ resources/sass/results.scss | 9 ++ 6 files changed, 173 insertions(+), 39 deletions(-) create mode 100644 resources/js/components/results/DetailDialog.js diff --git a/resources/js/components/results/DetailDialog.js b/resources/js/components/results/DetailDialog.js new file mode 100644 index 0000000..368575b --- /dev/null +++ b/resources/js/components/results/DetailDialog.js @@ -0,0 +1,95 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { Button, Col, Form, Modal, Row } from 'react-bootstrap'; +import { withTranslation } from 'react-i18next'; + +import Box from '../users/Box'; +import { getTime } from '../../helpers/Result'; +import { findResult } from '../../helpers/Participant'; +import { maySeeResults } from '../../helpers/permissions'; +import { withUser } from '../../helpers/UserContext'; +import i18n from '../../i18n'; + +const getPlacement = result => + `${result.placement}. (${i18n.t('results.points', { count: result.score })})`; + +const DetailDialog = ({ + onHide, + participant, + round, + show, + tournament, + user, +}) => { + const result = findResult(participant, round); + const maySee = maySeeResults(user, tournament, round); + return + + + {i18n.t('results.details')} + + + + + + {i18n.t('results.round')} +
+ #{round.number || '?'} + {' '} + {i18n.t('rounds.date', { date: new Date(round.created_at) })} +
+
+ + {i18n.t('results.runner')} +
+
+ + {i18n.t('results.result')} +
+ {maySee && result && result.has_finished + ? getTime(result, maySee) + : i18n.t('results.pending')} +
+
+ + {i18n.t('results.placement')} +
+ {maySee && result && result.placement + ? getPlacement(result) + : i18n.t('results.pending')} +
+
+ {maySee && result && result.comment ? + + {i18n.t('results.comment')} +
{result.comment}
+
+ : null} +
+
+ + + +
; +}; + +DetailDialog.propTypes = { + onHide: PropTypes.func, + participant: PropTypes.shape({ + user: PropTypes.shape({ + }), + }), + round: PropTypes.shape({ + created_at: PropTypes.string, + number: PropTypes.number, + }), + show: PropTypes.bool, + tournament: PropTypes.shape({ + }), + user: PropTypes.shape({ + }), +}; + +export default withTranslation()(withUser(DetailDialog)); diff --git a/resources/js/components/results/Item.js b/resources/js/components/results/Item.js index 0d73105..a2ee8e3 100644 --- a/resources/js/components/results/Item.js +++ b/resources/js/components/results/Item.js @@ -1,46 +1,14 @@ import PropTypes from 'prop-types'; -import React from 'react'; -import { withTranslation } from 'react-i18next'; +import React, { useState } from 'react'; +import { Button } from 'react-bootstrap'; -import Icon from '../common/Icon'; +import DetailDialog from './DetailDialog'; import Box from '../users/Box'; -import { formatTime } from '../../helpers/Result'; +import { getIcon, getTime } from '../../helpers/Result'; import { findResult } from '../../helpers/Participant'; import { maySeeResults } from '../../helpers/permissions'; import { withUser } from '../../helpers/UserContext'; -const getIcon = (result, maySee) => { - if (!result || !result.has_finished) { - return ; - } - if (result.forfeit && maySee) { - return ; - } - if (result.placement === 1 && maySee) { - return ; - } - if (result.placement === 2 && maySee) { - return ; - } - if (result.placement === 3 && maySee) { - return ; - } - return ; -}; - -const getTime = (result, maySee) => { - if (!result || !maySee) { - return null; - } - if (result.time) { - return formatTime(result); - } - if (result.forfeit) { - return 'DNF'; - } - return '?'; -}; - const getClassName = result => { const classNames = ['status']; if (result && result.has_finished) { @@ -60,19 +28,28 @@ const Item = ({ tournament, user, }) => { + const [showDialog, setShowDialog] = useState(false); const result = findResult(participant, round); const maySee = maySeeResults(user, tournament, round); return
-
setShowDialog(true)} title={maySee && result && result.comment ? result.comment : null} > {getTime(result, maySee)} {getIcon(result, maySee)} -
+ + setShowDialog(false)} + participant={participant} + round={round} + show={showDialog} + tournament={tournament} + />
; }; @@ -89,4 +66,4 @@ Item.propTypes = { }), }; -export default withTranslation()(withUser(Item)); +export default withUser(Item); diff --git a/resources/js/helpers/Result.js b/resources/js/helpers/Result.js index 06ade09..205a42b 100644 --- a/resources/js/helpers/Result.js +++ b/resources/js/helpers/Result.js @@ -1,3 +1,6 @@ +import React from 'react'; +import Icon from '../components/common/Icon'; + export const formatTime = result => { const hours = `${Math.floor(result.time / 60 / 60)}`; let minutes = `${Math.floor((result.time / 60) % 60)}`; @@ -11,6 +14,38 @@ export const formatTime = result => { return `${hours}:${minutes}:${seconds}`; }; +export const getIcon = (result, maySee) => { + if (!result || !result.has_finished) { + return ; + } + if (result.forfeit && maySee) { + return ; + } + if (result.placement === 1 && maySee) { + return ; + } + if (result.placement === 2 && maySee) { + return ; + } + if (result.placement === 3 && maySee) { + return ; + } + return ; +}; + +export const getTime = (result, maySee) => { + if (!result || !maySee) { + return null; + } + if (result.time) { + return formatTime(result); + } + if (result.forfeit) { + return 'DNF'; + } + return '?'; +}; + export const parseTime = str => { if (!str) return null; return `${str}`.split(/[-.: ]+/).reduce((acc,time) => (60 * acc) + +time, 0); @@ -18,5 +53,7 @@ export const parseTime = str => { export default { formatTime, + getIcon, + getTime, parseTime, }; diff --git a/resources/js/i18n/de.js b/resources/js/i18n/de.js index 09d6db7..322d0f2 100644 --- a/resources/js/i18n/de.js +++ b/resources/js/i18n/de.js @@ -144,14 +144,22 @@ export default { results: { addComment: 'Kommentieren', comment: 'Kommentar', + details: 'Details', edit: 'Ergebnis ändern', editComment: 'Kommentar ändern', forfeit: 'Aufgegeben', + pending: 'Ausstehend', + placement: 'Platzierung', + points_one: '{{ count }} Punkt', + points_other: '{{ count }} Punkte', report: 'Ergebnis eintragen', reportError: 'Fehler beim Eintragen :(', reportPreview: 'Wird als {{ time }} festgehalten', reportSuccess: 'Festgehalten', reportTime: 'Zeit', + result: 'Ergebnis', + round: 'Runde', + runner: 'Runner', time: 'Zeit: {{ time }}', }, rounds: { diff --git a/resources/js/i18n/en.js b/resources/js/i18n/en.js index 72548f6..acd3c48 100644 --- a/resources/js/i18n/en.js +++ b/resources/js/i18n/en.js @@ -144,14 +144,22 @@ export default { results: { addComment: 'Comment', comment: 'Comment', + details: 'Details', edit: 'Change result', editComment: 'Edit comment', forfeit: 'Forfeit', + pending: 'Pending', + placement: 'Placement', + points_one: '{{ count }} point', + points_other: '{{ count }} points', report: 'Report result', reportError: 'Error saving :(', reportPreview: 'Will be recorded as {{ time }}', reportSuccess: 'Stored, thanks :)', reportTime: 'Time', + result: 'Result', + round: 'Round', + runner: 'Runner', time: 'Time: {{ time }}', }, rounds: { diff --git a/resources/sass/results.scss b/resources/sass/results.scss index d78ebc5..3907e0e 100644 --- a/resources/sass/results.scss +++ b/resources/sass/results.scss @@ -8,18 +8,27 @@ .status { display: flex; + position: relative; align-items: center; justify-content: space-between; margin-top: 1ex; padding: 0.5em; + width: 100%; min-width: 15ex; + border: none; border-radius: 1ex; background: $dark; color: $light; + box-shadow: none; + transition: top 0.15s ease-in-out; &.has-comment { box-shadow: 0 0.5ex 0 $info; } + &:active { + box-shadow: none; + top: 0.5ex; + } .time { min-width: 9ex; -- 2.39.2