diff --git a/src/api/getChallengeLeaderboard.js b/src/api/getChallengeLeaderboard.js index 6b7db90..3f1dce4 100644 --- a/src/api/getChallengeLeaderboard.js +++ b/src/api/getChallengeLeaderboard.js @@ -1,16 +1,19 @@ -import {API} from '../utils/globals'; +import { API } from '../utils/globals'; -const getChallengeLeaderboard = (setDataState, challengeName, setLoading) => { - fetch(`${API}/leaderboard/${challengeName}`) - .then(response => response.json()) - .then(data => { - setDataState(data.entries); - if (setLoading) { - setTimeout(() => { - setLoading(false); - }, 3000); - } - }); +const getChallengeLeaderboard = async ( + setDataState, + challengeName, + setLoading +) => { + await fetch(`${API}/leaderboard/${challengeName}`) + .then((response) => response.json()) + .then((data) => { + setDataState(data.entries); + }); + + if (setLoading) { + setLoading(false); + } }; -export default getChallengeLeaderboard; \ No newline at end of file +export default getChallengeLeaderboard; diff --git a/src/components/specific_challenge/Leaderboard/Leaderboard.js b/src/components/specific_challenge/Leaderboard/Leaderboard.js index 58c566f..3e21f77 100644 --- a/src/components/specific_challenge/Leaderboard/Leaderboard.js +++ b/src/components/specific_challenge/Leaderboard/Leaderboard.js @@ -1,239 +1,295 @@ import React from 'react'; import Media from 'react-media'; import theme from '../../../utils/theme'; -import {FlexColumn} from '../../../utils/containers'; -import {H2} from '../../../utils/fonts'; +import { FlexColumn } from '../../../utils/containers'; +import { H2 } from '../../../utils/fonts'; import Table from '../Table'; import PropsTypes from 'prop-types'; import getChallengeLeaderboard from '../../../api/getChallengeLeaderboard'; import leaderboardSearchQueryHandler from './leaderboardSearchQueryHandler'; -import {CALC_PAGES, EVALUATIONS_FORMAT, RENDER_WHEN} from '../../../utils/globals'; +import { + CALC_PAGES, + EVALUATIONS_FORMAT, + RENDER_WHEN, +} from '../../../utils/globals'; import Search from '../../generic/Search'; import Pager from '../../generic/Pager'; import Loading from '../../generic/Loading'; const Leaderboard = (props) => { - const [entriesFromApi, setEntriesFromApi] = React.useState([]); - const [entries, setEntries] = React.useState([]); - const [pageNr, setPageNr] = React.useState(1); - const [loading, setLoading] = React.useState(true); - const [submitterSorted, setSubmitterSorted] = React.useState(false); - const [entriesSorted, setEntriesSorted] = React.useState(false); - const [whenSorted, setWhenSorted] = React.useState(false); - const [scoresSorted, setScoresSorted] = React.useState([]); + const [entriesFromApi, setEntriesFromApi] = React.useState([]); + const [entries, setEntries] = React.useState([]); + const [pageNr, setPageNr] = React.useState(1); + const [loading, setLoading] = React.useState(true); + const [submitterSorted, setSubmitterSorted] = React.useState(false); + const [entriesSorted, setEntriesSorted] = React.useState(false); + const [whenSorted, setWhenSorted] = React.useState(false); + const [scoresSorted, setScoresSorted] = React.useState([]); - React.useEffect(() => { - challengeDataRequest(props.challengeName); - }, [props.challengeName]); + React.useEffect(() => { + challengeDataRequest(props.challengeName); + }, [props.challengeName]); - const challengeDataRequest = (challengeName) => { - getChallengeLeaderboard(setEntriesFromApi, challengeName); - getChallengeLeaderboard(setEntries, challengeName, setLoading); - }; + const challengeDataRequest = (challengeName) => { + getChallengeLeaderboard(setEntriesFromApi, challengeName); + getChallengeLeaderboard(setEntries, challengeName, setLoading); + }; - const getMetricIndex = (metricName) => { - let i = 0; - for (let evaluation of entriesFromApi[0].evaluations) { - if (`${evaluation.test.metric}.${evaluation.test.name}` === metricName) { - return i; - } - i++; + const getMetricIndex = (metricName) => { + let i = 0; + for (let evaluation of entriesFromApi[0].evaluations) { + if (`${evaluation.test.metric}.${evaluation.test.name}` === metricName) { + return i; + } + i++; + } + }; + + const searchQueryHandler = (event) => { + leaderboardSearchQueryHandler(event, entriesFromApi, setPageNr, setEntries); + }; + + const nextPage = () => { + if (pageNr !== CALC_PAGES(entries ? entries : [])) { + let newPage = pageNr + 1; + setPageNr(newPage); + } + }; + + const previousPage = () => { + if (pageNr !== 1) { + let newPage = pageNr - 1; + setPageNr(newPage); + } + }; + + const getPossibleMetrics = () => { + let metrics = []; + for (let entry of entriesFromApi) { + for (let evaluation of entry.evaluations) { + let metric = evaluation.test.metric; + let name = evaluation.test.name; + if (metric && !metrics.includes(`${metric}.${name}`)) { + metrics.push(`${metric}.${name}`); } - }; + } + } + return metrics; + }; - const searchQueryHandler = (event) => { - leaderboardSearchQueryHandler(event, entriesFromApi, setPageNr, setEntries); - }; + const getLeaderboardHeader = () => { + let header = ['#', 'submitter']; + for (let metric of getPossibleMetrics()) { + header.push(metric); + } + header.push('entries'); + header.push('when'); + return header; + }; - const nextPage = () => { - if (pageNr !== CALC_PAGES(entries ? entries : [])) { - let newPage = pageNr + 1; - setPageNr(newPage); + const getLeaderboardHeaderMobile = () => { + let header = ['#', 'submitter', 'entries', 'when']; + for (let metric of getPossibleMetrics()) { + header.push(metric); + } + return header; + }; + + const sortByUpdate = (elem) => { + let metricIndex = 0; + let newEntries = entries; + switch (elem) { + case 'submitter': + if (submitterSorted) { + newEntries = newEntries.sort((a, b) => + a.submitter.toLowerCase() < b.submitter.toLowerCase() + ? 1 + : b.submitter.toLowerCase() < a.submitter.toLowerCase() + ? -1 + : 0 + ); + setSubmitterSorted(false); + } else { + newEntries = newEntries.sort((a, b) => + a.submitter.toLowerCase() > b.submitter.toLowerCase() + ? 1 + : b.submitter.toLowerCase() > a.submitter.toLowerCase() + ? -1 + : 0 + ); + setSubmitterSorted(true); } - }; - - const previousPage = () => { - if (pageNr !== 1) { - let newPage = pageNr - 1; - setPageNr(newPage); + break; + case 'entries': + if (entriesSorted) { + newEntries = newEntries.sort((a, b) => b.times - a.times); + setEntriesSorted(false); + } else { + newEntries = newEntries.sort((a, b) => a.times - b.times); + setEntriesSorted(true); } - }; - - const getPossibleMetrics = () => { - let metrics = []; - for (let entry of entriesFromApi) { - for (let evaluation of entry.evaluations) { - let metric = evaluation.test.metric; - let name = evaluation.test.name; - if (metric && !metrics.includes(`${metric}.${name}`)) { - metrics.push(`${metric}.${name}`); - } - } + break; + case 'when': + if (whenSorted) { + newEntries = newEntries.sort((a, b) => + a.when < b.when ? 1 : b.when < a.when ? -1 : 0 + ); + setWhenSorted(false); + } else { + newEntries = newEntries.sort((a, b) => + a.when > b.when ? 1 : b.when > a.when ? -1 : 0 + ); + setWhenSorted(true); } - return metrics; - }; - - const getLeaderboardHeader = () => { - let header = ['#', 'submitter']; - for (let metric of getPossibleMetrics()) { - header.push(metric); + break; + default: + metricIndex = getMetricIndex(elem); + // eslint-disable-next-line no-case-declarations + let newScoresSorted = scoresSorted; + if (scoresSorted[metricIndex]) { + newEntries = newEntries.sort( + (a, b) => + b.evaluations[metricIndex].score - + a.evaluations[metricIndex].score + ); + newScoresSorted[metricIndex] = false; + setScoresSorted(newScoresSorted); + } else { + newEntries = newEntries.sort( + (a, b) => + a.evaluations[metricIndex].score - + b.evaluations[metricIndex].score + ); + newScoresSorted[metricIndex] = true; + setScoresSorted(newScoresSorted); } - header.push('entries'); - header.push('when'); - return header; - }; - - const getLeaderboardHeaderMobile = () => { - let header = ['#', 'submitter', 'entries', 'when']; - for (let metric of getPossibleMetrics()) { - header.push(metric); - } - return header; - }; - - const sortByUpdate = (elem) => { - let metricIndex = 0; - let newEntries = entries; - switch (elem) { - case 'submitter': - if (submitterSorted) { - newEntries = newEntries.sort((a, b) => (a.submitter.toLowerCase() < b.submitter.toLowerCase()) ? 1 : ((b.submitter.toLowerCase() < a.submitter.toLowerCase()) ? -1 : 0)); - setSubmitterSorted(false); - } else { - newEntries = newEntries.sort((a, b) => (a.submitter.toLowerCase() > b.submitter.toLowerCase()) ? 1 : ((b.submitter.toLowerCase() > a.submitter.toLowerCase()) ? -1 : 0)); - setSubmitterSorted(true); - } - break; - case 'entries': - if (entriesSorted) { - newEntries = newEntries.sort((a, b) => b.times - a.times); - setEntriesSorted(false); - } else { - newEntries = newEntries.sort((a, b) => a.times - b.times); - setEntriesSorted(true); - } - break; - case 'when': - if (whenSorted) { - newEntries = newEntries.sort((a, b) => (a.when < b.when) ? 1 : ((b.when < a.when) ? -1 : 0)); - setWhenSorted(false); - } else { - newEntries = newEntries.sort((a, b) => (a.when > b.when) ? 1 : ((b.when > a.when) ? -1 : 0)); - setWhenSorted(true); - } - break; - default: - metricIndex = getMetricIndex(elem); - // eslint-disable-next-line no-case-declarations - let newScoresSorted = scoresSorted; - if (scoresSorted[metricIndex]) { - newEntries = newEntries.sort((a, b) => b.evaluations[metricIndex].score - a.evaluations[metricIndex].score); - newScoresSorted[metricIndex] = false; - setScoresSorted(newScoresSorted); - } else { - newEntries = newEntries.sort((a, b) => a.evaluations[metricIndex].score - b.evaluations[metricIndex].score); - newScoresSorted[metricIndex] = true; - setScoresSorted(newScoresSorted); - } - break; - } - setEntries(newEntries); - }; - - const mobileRender = () => { - return ( - -

- Leaderboard -

- {!loading ? - <> - - - - - : } - - ); - }; - - const desktopRender = () => { - return ( - -

- Leaderboard -

- {!loading ? - <> - -
- - - : } - - ); - }; + break; + } + setEntries(newEntries); + }; + const mobileRender = () => { return ( - <> - - {mobileRender()} - - - {desktopRender()} - - + +

+ Leaderboard +

+ {!loading ? ( + <> + +
+ + + ) : ( + + )} + ); + }; + + const desktopRender = () => { + return ( + +

+ Leaderboard +

+ {!loading ? ( + <> + +
+ + + ) : ( + + )} + + ); + }; + + return ( + <> + {mobileRender()} + {desktopRender()} + + ); }; Leaderboard.propsTypes = { - challengeName: PropsTypes.string, + challengeName: PropsTypes.string, }; Leaderboard.defaultProps = { - challengeName: '', + challengeName: '', }; -export default Leaderboard; \ No newline at end of file +export default Leaderboard;