Refactor Table and Leaderboard and correct Search in Challenges
This commit is contained in:
parent
59cb564dac
commit
fa1e58ecf0
75
src/components/elements/Table.js
Normal file
75
src/components/elements/Table.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {FlexColumn, FlexRow, Grid} from '../../utils/containers';
|
||||||
|
import {H3, Medium} from '../../utils/fonts';
|
||||||
|
import Media from 'react-media';
|
||||||
|
import theme from '../../utils/theme';
|
||||||
|
import Loading from './Loading';
|
||||||
|
import PropsTypes from 'prop-types';
|
||||||
|
|
||||||
|
const Table = (props) => {
|
||||||
|
const mobileRender = () => {
|
||||||
|
return (
|
||||||
|
<FlexColumn as='table' margin='20px 0 32px 0' minHeight='380px'>
|
||||||
|
<Grid as='thead' gridTemplateColumns='1fr 3fr 1fr 1fr 2fr'
|
||||||
|
gridGap='10px' width='100%'>
|
||||||
|
{props.headerElements.map((elem, index) => {
|
||||||
|
return (
|
||||||
|
<FlexRow as='tr' key={`leaderboard-header-${index}`}
|
||||||
|
alignmentX={(elem === '#' || elem === 'submitter') ? 'flex-start' : 'flex-end'}>
|
||||||
|
<Medium as='th'>{elem}</Medium>
|
||||||
|
</FlexRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Grid>
|
||||||
|
{props.renderElements('10px')}
|
||||||
|
</FlexColumn>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopRender = () => {
|
||||||
|
return (
|
||||||
|
<FlexColumn as='table' margin='32px 0 72px 0' minHeight='438px' width='100%'>
|
||||||
|
<Grid as='thead' gridTemplateColumns='1fr 3fr 1fr 1fr 2fr'
|
||||||
|
gridGap='32px' width='100%' margin='0 0 28px 0'>
|
||||||
|
{props.headerElements.map((elem, index) => {
|
||||||
|
return (
|
||||||
|
<FlexRow as='tr' key={`leaderboard-header-${index}`}
|
||||||
|
alignmentX={(elem === '#' || elem === 'submitter') ? 'flex-start' : 'flex-end'}>
|
||||||
|
<H3 as='th'>{elem}</H3>
|
||||||
|
</FlexRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Grid>
|
||||||
|
{props.renderElements('32px')}
|
||||||
|
</FlexColumn>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Loading visible={props.loading}/>
|
||||||
|
<Media query={theme.mobile}>
|
||||||
|
{!props.loading ? mobileRender() : ''}
|
||||||
|
</Media>
|
||||||
|
<Media query={theme.desktop}>
|
||||||
|
{!props.loading ? desktopRender() : ''}
|
||||||
|
</Media>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Table.propTypes = {
|
||||||
|
challengeName: PropsTypes.string,
|
||||||
|
loading: PropsTypes.bool,
|
||||||
|
renderElements: PropsTypes.func,
|
||||||
|
headerElements: PropsTypes.arrayOf(PropsTypes.string),
|
||||||
|
};
|
||||||
|
|
||||||
|
Table.defaultProps = {
|
||||||
|
challengeName: '',
|
||||||
|
loading: true,
|
||||||
|
renderElements: null,
|
||||||
|
headerElements: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Table;
|
@ -1,129 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import {FlexColumn, FlexRow, Grid} from '../../../utils/containers';
|
|
||||||
import getChallengeLeaderboard from '../../../api/getChallengeLeaderboard';
|
|
||||||
import {H3, Medium} from '../../../utils/fonts';
|
|
||||||
import _renderSubmissions from './_renderSubmissions';
|
|
||||||
import Pager from '../Pager';
|
|
||||||
import {CALC_PAGES} from '../../../utils/globals';
|
|
||||||
import Media from 'react-media';
|
|
||||||
import theme from '../../../utils/theme';
|
|
||||||
import Loading from '../Loading';
|
|
||||||
import PropsTypes from 'prop-types';
|
|
||||||
import _tableSearchQueryHandler from './_tableSearchQueryHandler';
|
|
||||||
import Search from '../Search';
|
|
||||||
|
|
||||||
const Table = (props) => {
|
|
||||||
const headerElements = ['#', 'submitter', 'result', 'entries', 'when'];
|
|
||||||
const [entriesFromApi, setEntriesFromApi] = React.useState([]);
|
|
||||||
const [entries, setEntries] = React.useState([]);
|
|
||||||
const [pageNr, setPageNr] = React.useState(1);
|
|
||||||
const [loading, setLoading] = React.useState(true);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
challengeDataRequest(props.challengeName);
|
|
||||||
}, [props.challengeName]);
|
|
||||||
|
|
||||||
const challengeDataRequest = (challengeName) => {
|
|
||||||
getChallengeLeaderboard(setEntriesFromApi, challengeName);
|
|
||||||
getChallengeLeaderboard(setEntries, challengeName, setLoading);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderSubmissions = (gridGap) => {
|
|
||||||
return _renderSubmissions(pageNr, entries
|
|
||||||
? entries : [], gridGap);
|
|
||||||
};
|
|
||||||
|
|
||||||
const tableSearchQueryHandler = (event) => {
|
|
||||||
_tableSearchQueryHandler(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 mobileRender = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Search searchQueryHandler={tableSearchQueryHandler}/>
|
|
||||||
<FlexColumn as='table' margin='20px 0 32px 0' minHeight='380px'>
|
|
||||||
<Grid as='thead' gridTemplateColumns='1fr 3fr 1fr 1fr 2fr'
|
|
||||||
gridGap='10px' width='100%'>
|
|
||||||
{headerElements.map((elem, index) => {
|
|
||||||
return (
|
|
||||||
<FlexRow as='tr' key={`leaderboard-header-${index}`}
|
|
||||||
alignmentX={(elem === '#' || elem === 'submitter') ? 'flex-start' : 'flex-end'}>
|
|
||||||
<Medium as='th'>{elem}</Medium>
|
|
||||||
</FlexRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Grid>
|
|
||||||
{renderSubmissions('10px')}
|
|
||||||
</FlexColumn>
|
|
||||||
<Pager pageNr={pageNr} width='48px' borderRadius='64px'
|
|
||||||
pages={CALC_PAGES(entries ? entries : [])}
|
|
||||||
nextPage={nextPage} previousPage={previousPage}
|
|
||||||
number={`${pageNr} / ${CALC_PAGES(entries ? entries : [])}`}/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const desktopRender = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Search searchQueryHandler={tableSearchQueryHandler}/>
|
|
||||||
<FlexColumn as='table' margin='32px 0 72px 0' minHeight='438px' width='100%'>
|
|
||||||
<Grid as='thead' gridTemplateColumns='1fr 3fr 1fr 1fr 2fr'
|
|
||||||
gridGap='32px' width='100%' margin='0 0 28px 0'>
|
|
||||||
{headerElements.map((elem, index) => {
|
|
||||||
return (
|
|
||||||
<FlexRow as='tr' key={`leaderboard-header-${index}`}
|
|
||||||
alignmentX={(elem === '#' || elem === 'submitter') ? 'flex-start' : 'flex-end'}>
|
|
||||||
<H3 as='th'>{elem}</H3>
|
|
||||||
</FlexRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Grid>
|
|
||||||
{renderSubmissions('32px')}
|
|
||||||
</FlexColumn>
|
|
||||||
<Pager pageNr={pageNr} width='72px' borderRadius='64px'
|
|
||||||
pages={CALC_PAGES(entries ? entries : [])}
|
|
||||||
nextPage={nextPage} previousPage={previousPage}
|
|
||||||
number={`${pageNr} / ${CALC_PAGES(entries ? entries : [])}`}/>
|
|
||||||
</>
|
|
||||||
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Loading visible={loading}/>
|
|
||||||
<Media query={theme.mobile}>
|
|
||||||
{!loading ? mobileRender() : ''}
|
|
||||||
|
|
||||||
</Media>
|
|
||||||
<Media query={theme.desktop}>
|
|
||||||
{!loading ? desktopRender() : ''}
|
|
||||||
</Media>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Table.propTypes = {
|
|
||||||
challengeName: PropsTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
Table.defaultProps = {
|
|
||||||
challengeName: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Table;
|
|
@ -1 +0,0 @@
|
|||||||
export {default} from './Table';
|
|
@ -1,11 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Media from 'react-media';
|
import Media from 'react-media';
|
||||||
import theme from '../../utils/theme';
|
import theme from '../../../utils/theme';
|
||||||
import {FlexColumn, FlexRow} from '../../utils/containers';
|
import {FlexColumn, FlexRow} from '../../../utils/containers';
|
||||||
import {H2, H3} from '../../utils/fonts';
|
import {H2, H3} from '../../../utils/fonts';
|
||||||
import Table from '../elements/Table';
|
import Table from '../../elements/Table';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import PropsTypes from 'prop-types';
|
import PropsTypes from 'prop-types';
|
||||||
|
import getChallengeLeaderboard from '../../../api/getChallengeLeaderboard';
|
||||||
|
import _renderSubmissions from './_renderSubmissions';
|
||||||
|
import _tableSearchQueryHandler from './_tableSearchQueryHandler';
|
||||||
|
import {CALC_PAGES} from '../../../utils/globals';
|
||||||
|
import Search from '../../elements/Search';
|
||||||
|
import Pager from '../../elements/Pager';
|
||||||
|
|
||||||
const BoardVariantMobile = styled(FlexRow)`
|
const BoardVariantMobile = styled(FlexRow)`
|
||||||
transition: color, background-color 0.3s ease-in-out;
|
transition: color, background-color 0.3s ease-in-out;
|
||||||
@ -46,6 +52,43 @@ const BoardVariantDesktop = styled(FlexRow)`
|
|||||||
|
|
||||||
const Leaderboard = (props) => {
|
const Leaderboard = (props) => {
|
||||||
const [variant, setVariant] = React.useState(0);
|
const [variant, setVariant] = React.useState(0);
|
||||||
|
const headerElements = ['#', 'submitter', 'result', 'entries', 'when'];
|
||||||
|
const [entriesFromApi, setEntriesFromApi] = React.useState([]);
|
||||||
|
const [entries, setEntries] = React.useState([]);
|
||||||
|
const [pageNr, setPageNr] = React.useState(1);
|
||||||
|
const [loading, setLoading] = React.useState(true);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
challengeDataRequest(props.challengeName);
|
||||||
|
}, [props.challengeName]);
|
||||||
|
|
||||||
|
const challengeDataRequest = (challengeName) => {
|
||||||
|
getChallengeLeaderboard(setEntriesFromApi, challengeName);
|
||||||
|
getChallengeLeaderboard(setEntries, challengeName, setLoading);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderSubmissions = (gridGap) => {
|
||||||
|
return _renderSubmissions(pageNr, entries
|
||||||
|
? entries : [], gridGap);
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableSearchQueryHandler = (event) => {
|
||||||
|
_tableSearchQueryHandler(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 mobileRender = () => {
|
const mobileRender = () => {
|
||||||
return (
|
return (
|
||||||
@ -61,7 +104,13 @@ const Leaderboard = (props) => {
|
|||||||
By metric
|
By metric
|
||||||
</BoardVariantMobile>
|
</BoardVariantMobile>
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
<Table challengeName={props.challengeName}/>
|
<Search searchQueryHandler={tableSearchQueryHandler}/>
|
||||||
|
<Table challengeName={props.challengeName} loading={loading}
|
||||||
|
renderElements={renderSubmissions} headerElements={headerElements}/>
|
||||||
|
<Pager pageNr={pageNr} width='48px' borderRadius='64px'
|
||||||
|
pages={CALC_PAGES(entries ? entries : [])}
|
||||||
|
nextPage={nextPage} previousPage={previousPage}
|
||||||
|
number={`${pageNr} / ${CALC_PAGES(entries ? entries : [])}`}/>
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -86,7 +135,13 @@ const Leaderboard = (props) => {
|
|||||||
</H3>
|
</H3>
|
||||||
</BoardVariantDesktop>
|
</BoardVariantDesktop>
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
<Table challengeName={props.challengeName}/>
|
<Search searchQueryHandler={tableSearchQueryHandler}/>
|
||||||
|
<Table challengeName={props.challengeName} loading={loading}
|
||||||
|
renderElements={renderSubmissions} headerElements={headerElements}/>
|
||||||
|
<Pager pageNr={pageNr} width='72px' borderRadius='64px'
|
||||||
|
pages={CALC_PAGES(entries ? entries : [])}
|
||||||
|
nextPage={nextPage} previousPage={previousPage}
|
||||||
|
number={`${pageNr} / ${CALC_PAGES(entries ? entries : [])}`}/>
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
);
|
);
|
||||||
};
|
};
|
1
src/components/sections/Leaderboard/index.js
Normal file
1
src/components/sections/Leaderboard/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export {default} from './Leaderboard';
|
@ -8,7 +8,7 @@ const _searchQueryHandler = (event, challengesFromAPI, setPageNr, setChallenges)
|
|||||||
for (let challenge of challengesFromAPI) {
|
for (let challenge of challengesFromAPI) {
|
||||||
const {title, description, type, mainMetric, bestScore, deadline, baseline, prize} = challenge;
|
const {title, description, type, mainMetric, bestScore, deadline, baseline, prize} = challenge;
|
||||||
const str = `${title} ${description} ${type} ${mainMetric} ${bestScore}
|
const str = `${title} ${description} ${type} ${mainMetric} ${bestScore}
|
||||||
${deadline.slice(11, 16)} ${deadline.slice(0, 10)} ${baseline} ${prize}`;
|
${deadline ? deadline.slice(11, 16) : ''} ${deadline ? deadline.slice(0, 10) : ''} ${baseline} ${prize}`;
|
||||||
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
|
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
|
||||||
challengesToRender.push(challenge);
|
challengesToRender.push(challenge);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import {useParams} from 'react-router-dom';
|
|||||||
import {H1, Medium} from '../utils/fonts';
|
import {H1, Medium} from '../utils/fonts';
|
||||||
import theme from '../utils/theme';
|
import theme from '../utils/theme';
|
||||||
import MobileChallengeMenu from '../components/elements/MobileChallengeMenu';
|
import MobileChallengeMenu from '../components/elements/MobileChallengeMenu';
|
||||||
import Leaderboard from '../components/sections/Leaderboard';
|
import Leaderboard from '../components/sections/Leaderboard/Leaderboard';
|
||||||
import Readme from '../components/sections/Readme';
|
import Readme from '../components/sections/Readme';
|
||||||
import HowTo from '../components/sections/HowTo';
|
import HowTo from '../components/sections/HowTo';
|
||||||
import MyEntries from '../components/sections/MyEntries';
|
import MyEntries from '../components/sections/MyEntries';
|
||||||
|
Loading…
Reference in New Issue
Block a user