Compare commits
No commits in common. "6c65af9bd72f0070ed5cc8ed6a1cabcc987ef115" and "ba0cdb944e128127b68fd45d92b25a4a6a58facd" have entirely different histories.
6c65af9bd7
...
ba0cdb944e
@ -1,14 +1,11 @@
|
|||||||
import CHALLENGES_ACTION from '../pages/Challanges/model/ChallengesActionEnum';
|
|
||||||
import { API } from '../utils/globals';
|
import { API } from '../utils/globals';
|
||||||
|
|
||||||
const getChallenges = (dispatch) => {
|
const getChallenges = (setDataStates, setLoadingState) => {
|
||||||
fetch(`${API}/list-challenges`)
|
fetch(`${API}/list-challenges`)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
dispatch({
|
for (let setState of setDataStates) setState(data);
|
||||||
type: CHALLENGES_ACTION.LOAD_CHALLENGES_FROM_API,
|
if (setLoadingState) setLoadingState(false);
|
||||||
payload: data,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,75 +1,66 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlexColumn, Grid, Svg } from '../../utils/containers';
|
import {FlexColumn, Grid, Svg} from '../../utils/containers';
|
||||||
import Filter from '../generic/Filter';
|
import Filter from '../generic/Filter';
|
||||||
import { Body, H3, Medium } from '../../utils/fonts';
|
import {Body, H3, Medium} from '../../utils/fonts';
|
||||||
import arrow from '../../assets/arrow.svg';
|
import arrow from '../../assets/arrow.svg';
|
||||||
import Media from 'react-media';
|
import Media from 'react-media';
|
||||||
import theme from '../../utils/theme';
|
import theme from '../../utils/theme';
|
||||||
|
import PropsTypes from 'prop-types';
|
||||||
|
|
||||||
const FilterBy = (props) => {
|
const FilterBy = (props) => {
|
||||||
const renderFilterOptions = () => {
|
const renderFilterOptions = () => {
|
||||||
return props.options.map((option, index) => {
|
return (
|
||||||
return (
|
props.options.map((option, index) => {
|
||||||
<Filter
|
return (
|
||||||
key={`filter_option-${index}`}
|
<Filter key={`filter_option-${index}`}
|
||||||
option={props.option}
|
option={props.option} handler={props.handler}
|
||||||
handler={props.handler}
|
id={`${props.header}-${option.name}-${index}`} name={props.header} index={index}>
|
||||||
id={`${props.header}-${option.name}-${index}`}
|
<Body as='p'>
|
||||||
name={props.header}
|
{option.name}
|
||||||
index={index}
|
</Body>
|
||||||
>
|
{option.sort ?
|
||||||
<Body as="p">{option.name}</Body>
|
<Svg as='span' src={arrow} rotate={option.rotate ? option.rotate : '0'}
|
||||||
{option.sort && (
|
margin={option.rotate ? '2px 0 0 0' : '0 0 2px 0'}/>
|
||||||
<Svg
|
: ''}
|
||||||
as="span"
|
</Filter>
|
||||||
src={arrow}
|
);
|
||||||
rotate={option.rotate ? option.rotate : '0'}
|
})
|
||||||
margin={option.rotate ? '2px 0 0 0' : '0 0 2px 0'}
|
);
|
||||||
/>
|
};
|
||||||
)}
|
|
||||||
</Filter>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlexColumn
|
<FlexColumn as='fieldset' width='100%' padding='8px' margin={props.margin ? props.margin : '0'}
|
||||||
as="fieldset"
|
alignmentX={props.alignmentX ? props.alignmentX : 'flex-start'}>
|
||||||
width="100%"
|
<Media query={theme.mobile}>
|
||||||
padding="8px"
|
<Medium as='legend' textTransform='uppercase' margin='0 0 12px 0'>
|
||||||
margin={props.margin ? props.margin : '0'}
|
{props.header}
|
||||||
alignmentX={props.alignmentX ? props.alignmentX : 'flex-start'}
|
</Medium>
|
||||||
>
|
</Media>
|
||||||
<Media query={theme.mobile}>
|
<Media query={theme.desktop}>
|
||||||
<Medium as="legend" textTransform="uppercase" margin="0 0 12px 0">
|
<H3 as='legend' textTransform='uppercase' width='100%'
|
||||||
{props.header}
|
textAlign={props.textAlign ? props.textAlign : 'left'} margin='0 0 24px 0'>
|
||||||
</Medium>
|
{props.header}
|
||||||
</Media>
|
</H3>
|
||||||
<Media query={theme.desktop}>
|
</Media>
|
||||||
<H3
|
<Grid gridTemplateColumns={props.gridTemplateColumns ? props.gridTemplateColumns : 'auto auto'}
|
||||||
as="legend"
|
gridTemplateRows={props.gridTemplateRows ? props.gridTemplateRows : 'auto'}
|
||||||
textTransform="uppercase"
|
gridGap='12px' position='relative'>
|
||||||
width="100%"
|
{renderFilterOptions()}
|
||||||
textAlign={props.textAlign ? props.textAlign : 'left'}
|
</Grid>
|
||||||
margin="0 0 24px 0"
|
</FlexColumn>
|
||||||
>
|
);
|
||||||
{props.header}
|
|
||||||
</H3>
|
|
||||||
</Media>
|
|
||||||
<Grid
|
|
||||||
gridTemplateColumns={
|
|
||||||
props.gridTemplateColumns ? props.gridTemplateColumns : 'auto auto'
|
|
||||||
}
|
|
||||||
gridTemplateRows={
|
|
||||||
props.gridTemplateRows ? props.gridTemplateRows : 'auto'
|
|
||||||
}
|
|
||||||
gridGap="12px"
|
|
||||||
position="relative"
|
|
||||||
>
|
|
||||||
{renderFilterOptions()}
|
|
||||||
</Grid>
|
|
||||||
</FlexColumn>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FilterBy;
|
FilterBy.propTypes = {
|
||||||
|
options: PropsTypes.arrayOf(PropsTypes.shape({
|
||||||
|
name: PropsTypes.string,
|
||||||
|
sort: PropsTypes.bool,
|
||||||
|
rotate: PropsTypes.string
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterBy.defaultProps = {
|
||||||
|
options: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FilterBy;
|
@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlexColumn, FlexRow, TransBack } from '../../../utils/containers';
|
import {FlexColumn, FlexRow, TransBack} from '../../../utils/containers';
|
||||||
import Button from '../../generic/Button';
|
import Button from '../../generic/Button';
|
||||||
import theme from '../../../utils/theme';
|
import theme from '../../../utils/theme';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import FilterBy from '../FilterBy';
|
import FilterBy from '../FilterBy';
|
||||||
import filterOptions from './filterOptions';
|
import filterOptions from './filterOptions';
|
||||||
import Media from 'react-media';
|
import Media from 'react-media';
|
||||||
import CHALLENGES_ACTION from '../../../pages/Challanges/model/ChallengesActionEnum';
|
import PropsTypes from 'prop-types';
|
||||||
|
|
||||||
const FiltersMenuStyle = styled(FlexColumn)`
|
const FiltersMenuStyle = styled(FlexColumn)`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -18,8 +18,8 @@ const FiltersMenuStyle = styled(FlexColumn)`
|
|||||||
max-height: 650px;
|
max-height: 650px;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
padding: 14px 16px 14px 24px;
|
padding: 14px 16px 14px 24px;
|
||||||
box-shadow: ${({ theme }) => theme.shadowLeft};
|
box-shadow: ${({theme}) => theme.shadowLeft};
|
||||||
background-color: ${({ theme }) => theme.colors.white};
|
background-color: ${({theme}) => theme.colors.white};
|
||||||
transition: transform 0.5s ease-in-out;
|
transition: transform 0.5s ease-in-out;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
|
||||||
@ -27,122 +27,89 @@ const FiltersMenuStyle = styled(FlexColumn)`
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: ${({ theme }) => theme.overMobile}) {
|
@media (min-width: ${({theme}) => theme.overMobile}) {
|
||||||
width: 310px;
|
width: 310px;
|
||||||
max-height: none;
|
max-height: none;
|
||||||
top: 50px;
|
top: 50px;
|
||||||
right: auto;
|
right: auto;
|
||||||
left: 0;
|
left: 0;
|
||||||
box-shadow: ${({ theme }) => theme.shadowRight};
|
box-shadow: ${({theme}) => theme.shadowRight};
|
||||||
padding: 32px 32px 64px;
|
padding: 32px 32px 64px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const FiltersMenu = (props) => {
|
const FiltersMenu = (props) => {
|
||||||
const sortByHandler = (value) => {
|
const resetHandler = () => {
|
||||||
props.dispatch({ type: CHALLENGES_ACTION.SET_SORT_BY, payload: value });
|
props.sortByHandler(0);
|
||||||
};
|
props.statusHandler(0);
|
||||||
|
props.challengeTypeHandler(0);
|
||||||
|
props.commercialHandler(0);
|
||||||
|
};
|
||||||
|
|
||||||
const statusHandler = (value) => {
|
return (
|
||||||
props.dispatch({
|
<>
|
||||||
type: CHALLENGES_ACTION.SET_STATUS_FILTER,
|
<TransBack backgroundColor={theme.colors.dark03} translateX={props.translateX}
|
||||||
payload: value,
|
opacity={props.opacity} onClick={props.toggleFiltersMenu}
|
||||||
});
|
display={props.transBackDisplay ? props.transBackDisplay : 'flex'}/>
|
||||||
};
|
<FiltersMenuStyle translateX={props.translateX} gap='16px'>
|
||||||
|
<FilterBy header='Sort by' options={filterOptions[0]}
|
||||||
const challengeTypeHandler = (value) => {
|
handler={props.sortByHandler} option={props.sortBy}/>
|
||||||
props.dispatch({
|
<FilterBy header='Status' options={filterOptions[1]}
|
||||||
type: CHALLENGES_ACTION.SET_CHALLENGE_TYPE_FILTER,
|
handler={props.statusHandler} option={props.status}/>
|
||||||
payload: value,
|
<FilterBy header='Challenge type' options={filterOptions[2]}
|
||||||
});
|
handler={props.challengeTypeHandler} option={props.challengeType}/>
|
||||||
};
|
<FilterBy header='Commercial' options={filterOptions[3]}
|
||||||
|
handler={props.commercialHandler} option={props.commercial}/>
|
||||||
const commercialHandler = (value) => {
|
<Media query={theme.mobile}>
|
||||||
props.dispatch({
|
<FlexRow gap='16px' margin='14px 0 0 0'>
|
||||||
type: CHALLENGES_ACTION.SET_COMMERCIAL_FILTER,
|
<Button width='64px' height='28px' handler={props.toggleFiltersMenu}>
|
||||||
payload: value,
|
Done
|
||||||
});
|
</Button>
|
||||||
};
|
<Button width='64px' height='28px' backgroundColor={theme.colors.dark} handler={resetHandler}>
|
||||||
|
Reset
|
||||||
const resetHandler = () => {
|
</Button>
|
||||||
sortByHandler(0);
|
</FlexRow>
|
||||||
statusHandler(0);
|
</Media>
|
||||||
challengeTypeHandler(0);
|
<Media query={theme.desktop}>
|
||||||
commercialHandler(0);
|
<FlexRow margin='8px 0 0 0' width='94%' alignmentX='flex-start'>
|
||||||
};
|
<Button width='72px' height='34px' backgroundColor={theme.colors.green} handler={resetHandler}>
|
||||||
|
Reset
|
||||||
return (
|
</Button>
|
||||||
<>
|
</FlexRow>
|
||||||
<TransBack
|
</Media>
|
||||||
backgroundColor={theme.colors.dark03}
|
</FiltersMenuStyle>
|
||||||
translateX={props.translateX}
|
</>
|
||||||
opacity={props.opacity}
|
);
|
||||||
onClick={() =>
|
|
||||||
props.dispatch({ type: CHALLENGES_ACTION.TOGGLE_FILTERS_MENU })
|
|
||||||
}
|
|
||||||
display={props.transBackDisplay ? props.transBackDisplay : 'flex'}
|
|
||||||
/>
|
|
||||||
<FiltersMenuStyle translateX={props.translateX} gap="16px">
|
|
||||||
<FilterBy
|
|
||||||
header="Sort by"
|
|
||||||
options={filterOptions[0]}
|
|
||||||
handler={sortByHandler}
|
|
||||||
option={props.sortBy}
|
|
||||||
/>
|
|
||||||
<FilterBy
|
|
||||||
header="Status"
|
|
||||||
options={filterOptions[1]}
|
|
||||||
handler={statusHandler}
|
|
||||||
option={props.status}
|
|
||||||
/>
|
|
||||||
<FilterBy
|
|
||||||
header="Challenge type"
|
|
||||||
options={filterOptions[2]}
|
|
||||||
handler={challengeTypeHandler}
|
|
||||||
option={props.challengeTypeFilter}
|
|
||||||
/>
|
|
||||||
<FilterBy
|
|
||||||
header="Commercial"
|
|
||||||
options={filterOptions[3]}
|
|
||||||
handler={commercialHandler}
|
|
||||||
option={props.commercialFilter}
|
|
||||||
/>
|
|
||||||
<Media query={theme.mobile}>
|
|
||||||
<FlexRow gap="16px" margin="14px 0 0 0">
|
|
||||||
<Button
|
|
||||||
width="64px"
|
|
||||||
height="28px"
|
|
||||||
handler={() =>
|
|
||||||
props.dispatch({ type: CHALLENGES_ACTION.TOGGLE_FILTERS_MENU })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Done
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
width="64px"
|
|
||||||
height="28px"
|
|
||||||
backgroundColor={theme.colors.dark}
|
|
||||||
handler={resetHandler}
|
|
||||||
>
|
|
||||||
Reset
|
|
||||||
</Button>
|
|
||||||
</FlexRow>
|
|
||||||
</Media>
|
|
||||||
<Media query={theme.desktop}>
|
|
||||||
<FlexRow margin="8px 0 0 0" width="94%" alignmentX="flex-start">
|
|
||||||
<Button
|
|
||||||
width="72px"
|
|
||||||
height="34px"
|
|
||||||
backgroundColor={theme.colors.green}
|
|
||||||
handler={resetHandler}
|
|
||||||
>
|
|
||||||
Reset
|
|
||||||
</Button>
|
|
||||||
</FlexRow>
|
|
||||||
</Media>
|
|
||||||
</FiltersMenuStyle>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FiltersMenu;
|
FiltersMenu.propTypes = {
|
||||||
|
translateX: PropsTypes.string,
|
||||||
|
opacity: PropsTypes.string,
|
||||||
|
transBackDisplay: PropsTypes.string,
|
||||||
|
toggleFiltersMenu: PropsTypes.func,
|
||||||
|
sortByHandler: PropsTypes.func,
|
||||||
|
statusHandler: PropsTypes.func,
|
||||||
|
challengeTypeHandler: PropsTypes.func,
|
||||||
|
commercialHandler: PropsTypes.func,
|
||||||
|
sortBy: PropsTypes.number,
|
||||||
|
status: PropsTypes.number,
|
||||||
|
challengeType: PropsTypes.number,
|
||||||
|
commercial: PropsTypes.number,
|
||||||
|
};
|
||||||
|
|
||||||
|
FiltersMenu.defaultProps = {
|
||||||
|
translateX: '',
|
||||||
|
opacity: '',
|
||||||
|
transBackDisplay: 'flex',
|
||||||
|
toggleFiltersMenu: null,
|
||||||
|
sortByHandler: null,
|
||||||
|
statusHandler: null,
|
||||||
|
challengeTypeHandler: null,
|
||||||
|
commercialHandler: null,
|
||||||
|
sortBy: 0,
|
||||||
|
status: 0,
|
||||||
|
challengeType: 0,
|
||||||
|
commercial: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FiltersMenu;
|
@ -1,35 +1,31 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { FlexRow } from '../../utils/containers';
|
import {FlexRow} from '../../utils/containers';
|
||||||
|
import PropsTypes from 'prop-types';
|
||||||
|
|
||||||
const FilterStyle = styled(FlexRow)`
|
const FilterStyle = styled(FlexRow)`
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border-radius: ${({ borderRadius }) =>
|
border-radius: ${({borderRadius}) => borderRadius ? borderRadius : '32px'};
|
||||||
borderRadius ? borderRadius : '32px'};
|
border: 1px solid ${({theme}) => theme.colors.dark};
|
||||||
border: 1px solid ${({ theme }) => theme.colors.dark};
|
box-shadow: ${({theme}) => theme.shadow};
|
||||||
box-shadow: ${({ theme }) => theme.shadow};
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: ${({ theme, active }) =>
|
background-color: ${({theme, active}) => active ? theme.colors.dark : theme.colors.white};
|
||||||
active ? theme.colors.dark : theme.colors.white};
|
|
||||||
transition: transform 0.3s ease-in-out;
|
transition: transform 0.3s ease-in-out;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
color: ${({ theme, active }) =>
|
color: ${({theme, active}) => active ? theme.colors.white : theme.colors.dark};
|
||||||
active ? theme.colors.white : theme.colors.dark};
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: ${({ theme, active }) =>
|
color: ${({theme, active}) => active ? theme.colors.white : theme.colors.dark};
|
||||||
active ? theme.colors.white : theme.colors.dark};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
background-color: ${({ theme, active }) =>
|
background-color: ${({theme, active}) => active ? theme.colors.white : theme.colors.dark};
|
||||||
active ? theme.colors.white : theme.colors.dark};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@ -38,32 +34,36 @@ const FilterStyle = styled(FlexRow)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Filter = (props) => {
|
const Filter = (props) => {
|
||||||
const onCheckHandler = (e) => {
|
const onCheckHandler = (e) => {
|
||||||
if (e.target.checked) props.handler(Number(e.target.value));
|
if (e.target.checked)
|
||||||
};
|
props.handler(Number(e.target.value));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FilterStyle
|
<FilterStyle as='label' borderRadius={props.borderRadius} htmlFor={props.id}
|
||||||
as="label"
|
active={props.option === props.index}>
|
||||||
borderRadius={props.borderRadius}
|
{props.children}
|
||||||
htmlFor={props.id}
|
</FilterStyle>
|
||||||
active={props.option === props.index}
|
<FlexRow display='none' as='input' type='radio' value={props.index}
|
||||||
>
|
id={props.id} name={props.name} checked={props.option === props.index}
|
||||||
{props.children}
|
onChange={(e) => onCheckHandler(e)}/>
|
||||||
</FilterStyle>
|
</>
|
||||||
<FlexRow
|
);
|
||||||
display="none"
|
|
||||||
as="input"
|
|
||||||
type="radio"
|
|
||||||
value={props.index}
|
|
||||||
id={props.id}
|
|
||||||
name={props.name}
|
|
||||||
checked={props.option === props.index}
|
|
||||||
onChange={(e) => onCheckHandler(e)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Filter;
|
Filter.propTypes = {
|
||||||
|
index: PropsTypes.number.isRequired,
|
||||||
|
option: PropsTypes.number.isRequired,
|
||||||
|
handler: PropsTypes.func,
|
||||||
|
id: PropsTypes.string.isRequired,
|
||||||
|
name: PropsTypes.string.isRequired,
|
||||||
|
children: PropsTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
Filter.defaultProps = {
|
||||||
|
handler: null,
|
||||||
|
children: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Filter;
|
@ -1,35 +1,37 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlexRow, Svg } from '../../utils/containers';
|
import {FlexRow, Svg} from '../../utils/containers';
|
||||||
import CircleNumber from './CircleNumber';
|
import CircleNumber from './CircleNumber';
|
||||||
import polygon from '../../assets/polygon.svg';
|
import polygon from '../../assets/polygon.svg';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import theme from '../../utils/theme';
|
import theme from '../../utils/theme';
|
||||||
|
import PropsTypes from 'prop-types';
|
||||||
import { NEXT_PAGE, PREVIOUS_PAGE } from '../../utils/globals';
|
import { NEXT_PAGE, PREVIOUS_PAGE } from '../../utils/globals';
|
||||||
|
|
||||||
|
|
||||||
const PagerStyle = styled(FlexRow)`
|
const PagerStyle = styled(FlexRow)`
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
|
|
||||||
@media (min-width: ${({ theme }) => theme.overMobile}) {
|
@media (min-width: ${({theme}) => theme.overMobile}) {
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const LeftArrow = styled(Svg)`
|
const LeftArrow = styled(Svg)`
|
||||||
background-color: ${({ backgroundColor }) => backgroundColor};
|
background-color: ${({backgroundColor}) => backgroundColor};
|
||||||
cursor: ${({ backgroundColor }) =>
|
cursor: ${({backgroundColor}) => (backgroundColor === 'transparent') ? 'auto' : 'pointer'};
|
||||||
backgroundColor === 'transparent' ? 'auto' : 'pointer'};
|
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
transition: background-color, transform 0.3s ease-in-out;
|
transition: background-color, transform 0.3s ease-in-out;
|
||||||
|
|
||||||
&:hover,
|
&:hover, &:focus {
|
||||||
&:focus {
|
background-color: ${({
|
||||||
background-color: ${({ theme, backgroundColor }) =>
|
theme,
|
||||||
backgroundColor === 'transparent' ? 'transparent' : theme.colors.green};
|
backgroundColor
|
||||||
|
}) => (backgroundColor === 'transparent') ? 'transparent' : theme.colors.green};
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: ${({ theme }) => theme.overMobile}) {
|
@media (min-width: ${({theme}) => theme.overMobile}) {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
}
|
}
|
||||||
@ -38,50 +40,57 @@ const LeftArrow = styled(Svg)`
|
|||||||
const RightArrow = styled(LeftArrow)`
|
const RightArrow = styled(LeftArrow)`
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
|
|
||||||
&:hover,
|
&:hover, &:focus {
|
||||||
&:focus {
|
background-color: ${({
|
||||||
background-color: ${({ theme, backgroundColor }) =>
|
theme,
|
||||||
backgroundColor === 'transparent' ? 'transparent' : theme.colors.green};
|
backgroundColor
|
||||||
|
}) => (backgroundColor === 'transparent') ? 'transparent' : theme.colors.green};
|
||||||
transform: scale(1.1) rotate(180deg);
|
transform: scale(1.1) rotate(180deg);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Pager = (props) => {
|
const Pager = (props) => {
|
||||||
const leftArrowVisible = () => {
|
const leftArrowVisible = () => {
|
||||||
if (props.pageNr === 1) return 'transparent';
|
if (props.pageNr === 1)
|
||||||
return theme.colors.dark;
|
return 'transparent';
|
||||||
};
|
return theme.colors.dark;
|
||||||
|
};
|
||||||
|
|
||||||
const rightArrowVisible = () => {
|
const rightArrowVisible = () => {
|
||||||
if (props.pageNr === props.pages) return 'transparent';
|
if (props.pageNr === props.pages)
|
||||||
return theme.colors.dark;
|
return 'transparent';
|
||||||
};
|
return theme.colors.dark;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PagerStyle>
|
<PagerStyle>
|
||||||
<LeftArrow
|
<LeftArrow as='a' href='#start' src={polygon} onClick={() => PREVIOUS_PAGE(props.pageNr, props.setPageNr)} size='cover'
|
||||||
as="a"
|
backgroundColor={leftArrowVisible()}/>
|
||||||
href="#start"
|
<CircleNumber number={props.number} width={props.width} borderRadius={props.borderRadius}/>
|
||||||
src={polygon}
|
<RightArrow as='a' href='#start' src={polygon} onClick={() => NEXT_PAGE(props.elements, props.pageNr, props.setPageNr)} size='cover'
|
||||||
onClick={() => PREVIOUS_PAGE(props.pageNr, props.setPage)}
|
backgroundColor={rightArrowVisible()}/>
|
||||||
size="cover"
|
</PagerStyle>
|
||||||
backgroundColor={leftArrowVisible()}
|
);
|
||||||
/>
|
|
||||||
<CircleNumber
|
|
||||||
number={props.number}
|
|
||||||
width={props.width}
|
|
||||||
borderRadius={props.borderRadius}
|
|
||||||
/>
|
|
||||||
<RightArrow
|
|
||||||
as="a"
|
|
||||||
href="#start"
|
|
||||||
src={polygon}
|
|
||||||
onClick={() => NEXT_PAGE(props.elements, props.pageNr, props.setPage)}
|
|
||||||
size="cover"
|
|
||||||
backgroundColor={rightArrowVisible()}
|
|
||||||
/>
|
|
||||||
</PagerStyle>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Pager;
|
Pager.propTypes = {
|
||||||
|
previousPage: PropsTypes.func,
|
||||||
|
pageNr: PropsTypes.number,
|
||||||
|
nextPage: PropsTypes.func,
|
||||||
|
pages: PropsTypes.number,
|
||||||
|
number: PropsTypes.string,
|
||||||
|
width: PropsTypes.string,
|
||||||
|
borderRadius: PropsTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
Pager.defaultProps = {
|
||||||
|
previousPage: null,
|
||||||
|
pageNr: 1,
|
||||||
|
nextPage: null,
|
||||||
|
pages: 1,
|
||||||
|
number: '',
|
||||||
|
width: null,
|
||||||
|
borderRadius: null
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Pager;
|
@ -7,10 +7,6 @@ import { Body, Medium } from '../../utils/fonts';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import ColumnFilterIcon from './ColumnFilterIcon';
|
import ColumnFilterIcon from './ColumnFilterIcon';
|
||||||
|
|
||||||
const TableStyle = styled(FlexColumn)`
|
|
||||||
overflow-x: ${({metrics}) => metrics > 10 ? 'scroll' : 'auto'};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Line = styled(FlexRow)`
|
const Line = styled(FlexRow)`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: ${({ top }) => (top ? top : 'auto')};
|
top: ${({ top }) => (top ? top : 'auto')};
|
||||||
@ -109,7 +105,7 @@ const Table = (props) => {
|
|||||||
as="td"
|
as="td"
|
||||||
order={props.iterableColumnElement.order}
|
order={props.iterableColumnElement.order}
|
||||||
textAlign={props.iterableColumnElement.align}
|
textAlign={props.iterableColumnElement.align}
|
||||||
minWidth="88px"
|
minWidth="72px"
|
||||||
margin="auto 0"
|
margin="auto 0"
|
||||||
overflowWrap="anywhere"
|
overflowWrap="anywhere"
|
||||||
>
|
>
|
||||||
@ -137,7 +133,6 @@ const Table = (props) => {
|
|||||||
order={elemName.order}
|
order={elemName.order}
|
||||||
textAlign={elemName.align}
|
textAlign={elemName.align}
|
||||||
margin="auto 0"
|
margin="auto 0"
|
||||||
minWidth="88px"
|
|
||||||
overflowWrap="anywhere"
|
overflowWrap="anywhere"
|
||||||
>
|
>
|
||||||
{IS_MOBILE() && (
|
{IS_MOBILE() && (
|
||||||
@ -158,7 +153,7 @@ const Table = (props) => {
|
|||||||
let elementsToMap = props.elements.slice(n, n + ELEMENTS_PER_PAGE * 2);
|
let elementsToMap = props.elements.slice(n, n + ELEMENTS_PER_PAGE * 2);
|
||||||
if (elementsToMap.length > 0) {
|
if (elementsToMap.length > 0) {
|
||||||
return (
|
return (
|
||||||
<TableStyle as="table" margin="32px 0 72px 0" width="100%">
|
<FlexColumn as="table" margin="32px 0 72px 0" width="100%">
|
||||||
<FlexColumn as="tbody" width="100%">
|
<FlexColumn as="tbody" width="100%">
|
||||||
<Grid
|
<Grid
|
||||||
as="tr"
|
as="tr"
|
||||||
@ -195,9 +190,7 @@ const Table = (props) => {
|
|||||||
width={elem === 'when' ? '100%' : 'auto'}
|
width={elem === 'when' ? '100%' : 'auto'}
|
||||||
padding="0 4px 0 0"
|
padding="0 4px 0 0"
|
||||||
overflowWrap="anywhere"
|
overflowWrap="anywhere"
|
||||||
minWidth="72px"
|
minWidth={elem === 'result' ? '72px' : 'none'}
|
||||||
|
|
||||||
// minWidth={elem === 'result' ? '72px' : 'none'}
|
|
||||||
>
|
>
|
||||||
{elem.replace('.', ' ')}
|
{elem.replace('.', ' ')}
|
||||||
</Medium>
|
</Medium>
|
||||||
@ -240,7 +233,7 @@ const Table = (props) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
</TableStyle>
|
</FlexColumn>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <Medium margin="72px 0">No results ;c</Medium>;
|
return <Medium margin="72px 0">No results ;c</Medium>;
|
||||||
|
@ -1,102 +1,163 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Body, H1 } from '../../utils/fonts';
|
||||||
|
import { FlexColumn, FlexRow, Svg } from '../../utils/containers';
|
||||||
|
import Search from '../../components/generic/Search';
|
||||||
|
import Pager from '../../components/generic/Pager';
|
||||||
|
import challengeSearchQueryHandler from './challengeSearchQueryHandler';
|
||||||
|
import renderChallenges from './renderChallenges';
|
||||||
import Media from 'react-media';
|
import Media from 'react-media';
|
||||||
import theme from '../../utils/theme';
|
import theme from '../../utils/theme';
|
||||||
|
import cupIco from '../../assets/cup_ico.svg';
|
||||||
import getChallenges from '../../api/getChallenges';
|
import getChallenges from '../../api/getChallenges';
|
||||||
import { CHALLENGES_STATUS_FILTER } from '../../utils/globals';
|
import { CALC_PAGES, CHALLENGES_STATUS_FILTER } from '../../utils/globals';
|
||||||
|
import Loading from '../../components/generic/Loading';
|
||||||
|
import ChallengesStyle from './ChallengesStyle';
|
||||||
import FiltersMenu from '../../components/challenges_list/FiltersMenu';
|
import FiltersMenu from '../../components/challenges_list/FiltersMenu';
|
||||||
import statusFilterHandle from './functions/statusFilterHandle';
|
import statusFilter from './statusFilter';
|
||||||
import ChallengesMobile from './components/ChallengesMobile';
|
|
||||||
import ChallengesDesktop from './components/ChallengesDesktop';
|
|
||||||
import challengeSearchQueryHandler from './functions/challengeSearchQueryHandler';
|
|
||||||
import ChallengesReducer from './model/ChallengesReducer';
|
|
||||||
import CHALLENGES_ACTION from './model/ChallengesActionEnum';
|
|
||||||
|
|
||||||
const Challenges = () => {
|
const Challenges = () => {
|
||||||
const [state, dispatch] = React.useReducer(ChallengesReducer, {
|
const [pageNr, setPageNr] = React.useState(1);
|
||||||
pageNr: 1,
|
const [challengesFromAPI, setChallengesFromAPI] = React.useState([]);
|
||||||
challengesFromAPI: [],
|
const [challenges, setChallenges] = React.useState([]);
|
||||||
challenges: [],
|
const [challengesFiltered, setChallengesFiltered] = React.useState([]);
|
||||||
challengesFiltered: [],
|
const [filtersMenu, setFiltersMenu] = React.useState(false);
|
||||||
filtersMenu: false,
|
const [sortBy, setSortBy] = React.useState(0);
|
||||||
sortBy: 0,
|
const [status, setStatus] = React.useState(CHALLENGES_STATUS_FILTER.BOTH);
|
||||||
statusFilter: CHALLENGES_STATUS_FILTER.BOTH,
|
const [challengeType, setChallengeType] = React.useState(0);
|
||||||
challengeTypeFilter: 0,
|
const [commercial, setCommercial] = React.useState(0);
|
||||||
commercialFilter: 0,
|
const [loading, setLoading] = React.useState(true);
|
||||||
loading: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
React.useMemo(() => {
|
React.useEffect(() => {
|
||||||
getChallenges(dispatch);
|
challengesRequest();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
statusFilterHandle(state.statusFilter, state.challenges, dispatch);
|
statusFilter(status, challenges, setChallengesFiltered);
|
||||||
}, [state.statusFilter, state.challenges]);
|
}, [status, challenges]);
|
||||||
|
|
||||||
const setPage = React.useCallback((value) => {
|
const challengesRequest = () => {
|
||||||
dispatch({ type: CHALLENGES_ACTION.SET_PAGE, payload: value });
|
getChallenges(
|
||||||
}, []);
|
[setChallengesFromAPI, setChallenges, setChallengesFiltered],
|
||||||
|
setLoading
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const searchQueryHandler = React.useCallback(
|
const searchQueryHandler = (event) => {
|
||||||
(event) =>
|
challengeSearchQueryHandler(
|
||||||
challengeSearchQueryHandler(
|
event,
|
||||||
event,
|
challengesFromAPI,
|
||||||
state.challengesFromAPI,
|
setPageNr,
|
||||||
state.setPageNr,
|
setChallenges
|
||||||
dispatch
|
);
|
||||||
),
|
};
|
||||||
[state.challengesFromAPI, state.setPageNr]
|
|
||||||
);
|
|
||||||
|
|
||||||
const filtersMenuRender = React.useCallback(
|
const toggleFiltersMenu = () => {
|
||||||
(translateX = '0', opacity = '1', transBackDisplay = 'none') => {
|
let newFiltersMenu = !filtersMenu;
|
||||||
return (
|
setFiltersMenu(newFiltersMenu);
|
||||||
<FiltersMenu
|
};
|
||||||
dispatch={dispatch}
|
|
||||||
sortBy={state.sortBy}
|
const filtersMenuRender = (
|
||||||
status={state.statusFilter}
|
translateX = '0',
|
||||||
challengeTypeFilter={state.challengeTypeFilter}
|
opacity = '1',
|
||||||
commercialFilter={state.commercialFilter}
|
transBackDisplay = 'none'
|
||||||
translateX={translateX}
|
) => {
|
||||||
opacity={opacity}
|
return (
|
||||||
transBackDisplay={transBackDisplay}
|
<FiltersMenu
|
||||||
/>
|
toggleFiltersMenu={toggleFiltersMenu}
|
||||||
);
|
sortByHandler={setSortBy}
|
||||||
},
|
statusHandler={setStatus}
|
||||||
[
|
challengeTypeHandler={setChallengeType}
|
||||||
state.sortBy,
|
commercialHandler={setCommercial}
|
||||||
state.statusFilter,
|
sortBy={sortBy}
|
||||||
state.challengeTypeFilter,
|
status={status}
|
||||||
state.commercialFilter,
|
challengeType={challengeType}
|
||||||
]
|
commercial={commercial}
|
||||||
);
|
translateX={translateX}
|
||||||
|
opacity={opacity}
|
||||||
|
transBackDisplay={transBackDisplay}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileRender = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{filtersMenuRender(
|
||||||
|
filtersMenu ? '0' : '100vw',
|
||||||
|
filtersMenu ? '1' : '0',
|
||||||
|
'flex'
|
||||||
|
)}
|
||||||
|
<ChallengesStyle as="main" id="start">
|
||||||
|
<FlexColumn className="ChallengesStyle__page-container">
|
||||||
|
<H1 as="h1">Challenges</H1>
|
||||||
|
<Search
|
||||||
|
searchQueryHandler={searchQueryHandler}
|
||||||
|
filterButton
|
||||||
|
toggleFiltersMenu={toggleFiltersMenu}
|
||||||
|
/>
|
||||||
|
<FlexColumn width="100%">
|
||||||
|
<Loading visible={loading} />
|
||||||
|
{renderChallenges(pageNr, challengesFiltered)}
|
||||||
|
</FlexColumn>
|
||||||
|
</FlexColumn>
|
||||||
|
{!loading && (
|
||||||
|
<Pager
|
||||||
|
elements={challengesFiltered}
|
||||||
|
pageNr={pageNr}
|
||||||
|
setPageNr={setPageNr}
|
||||||
|
pages={CALC_PAGES(challengesFiltered)}
|
||||||
|
width="48px"
|
||||||
|
borderRadius="64px"
|
||||||
|
number={`${pageNr} / ${CALC_PAGES(challengesFiltered)}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ChallengesStyle>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const desktopRender = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{filtersMenuRender()}
|
||||||
|
<ChallengesStyle as="main" id="start">
|
||||||
|
<FlexColumn className="ChallengesStyle__page-container">
|
||||||
|
<FlexRow className="ChallengesStyle__page-header-container">
|
||||||
|
<FlexColumn className="ChallengesStyle__page-header">
|
||||||
|
<H1 as="h1">Challenges</H1>
|
||||||
|
<Body className="ChallengesStyle__header-content">
|
||||||
|
Increase your machine learning skills by competing in our
|
||||||
|
exciting challenges.
|
||||||
|
</Body>
|
||||||
|
<Search searchQueryHandler={searchQueryHandler} />
|
||||||
|
</FlexColumn>
|
||||||
|
<Svg src={cupIco} className="ChallengesStyle__main-image" />
|
||||||
|
</FlexRow>
|
||||||
|
<FlexColumn width="100%">
|
||||||
|
<Loading visible={loading} />
|
||||||
|
{renderChallenges(pageNr, challengesFiltered)}
|
||||||
|
</FlexColumn>
|
||||||
|
</FlexColumn>
|
||||||
|
{!loading && (
|
||||||
|
<Pager
|
||||||
|
pageNr={pageNr}
|
||||||
|
setPageNr={setPageNr}
|
||||||
|
elements={challengesFiltered}
|
||||||
|
pages={CALC_PAGES(challengesFiltered)}
|
||||||
|
width="72px"
|
||||||
|
borderRadius="64px"
|
||||||
|
number={`${pageNr} / ${CALC_PAGES(challengesFiltered)}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ChallengesStyle>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Media query={theme.mobile}>
|
<Media query={theme.mobile}>{mobileRender()}</Media>
|
||||||
<ChallengesMobile
|
<Media query={theme.desktop}>{desktopRender()}</Media>
|
||||||
dispatch={dispatch}
|
|
||||||
filtersMenuRender={filtersMenuRender}
|
|
||||||
searchQueryHandler={searchQueryHandler}
|
|
||||||
setPage={setPage}
|
|
||||||
filtersMenu={state.filtersMenu}
|
|
||||||
loading={state.loading}
|
|
||||||
pageNr={state.pageNr}
|
|
||||||
challengesFiltered={state.challengesFiltered}
|
|
||||||
/>
|
|
||||||
</Media>
|
|
||||||
<Media query={theme.desktop}>
|
|
||||||
<ChallengesDesktop
|
|
||||||
dispatch={dispatch}
|
|
||||||
filtersMenuRender={filtersMenuRender}
|
|
||||||
searchQueryHandler={searchQueryHandler}
|
|
||||||
setPage={setPage}
|
|
||||||
filtersMenu={state.filtersMenu}
|
|
||||||
loading={state.loading}
|
|
||||||
pageNr={state.pageNr}
|
|
||||||
challengesFiltered={state.challengesFiltered}
|
|
||||||
/>
|
|
||||||
</Media>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
19
src/pages/Challanges/challengeSearchQueryHandler.js
Normal file
19
src/pages/Challanges/challengeSearchQueryHandler.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const challengeSearchQueryHandler = (event, challengesFromAPI, setPageNr, setChallenges) => {
|
||||||
|
let searchQuery = event.target.value;
|
||||||
|
let challengesToRender = [];
|
||||||
|
setPageNr(1);
|
||||||
|
if (searchQuery === '')
|
||||||
|
setChallenges(challengesFromAPI);
|
||||||
|
else {
|
||||||
|
for (let challenge of challengesFromAPI) {
|
||||||
|
const {title, description, type, mainMetric, bestScore, deadline, baseline, prize} = challenge;
|
||||||
|
const str = `${title} ${description} ${type} ${mainMetric} ${bestScore}
|
||||||
|
${deadline ? deadline.slice(11, 16) : ''} ${deadline ? deadline.slice(0, 10) : ''} ${baseline} ${prize}`;
|
||||||
|
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
|
||||||
|
challengesToRender.push(challenge);
|
||||||
|
}
|
||||||
|
setChallenges(challengesToRender);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default challengeSearchQueryHandler;
|
@ -1,51 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import ChallengesStyle from '../ChallengesStyle';
|
|
||||||
import { FlexColumn, FlexRow } from '../../../utils/containers';
|
|
||||||
import Pager from '../../../components/generic/Pager';
|
|
||||||
import { H1, Body } from '../../../utils/fonts';
|
|
||||||
import Search from '../../../components/generic/Search';
|
|
||||||
import { CALC_PAGES } from '../../../utils/globals';
|
|
||||||
import renderChallenges from '../functions/renderChallenges';
|
|
||||||
import Loading from '../../../components/generic/Loading';
|
|
||||||
import cupIco from '../../../assets/cup_ico.svg';
|
|
||||||
import { Svg } from '../../../utils/containers';
|
|
||||||
|
|
||||||
const ChallengesDesktop = (props) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{props.filtersMenuRender()}
|
|
||||||
<ChallengesStyle as="main" id="start">
|
|
||||||
<FlexColumn className="ChallengesStyle__page-container">
|
|
||||||
<FlexRow className="ChallengesStyle__page-header-container">
|
|
||||||
<FlexColumn className="ChallengesStyle__page-header">
|
|
||||||
<H1 as="h1">Challenges</H1>
|
|
||||||
<Body className="ChallengesStyle__header-content">
|
|
||||||
Increase your machine learning skills by competing in our
|
|
||||||
exciting challenges.
|
|
||||||
</Body>
|
|
||||||
<Search searchQueryHandler={props.searchQueryHandler} />
|
|
||||||
</FlexColumn>
|
|
||||||
<Svg src={cupIco} className="ChallengesStyle__main-image" />
|
|
||||||
</FlexRow>
|
|
||||||
<FlexColumn width="100%">
|
|
||||||
<Loading visible={props.loading} />
|
|
||||||
{renderChallenges(props.pageNr, props.challengesFiltered)}
|
|
||||||
</FlexColumn>
|
|
||||||
</FlexColumn>
|
|
||||||
{!props.loading && (
|
|
||||||
<Pager
|
|
||||||
pageNr={props.pageNr}
|
|
||||||
setPage={props.setPage}
|
|
||||||
elements={props.challengesFiltered}
|
|
||||||
pages={CALC_PAGES(props.challengesFiltered)}
|
|
||||||
width="72px"
|
|
||||||
borderRadius="64px"
|
|
||||||
number={`${props.pageNr} / ${CALC_PAGES(props.challengesFiltered)}`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ChallengesStyle>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ChallengesDesktop;
|
|
@ -1,53 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import ChallengesStyle from '../ChallengesStyle';
|
|
||||||
import { FlexColumn } from '../../../utils/containers';
|
|
||||||
import Pager from '../../../components/generic/Pager';
|
|
||||||
import { H1 } from '../../../utils/fonts';
|
|
||||||
import Search from '../../../components/generic/Search';
|
|
||||||
import { CALC_PAGES } from '../../../utils/globals';
|
|
||||||
import renderChallenges from '../functions/renderChallenges';
|
|
||||||
import Loading from '../../../components/generic/Loading';
|
|
||||||
import CHALLENGES_ACTION from '../model/ChallengesActionEnum';
|
|
||||||
|
|
||||||
const ChallengesMobile = (props) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{props.filtersMenuRender(
|
|
||||||
props.filtersMenu ? '0' : '100vw',
|
|
||||||
props.filtersMenu ? '1' : '0',
|
|
||||||
'flex'
|
|
||||||
)}
|
|
||||||
<ChallengesStyle as="main" id="start">
|
|
||||||
<FlexColumn className="ChallengesStyle__page-container">
|
|
||||||
<H1 as="h1">Challenges</H1>
|
|
||||||
<Search
|
|
||||||
searchQueryHandler={props.searchQueryHandler}
|
|
||||||
filterButton
|
|
||||||
toggleFiltersMenu={() =>
|
|
||||||
props.dispatch({
|
|
||||||
type: CHALLENGES_ACTION.TOGGLE_FILTERS_MENU,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<FlexColumn width="100%">
|
|
||||||
<Loading visible={props.loading} />
|
|
||||||
{renderChallenges(props.pageNr, props.challengesFiltered)}
|
|
||||||
</FlexColumn>
|
|
||||||
</FlexColumn>
|
|
||||||
{!props.loading && (
|
|
||||||
<Pager
|
|
||||||
width="48px"
|
|
||||||
borderRadius="64px"
|
|
||||||
elements={props.challengesFiltered}
|
|
||||||
pageNr={props.pageNr}
|
|
||||||
setPage={props.setPage}
|
|
||||||
pages={CALC_PAGES(props.challengesFiltered)}
|
|
||||||
number={`${props.pageNr} / ${CALC_PAGES(props.challengesFiltered)}`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ChallengesStyle>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ChallengesMobile;
|
|
@ -1,38 +0,0 @@
|
|||||||
import CHALLENGES_ACTION from '../model/ChallengesActionEnum';
|
|
||||||
|
|
||||||
const challengeSearchQueryHandler = (event, challengesFromAPI, dispatch) => {
|
|
||||||
let searchQuery = event.target.value;
|
|
||||||
let challengesToRender = [];
|
|
||||||
dispatch({ type: CHALLENGES_ACTION.SET_PAGE, payload: 1 });
|
|
||||||
if (searchQuery === '')
|
|
||||||
dispatch({
|
|
||||||
type: CHALLENGES_ACTION.SET_CHALLENGES,
|
|
||||||
payload: challengesFromAPI,
|
|
||||||
});
|
|
||||||
else {
|
|
||||||
for (let challenge of challengesFromAPI) {
|
|
||||||
const {
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
type,
|
|
||||||
mainMetric,
|
|
||||||
bestScore,
|
|
||||||
deadline,
|
|
||||||
baseline,
|
|
||||||
prize,
|
|
||||||
} = challenge;
|
|
||||||
const str = `${title} ${description} ${type} ${mainMetric} ${bestScore}
|
|
||||||
${deadline ? deadline.slice(11, 16) : ''} ${
|
|
||||||
deadline ? deadline.slice(0, 10) : ''
|
|
||||||
} ${baseline} ${prize}`;
|
|
||||||
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
|
|
||||||
challengesToRender.push(challenge);
|
|
||||||
}
|
|
||||||
dispatch({
|
|
||||||
type: CHALLENGES_ACTION.SET_CHALLENGES,
|
|
||||||
payload: challengesToRender,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default challengeSearchQueryHandler;
|
|
@ -1,16 +0,0 @@
|
|||||||
const CHALLENGES_ACTION = {
|
|
||||||
NEXT_PAGE: 'next_page',
|
|
||||||
PREVIOUS_PAGE: 'previous_page',
|
|
||||||
SET_PAGE: 'set_page',
|
|
||||||
LOAD_CHALLENGES_FROM_API: 'load_challenges_from_api',
|
|
||||||
SET_CHALLENGES: 'set_challenges',
|
|
||||||
SET_CHALLENGES_FILTERED: 'set_challenges_filtered',
|
|
||||||
TOGGLE_FILTERS_MENU: 'toggle_filters_menu',
|
|
||||||
TOGGLE_LOADING: 'toggle_loading',
|
|
||||||
SET_SORT_BY: 'set_sort_by',
|
|
||||||
SET_STATUS_FILTER: 'set_status_filter',
|
|
||||||
SET_CHALLENGE_TYPE_FILTER: 'set_challenge_type_filter',
|
|
||||||
SET_COMMERCIAL_FILTER: 'set_commercial_filter',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CHALLENGES_ACTION;
|
|
@ -1,58 +0,0 @@
|
|||||||
import CHALLENGES_ACTION from './ChallengesActionEnum';
|
|
||||||
|
|
||||||
const ChallengesReducer = (state, action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case CHALLENGES_ACTION.NEXT_PAGE:
|
|
||||||
return { ...state, pageNr: state.pageNr + 1 };
|
|
||||||
case CHALLENGES_ACTION.PREVIOUS_PAGE:
|
|
||||||
return { ...state, pageNr: state.pageNr - 1 };
|
|
||||||
case CHALLENGES_ACTION.SET_PAGE:
|
|
||||||
return { ...state, pageNr: action.payload };
|
|
||||||
case CHALLENGES_ACTION.LOAD_CHALLENGES_FROM_API:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
challengesFromAPI: action.payload,
|
|
||||||
challenges: action.payload,
|
|
||||||
challengesFiltered: action.payload,
|
|
||||||
loading: !state.loading,
|
|
||||||
};
|
|
||||||
case CHALLENGES_ACTION.SET_CHALLENGES:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
challenges: action.payload,
|
|
||||||
};
|
|
||||||
case CHALLENGES_ACTION.SET_CHALLENGES_FILTERED:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
challengesFiltered: action.payload,
|
|
||||||
};
|
|
||||||
case CHALLENGES_ACTION.TOGGLE_FILTERS_MENU:
|
|
||||||
return { ...state, filtersMenu: !state.filtersMenu };
|
|
||||||
case CHALLENGES_ACTION.TOGGLE_LOADING:
|
|
||||||
return { ...state, loading: !state.loading };
|
|
||||||
case CHALLENGES_ACTION.SET_SORT_BY:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
sortBy: action.payload,
|
|
||||||
};
|
|
||||||
case CHALLENGES_ACTION.SET_STATUS_FILTER:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
statusFilter: action.payload,
|
|
||||||
};
|
|
||||||
case CHALLENGES_ACTION.SET_CHALLENGE_TYPE_FILTER:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
challengeTypeFilter: action.payload,
|
|
||||||
};
|
|
||||||
case CHALLENGES_ACTION.SET_COMMERCIAL_FILTER:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
commercialFilter: action.payload,
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
throw new Error('Undefined action in ChallengesReducer!');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ChallengesReducer;
|
|
@ -1,6 +1,6 @@
|
|||||||
import { ELEMENTS_PER_PAGE } from '../../../utils/globals';
|
import { ELEMENTS_PER_PAGE } from '../../utils/globals';
|
||||||
import MiniChallenge from '../../../components/challenges_list/MiniChallenge';
|
import MiniChallenge from '../../components/challenges_list/MiniChallenge';
|
||||||
import { Grid } from '../../../utils/containers';
|
import { Grid } from '../../utils/containers';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const ChallengesGrid = styled(Grid)`
|
const ChallengesGrid = styled(Grid)`
|
||||||
@ -18,7 +18,7 @@ const ChallengesGrid = styled(Grid)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const renderChallenges = (pageNr, challenges) => {
|
const renderChallenges = (pageNr, challenges, statusFilter) => {
|
||||||
const n = (pageNr - 1) * ELEMENTS_PER_PAGE;
|
const n = (pageNr - 1) * ELEMENTS_PER_PAGE;
|
||||||
if (challenges && challenges !== []) {
|
if (challenges && challenges !== []) {
|
||||||
return (
|
return (
|
@ -1,7 +1,8 @@
|
|||||||
import { CHALLENGES_STATUS_FILTER } from '../../../utils/globals';
|
import { CHALLENGES_STATUS_FILTER } from '../../utils/globals';
|
||||||
import CHALLENGES_ACTION from '../model/ChallengesActionEnum';
|
|
||||||
|
|
||||||
const dateIsOlder = (newerDate, olderDate) => {
|
const dateIsOlder = (newerDate, olderDate) => {
|
||||||
|
console.log(newerDate);
|
||||||
|
console.log(olderDate);
|
||||||
if (newerDate.year > olderDate.year) return true;
|
if (newerDate.year > olderDate.year) return true;
|
||||||
else if (newerDate.month > olderDate.month) return true;
|
else if (newerDate.month > olderDate.month) return true;
|
||||||
else if (newerDate.day > olderDate.day) return true;
|
else if (newerDate.day > olderDate.day) return true;
|
||||||
@ -18,7 +19,7 @@ const getDeadlineTime = (deadline) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const statusFilterHandle = (status, challenges, dispatch) => {
|
const statusFilter = (status, challenges, setChallengesFiltered) => {
|
||||||
let result = challenges;
|
let result = challenges;
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const currentDate = {
|
const currentDate = {
|
||||||
@ -48,10 +49,7 @@ const statusFilterHandle = (status, challenges, dispatch) => {
|
|||||||
result = challenges;
|
result = challenges;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dispatch({
|
setChallengesFiltered(result);
|
||||||
type: CHALLENGES_ACTION.SET_CHALLENGES_FILTERED,
|
|
||||||
payload: result,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default statusFilterHandle;
|
export default statusFilter;
|
@ -92,17 +92,18 @@ const RENDER_DEADLINE_TIME = (time) => {
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
const NEXT_PAGE = (elements, pageNr, setPage) => {
|
const NEXT_PAGE = (elements, pageNr, setPageNr) => {
|
||||||
if (pageNr !== CALC_PAGES(elements ? elements : [])) {
|
if (pageNr !== CALC_PAGES(elements ? elements : [])) {
|
||||||
let newPage = pageNr + 1;
|
let newPage = pageNr + 1;
|
||||||
setPage(newPage);
|
setPageNr(newPage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PREVIOUS_PAGE = (pageNr, setPage) => {
|
|
||||||
|
const PREVIOUS_PAGE = (pageNr, setPageNr) => {
|
||||||
if (pageNr !== 1) {
|
if (pageNr !== 1) {
|
||||||
let newPage = pageNr - 1;
|
let newPage = pageNr - 1;
|
||||||
setPage(newPage);
|
setPageNr(newPage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -141,5 +142,5 @@ export {
|
|||||||
RENDER_WHEN,
|
RENDER_WHEN,
|
||||||
EVALUATIONS_FORMAT,
|
EVALUATIONS_FORMAT,
|
||||||
PREVIOUS_PAGE,
|
PREVIOUS_PAGE,
|
||||||
NEXT_PAGE,
|
NEXT_PAGE
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user