Search in Leaderboard

This commit is contained in:
mattyl006 2022-08-01 14:25:27 +02:00
parent 033ef57bbe
commit 6b183ad5bb
9 changed files with 111 additions and 88 deletions

View File

@ -1,10 +1,10 @@
import {API} from '../utils/globals';
const getChallengeLeaderboard = (setDataState, setLoading, challengeName) => {
const getChallengeLeaderboard = (setDataState, challengeName, setLoading) => {
fetch(`${API}/leaderboard/${challengeName}`)
.then(response => response.json())
.then(data => {
setDataState(data);
setDataState(data.entries);
if (setLoading)
setLoading(false);
});

View File

@ -71,7 +71,7 @@ const FiltersMenu = (props) => {
</FlexRow>
</Media>
<Media query={theme.desktop}>
<FlexRow margin='20px 0 0 0' width='94%' alignmentX='flex-start'>
<FlexRow margin='8px 0 0 0' width='94%' alignmentX='flex-start'>
<Button width='72px' height='34px' backgroundColor={theme.colors.green} handler={resetHandler}>
Reset
</Button>

View File

@ -50,23 +50,19 @@ const RightArrow = styled(Svg)`
`;
const Pager = (props) => {
if (props.visible) {
return (
<PagerStyle>
<LeftArrow as='button' src={polygon} onClick={props.previousPage} size='cover'
backgroundColor={(props.pageNr === 1) ? 'transparent' : theme.colors.dark}/>
<CircleNumber number={props.number} width={props.width} borderRadius={props.borderRadius}/>
<RightArrow as='button' src={polygon} onClick={props.nextPage} size='cover'
backgroundColor={(props.pageNr === props.pages)
? 'transparent' : theme.colors.dark}/>
</PagerStyle>
);
}
return '';
return (
<PagerStyle>
<LeftArrow as='button' src={polygon} onClick={props.previousPage} size='cover'
backgroundColor={(props.pageNr === 1) ? 'transparent' : theme.colors.dark}/>
<CircleNumber number={props.number} width={props.width} borderRadius={props.borderRadius}/>
<RightArrow as='button' src={polygon} onClick={props.nextPage} size='cover'
backgroundColor={(props.pageNr === props.pages)
? 'transparent' : theme.colors.dark}/>
</PagerStyle>
);
};
Pager.propTypes = {
visible: PropsTypes.bool,
previousPage: PropsTypes.func,
pageNr: PropsTypes.number,
nextPage: PropsTypes.func,
@ -77,7 +73,6 @@ Pager.propTypes = {
};
Pager.defaultProps = {
visible: false,
previousPage: null,
pageNr: 1,
nextPage: null,

View File

@ -29,10 +29,6 @@ const SearchStyle = styled(FlexRow)`
&:hover {
transform: scale(1.25);
}
@media (min-width: ${({theme}) => theme.overMobile}) {
display: none;
}
}
input {
@ -46,7 +42,8 @@ const Search = (props) => {
<SearchStyle>
<Svg src={loopIco}/>
<Body as='input' onChange={(event) => props.searchQueryHandler(event)}/>
<Svg as='button' src={filtersIco} onClick={props.toggleFiltersMenu}/>
<Svg as='button' src={filtersIco} onClick={props.toggleFiltersMenu}
display={props.filterButton ? 'block' : 'none'}/>
</SearchStyle>
);
};
@ -54,11 +51,13 @@ const Search = (props) => {
Search.propTypes = {
searchQueryHandler: PropsTypes.func,
toggleFiltersMenu: PropsTypes.func,
filterButton: PropsTypes.bool
};
Search.defaultProps = {
searchQueryHandler: null,
toggleFiltersMenu: null,
filterButton: false,
};
export default Search;

View File

@ -9,28 +9,36 @@ 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', 'when', 'result', 'entries'];
const [leaderboardData, setLeaderboardData] = React.useState({});
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();
});
challengeDataRequest(props.challengeName);
}, [props.challengeName]);
const challengeDataRequest = () => {
getChallengeLeaderboard(setLeaderboardData, setLoading, props.challengeName);
const challengeDataRequest = (challengeName) => {
getChallengeLeaderboard(setEntriesFromApi, challengeName);
getChallengeLeaderboard(setEntries, challengeName, setLoading);
};
const renderSubmissions = () => {
return _renderSubmissions(pageNr, leaderboardData.entries
? leaderboardData.entries : []);
return _renderSubmissions(pageNr, entries
? entries : []);
};
const tableSearchQueryHandler = (event) => {
_tableSearchQueryHandler(event, entriesFromApi, setPageNr, setEntries);
};
const nextPage = () => {
if (pageNr !== CALC_PAGES(leaderboardData.entries ? leaderboardData.entries : [])) {
if (pageNr !== CALC_PAGES(entries ? entries : [])) {
let newPage = pageNr + 1;
setPageNr(newPage);
}
@ -45,40 +53,54 @@ const Table = (props) => {
const mobileRender = () => {
return (
<FlexColumn as='table' margin='0 0 32px 0' minHeight='380px'>
<Grid as='thead' gridTemplateColumns='1fr 3fr 3fr 1fr 1fr'
gridGap='10px' width='100%'>
{headerElements.map((elem, index) => {
return (
<FlexRow as='tr' key={`leaderboard-header-${index}`}
alignmentX={elem === 'entries' ? 'flex-end' : 'flex-start'}>
<Medium as='th'>{elem}</Medium>
</FlexRow>
);
})}
</Grid>
{renderSubmissions()}
</FlexColumn>
<>
<Search searchQueryHandler={tableSearchQueryHandler}/>
<FlexColumn as='table' margin='20px 0 32px 0' minHeight='380px'>
<Grid as='thead' gridTemplateColumns='1fr 3fr 3fr 1fr 1fr'
gridGap='10px' width='100%'>
{headerElements.map((elem, index) => {
return (
<FlexRow as='tr' key={`leaderboard-header-${index}`}
alignmentX={elem === 'entries' ? 'flex-end' : 'flex-start'}>
<Medium as='th'>{elem}</Medium>
</FlexRow>
);
})}
</Grid>
{renderSubmissions()}
</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 (
<FlexColumn as='table' margin='0 0 72px 0' minHeight='438px'>
<Grid as='thead' gridTemplateColumns='1fr 3fr 3fr 1fr 1fr'
gridGap='10px' width='100%' margin='0 0 28px 0'>
{headerElements.map((elem, index) => {
return (
<FlexRow as='tr' key={`leaderboard-header-${index}`}
alignmentX={elem === 'entries' ? 'flex-end' : 'flex-start'}>
<H3 as='th'>{elem}</H3>
</FlexRow>
);
})}
</Grid>
{renderSubmissions()}
</FlexColumn>
<>
<Search searchQueryHandler={tableSearchQueryHandler}/>
<FlexColumn as='table' margin='32px 0 72px 0' minHeight='438px'>
<Grid as='thead' gridTemplateColumns='1fr 3fr 3fr 1fr 1fr'
gridGap='10px' width='100%' margin='0 0 28px 0'>
{headerElements.map((elem, index) => {
return (
<FlexRow as='tr' key={`leaderboard-header-${index}`}
alignmentX={elem === 'entries' ? 'flex-end' : 'flex-start'}>
<H3 as='th'>{elem}</H3>
</FlexRow>
);
})}
</Grid>
{renderSubmissions()}
</FlexColumn>
<Pager pageNr={pageNr} width='72px' borderRadius='64px'
pages={CALC_PAGES(entries ? entries : [])}
nextPage={nextPage} previousPage={previousPage}
number={`${pageNr} / ${CALC_PAGES(entries ? entries : [])}`}/>
</>
);
};
@ -86,24 +108,11 @@ const Table = (props) => {
<>
<Loading visible={loading}/>
<Media query={theme.mobile}>
<>
{!loading ? mobileRender() : ''}
<Pager visible={!loading} pageNr={pageNr}
pages={CALC_PAGES(leaderboardData.entries ? leaderboardData.entries : [])}
nextPage={nextPage} previousPage={previousPage} width='48px' borderRadius='64px'
number={`${pageNr} / ${CALC_PAGES(leaderboardData.entries ?
leaderboardData.entries : [])}`}/>
</>
{!loading ? mobileRender() : ''}
</Media>
<Media query={theme.desktop}>
<>
{!loading ? desktopRender() : ''}
<Pager visible={!loading} pageNr={pageNr}
pages={CALC_PAGES(leaderboardData.entries ? leaderboardData.entries : [])}
nextPage={nextPage} previousPage={previousPage} width='72px' borderRadius='64px'
number={`${pageNr} / ${CALC_PAGES(leaderboardData.entries ?
leaderboardData.entries : [])}`}/>
</>
{!loading ? desktopRender() : ''}
</Media>
</>
);

View File

@ -0,0 +1,18 @@
const _tableSearchQueryHandler = (event, entriesFromApi, setPageNr, setEntries) => {
let searchQuery = event.target.value;
let submissionsToRender = [];
setPageNr(1);
if (searchQuery === '')
setEntries(entriesFromApi);
else {
for (let entry of entriesFromApi) {
const {submitter, when, evaluations, times} = entry;
const str = `${submitter} ${when.slice(11, 16)} ${when.slice(0, 10)} ${evaluations} ${times}`;
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
submissionsToRender.push(entry);
}
setEntries(submissionsToRender);
}
};
export default _tableSearchQueryHandler;

View File

@ -53,7 +53,7 @@ const Leaderboard = (props) => {
<H2 as='h2' margin='0 0 12px 0'>
Leaderboard
</H2>
<FlexRow gap='12px' margin='0 0 20px 0'>
<FlexRow gap='12px' margin='0 0 24px 0'>
<BoardVariantMobile as='button' active={0 === variant} onClick={() => setVariant(0)}>
By user
</BoardVariantMobile>
@ -72,7 +72,7 @@ const Leaderboard = (props) => {
<H2 as='h2' margin='0 0 32px 0'>
Leaderboard
</H2>
<FlexRow border={`1px solid ${theme.colors.green05}`} margin='0 0 76px 0'>
<FlexRow border={`1px solid ${theme.colors.green05}`} margin='0 0 48px 0'>
<BoardVariantDesktop as='button' width='150px' height='48px'
active={0 === variant} onClick={() => setVariant(0)}>
<H3 as='span'>

View File

@ -90,15 +90,16 @@ const Challenges = () => {
<H1 as='h1' margin='0 0 20px 0'>
Challenges
</H1>
<Search searchQueryHandler={searchQueryHandler} toggleFiltersMenu={toggleFiltersMenu}/>
<Search searchQueryHandler={searchQueryHandler} filterButton
toggleFiltersMenu={toggleFiltersMenu}/>
<FlexColumn width='100%'>
<Loading visible={loading}/>
{renderChallenges()}
</FlexColumn>
</FlexColumn>
<Pager visible={!loading} pageNr={pageNr} pages={CALC_PAGES(challenges)}
nextPage={nextPage} previousPage={previousPage} width='48px' borderRadius='64px'
number={`${pageNr} / ${CALC_PAGES(challenges)}`}/>
{!loading ? <Pager pageNr={pageNr} pages={CALC_PAGES(challenges)}
nextPage={nextPage} previousPage={previousPage} width='48px' borderRadius='64px'
number={`${pageNr} / ${CALC_PAGES(challenges)}`}/> : ''}
</FlexColumn>
</>
);
@ -122,7 +123,7 @@ const Challenges = () => {
<Body margin='0 0 12px 0' maxWidth='400px'>
Increase your machine learning skills by competing in our exciting challenges.
</Body>
<Search searchQueryHandler={searchQueryHandler} toggleFiltersMenu={toggleFiltersMenu}/>
<Search searchQueryHandler={searchQueryHandler}/>
</FlexColumn>
<Svg src={cupIco} size='contain' width='25%'
height='160px' backgroundColor={theme.colors.green}/>
@ -132,9 +133,9 @@ const Challenges = () => {
{renderChallenges()}
</FlexColumn>
</FlexColumn>
<Pager visible={!loading} pageNr={pageNr} pages={CALC_PAGES(challenges)}
nextPage={nextPage} previousPage={previousPage} width='72px' borderRadius='64px'
number={`${pageNr} / ${CALC_PAGES(challenges)}`}/>
{!loading ? <Pager pageNr={pageNr} pages={CALC_PAGES(challenges)}
nextPage={nextPage} previousPage={previousPage} width='72px' borderRadius='64px'
number={`${pageNr} / ${CALC_PAGES(challenges)}`}/> : ''}
</FlexColumn>
</>
);

View File

@ -6,8 +6,9 @@ const _searchQueryHandler = (event, challengesFromAPI, setPageNr, setChallenges)
setChallenges(challengesFromAPI);
else {
for (let challenge of challengesFromAPI) {
let str = `${challenge.title} ${challenge.description} ${challenge.type} ${challenge.mainMetric}
${challenge.bestScore} ${challenge.deadline} ${challenge.baseline} ${challenge.prize}`;
const {title, description, type, mainMetric, bestScore, deadline, baseline, prize} = challenge;
const str = `${title} ${description} ${type} ${mainMetric} ${bestScore}
${deadline.slice(11, 16)} ${deadline.slice(0, 10)} ${baseline} ${prize}`;
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
challengesToRender.push(challenge);
}