Refactor Table and Leaderboard and correct Search in Challenges

This commit is contained in:
mattyl006 2022-08-30 09:25:45 +02:00
parent 59cb564dac
commit fa1e58ecf0
9 changed files with 139 additions and 138 deletions

View 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;

View File

@ -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;

View File

@ -1 +0,0 @@
export {default} from './Table';

View File

@ -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>
); );
}; };

View File

@ -0,0 +1 @@
export {default} from './Leaderboard';

View File

@ -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);
} }

View File

@ -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';