diff --git a/src/api/getChallengeFullDescription.js b/src/api/getChallengeFullDescription.js index 4463790..badb32f 100644 --- a/src/api/getChallengeFullDescription.js +++ b/src/api/getChallengeFullDescription.js @@ -1,10 +1,12 @@ import {API} from "../utils/globals"; -const getChallengeFullDescription = (setState, challengeName) => { +const getChallengeFullDescription = (setDataState, setLoading, challengeName) => { fetch(`${API}/challenge-readme/${challengeName}/markdown`) .then(response => response.text()) .then(data => { - setState(data); + setDataState(data); + if (setLoading) + setLoading(false); }); } diff --git a/src/api/getChallengeInfo.js b/src/api/getChallengeInfo.js index be39e74..3a8c327 100644 --- a/src/api/getChallengeInfo.js +++ b/src/api/getChallengeInfo.js @@ -1,10 +1,12 @@ import {API} from "../utils/globals"; -const getChallengeInfo = (setState, challengeName) => { +const getChallengeInfo = (setDataState, setLoadingState, challengeName) => { fetch(`${API}/challenge-info/${challengeName}`) .then(response => response.json()) .then(data => { - setState(data); + setDataState(data); + if (setLoadingState) + setLoadingState(false); }); } diff --git a/src/api/getChallengeSubmissions.js b/src/api/getChallengeSubmissions.js index 4a27c89..8f682cf 100644 --- a/src/api/getChallengeSubmissions.js +++ b/src/api/getChallengeSubmissions.js @@ -1,10 +1,12 @@ import {API} from "../utils/globals"; -const getChallengeSubmissions = (setState, challengeName) => { +const getChallengeSubmissions = (setDataState, setLoading, challengeName) => { fetch(`${API}/challenge-all-submissions/${challengeName}`) .then(response => response.json()) .then(data => { - setState(data); + setDataState(data); + if (setLoading) + setLoading(false); }); } diff --git a/src/api/getChallenges.js b/src/api/getChallenges.js index 27c38f1..f25df7a 100644 --- a/src/api/getChallenges.js +++ b/src/api/getChallenges.js @@ -1,10 +1,12 @@ import {API} from "../utils/globals"; -const getChallenges = (setState) => { +const getChallenges = (setDataState, setLoadingState) => { fetch(`${API}/list-challenges`) .then(response => response.json()) .then(data => { - setState(data); + setDataState(data); + if (setLoadingState) + setLoadingState(false); }); } diff --git a/src/components/elements/Loading.js b/src/components/elements/Loading.js new file mode 100644 index 0000000..76c2c21 --- /dev/null +++ b/src/components/elements/Loading.js @@ -0,0 +1,50 @@ +import React from "react"; +import styled, {keyframes} from "styled-components"; +import {Container} from "../../utils/containers"; + +const rotate = keyframes` + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +`; + +const SpinnerContainer = styled(Container)` + display: grid; + justify-content: center; + align-items: center; + height: 200px; + + @media (min-width: ${({theme}) => theme.overMobile}) { + height: 350px; + } +`; + +const LoadingSpinner = styled(Container)` + width: 50px; + height: 50px; + border: 10px solid ${({theme}) => theme.colors.dark01}; /* Light grey */ + border-top: 10px solid ${({theme}) => theme.colors.green}; /* Black */ + border-radius: 50%; + animation: ${rotate} 1.1s ease-in-out infinite; + + @media (min-width: ${({theme}) => theme.overMobile}) { + width: 100px; + height: 100px; + } +`; + +const Loading = (props) => { + return ( + <> + {props.visible ? + + : ''} + + ); +} + +export default Loading; \ No newline at end of file diff --git a/src/components/elements/Pager.js b/src/components/elements/Pager.js index 164afc6..3257f54 100644 --- a/src/components/elements/Pager.js +++ b/src/components/elements/Pager.js @@ -49,15 +49,18 @@ const RightArrow = styled(Svg)` `; const Pager = (props) => { - return ( - - - - - - ); + if (props.visible) { + return ( + + + + + + ); + } + return ''; } export default Pager; \ No newline at end of file diff --git a/src/components/elements/Table/Table.js b/src/components/elements/Table/Table.js index e3664d7..dea8997 100644 --- a/src/components/elements/Table/Table.js +++ b/src/components/elements/Table/Table.js @@ -7,18 +7,20 @@ import Pager from "../Pager"; import {CALC_PAGES} from "../../../utils/globals"; import Media from "react-media"; import theme from "../../../utils/theme"; +import Loading from "../Loading"; const Table = (props) => { const headerElements = ['#', 'submitter', 'when', 'result', 'entries']; const [challengeData, setChallengeData] = React.useState({}); const [pageNr, setPageNr] = React.useState(1); + const [loading, setLoading] = React.useState(true); React.useEffect(() => { challengeDataRequest(); }); const challengeDataRequest = () => { - getChallengeSubmissions(setChallengeData, props.challengeName); + getChallengeSubmissions(setChallengeData, setLoading, props.challengeName); } const renderSubmissions = () => { @@ -54,6 +56,7 @@ const Table = (props) => { ) })} + {renderSubmissions()} @@ -74,6 +77,7 @@ const Table = (props) => { ) })} + {renderSubmissions()} ); @@ -87,7 +91,7 @@ const Table = (props) => { {desktopRender()} - ); diff --git a/src/components/sections/Readme.js b/src/components/sections/Readme.js index da2f46d..1648688 100644 --- a/src/components/sections/Readme.js +++ b/src/components/sections/Readme.js @@ -7,6 +7,7 @@ import getChallengeFullDescription from "../../api/getChallengeFullDescription"; import {markdown} from "markdown"; import styled from "styled-components"; import InfoList from "../elements/InfoList"; +import Loading from "../elements/Loading"; const ReadmeStyle = styled(Body)` h3 { @@ -52,9 +53,10 @@ const ReadmeStyle = styled(Body)` const Readme = (props) => { const [fullDescription, setFullDescription] = React.useState(''); + const [loading, setLoading] = React.useState(true); React.useEffect(() => { - getChallengeFullDescription(setFullDescription, props.challengeName); + getChallengeFullDescription(setFullDescription, setLoading, props.challengeName); }, [props.challengeName]); const parseMarkdownResponse = (response) => { @@ -148,10 +150,10 @@ const Readme = (props) => { return ( <> - {mobileRender()} + {!loading ? mobileRender() : } - {desktopRender()} + {!loading ? desktopRender() : } ); diff --git a/src/pages/Challanges/Challenges.js b/src/pages/Challanges/Challenges.js index b892b42..8014ccf 100644 --- a/src/pages/Challanges/Challenges.js +++ b/src/pages/Challanges/Challenges.js @@ -11,6 +11,7 @@ import theme from "../../utils/theme"; import cupIco from '../../assets/cup_ico.svg'; import getChallenges from "../../api/getChallenges"; import {CALC_PAGES} from "../../utils/globals"; +import Loading from "../../components/elements/Loading"; const Challenges = () => { const [pageNr, setPageNr] = React.useState(1); @@ -21,6 +22,7 @@ const Challenges = () => { const [status, setStatus] = React.useState(0); const [challengeType, setChallengeType] = React.useState(0); const [commercial, setCommercial] = React.useState(0); + const [loading, setLoading] = React.useState(true); React.useEffect(() => { challengesRequest(); @@ -28,7 +30,7 @@ const Challenges = () => { const challengesRequest = () => { getChallenges(setChallengesFromAPI); - getChallenges(setChallenges); + getChallenges(setChallenges, setLoading); } const sortByHandler = (value) => { @@ -90,10 +92,11 @@ const Challenges = () => { + {renderChallenges()} - @@ -124,10 +127,11 @@ const Challenges = () => { height='160px' backgroundColor={theme.colors.green}/> + {renderChallenges()} - diff --git a/src/pages/Challanges/_renderChallenges.js b/src/pages/Challanges/_renderChallenges.js index ba9801a..976fc59 100644 --- a/src/pages/Challanges/_renderChallenges.js +++ b/src/pages/Challanges/_renderChallenges.js @@ -20,19 +20,22 @@ const ChallengesGrid = styled(Grid)` const _renderChallenges = (pageNr, challenges) => { const n = (pageNr - 1) * ELEMENTS_PER_PAGE; - return ( - - {challenges.slice(n, n + ELEMENTS_PER_PAGE).map((challenge, index) => { - return ( - - ); - })} - - ) + if (challenges && challenges !== []) { + return ( + + {challenges.slice(n, n + ELEMENTS_PER_PAGE).map((challenge, index) => { + return ( + + ); + })} + + ) + } + return ''; } export default _renderChallenges; \ No newline at end of file diff --git a/src/pages/Challenge.js b/src/pages/Challenge.js index eb94869..3d3f3c5 100644 --- a/src/pages/Challenge.js +++ b/src/pages/Challenge.js @@ -14,14 +14,16 @@ import DesktopChallengeMenu from "../components/elements/DesktopChallengeMenu"; import {RENDER_ICO} from "../utils/globals"; import textIco from "../assets/text_ico.svg"; import getChallengeInfo from "../api/getChallengeInfo"; +import Loading from "../components/elements/Loading"; const Challenge = () => { const challengeName = useParams().challengeId; const [challenge, setChallenge] = React.useState([]); const [section, setSection] = React.useState(0); + const [loading, setLoading] = React.useState(true); React.useEffect(() => { - getChallengeInfo(setChallenge, challengeName); + getChallengeInfo(setChallenge, setLoading, challengeName); }, [challengeName]); const sectionRender = () => { @@ -45,6 +47,7 @@ const Challenge = () => { const mobileRender = () => { return ( +

{challenge.title}

@@ -61,6 +64,7 @@ const Challenge = () => { +

{challenge.title} diff --git a/src/utils/colors.js b/src/utils/colors.js index dbff457..5b632a8 100644 --- a/src/utils/colors.js +++ b/src/utils/colors.js @@ -4,6 +4,7 @@ const colors = { green03: 'rgba(27, 153, 139, 0.3)', green05: 'rgba(27, 153, 139, 0.5)', dark: '#343434', + dark01: 'rgba(52, 52, 52, 0.1)', dark03: 'rgba(52, 52, 52, 0.3)', dark04: 'rgba(52, 52, 52, 0.4)', dark05: 'rgba(52, 52, 52, 0.5)',