diff options
| author | Eug-VS <eug-vs@keemail.me> | 2020-01-11 17:56:38 +0300 | 
|---|---|---|
| committer | Eug-VS <eug-vs@keemail.me> | 2020-01-11 17:58:19 +0300 | 
| commit | b2fe1b816044b8630f570c04c884c8ffcf3e3e61 (patch) | |
| tree | d2a33cea442a05e626fc74e05f29b8e3c7f94bdc /src/pages/Timer | |
| parent | d517398707f74c670d47ed0a277ba328e531579e (diff) | |
| download | chrono-cube-ui-b2fe1b816044b8630f570c04c884c8ffcf3e3e61.tar.gz | |
Improve names, getPageComponent() -->  <Page />
Remove 'Page' word from page-components, since they are all
now located in the pages/ folder.
Diffstat (limited to 'src/pages/Timer')
| -rw-r--r-- | src/pages/Timer/Timer.js | 76 | ||||
| -rw-r--r-- | src/pages/Timer/TimerButton/TimerButton.js | 119 | 
2 files changed, 195 insertions, 0 deletions
diff --git a/src/pages/Timer/Timer.js b/src/pages/Timer/Timer.js new file mode 100644 index 0000000..4b5925f --- /dev/null +++ b/src/pages/Timer/Timer.js @@ -0,0 +1,76 @@ +import React from 'react'; + +import { post } from '../../requests'; + +import Window from "../../components/Window/Window"; +import ContentSection from "../../components/ContentSection/ContentSection"; +import TimerButton from "./TimerButton/TimerButton"; +import SmartList from "../../components/SmartList/SmartList"; +import SolutionCard from "../../components/SolutionCard/SolutionCard"; + +import { Typography, makeStyles } from "@material-ui/core"; + + +const useStyles = makeStyles(theme => ({ +  primary: { +    padding: theme.spacing(4), +  }, +  cell: { +    padding: theme.spacing(5), +  }, +})); + +const Timer = ({ recentSolutions, setRecentSolutions }) => { +  const classes = useStyles(); + +  const user = { +    id: null, +    username: 'anonymous', +  }; + +  const registerResult = result => { +    const solution = { author_id: user.id, result }; +    post('solutions/', solution).then(response => { +      setRecentSolutions([response.data].concat(recentSolutions)); +    }); +  }; + +  const removeSolution = (id) => { +    setRecentSolutions(recentSolutions.filter((solution => solution.id !== id))); +  }; + +  const renderItem = ({ index, style }) => { +    const solution = recentSolutions[index]; +    return ( +      <div style={style} className={classes.cell}> +        <SolutionCard data={solution} removeThisCard={removeSolution} /> +      </div> +    ); +  }; + +  return ( +    <> +      <Window type="primary"> +        <div className={classes.primary}> +          <ContentSection sectionName="Welcome to ChronoCube!"> +            <Typography> +              Here is some text about how cool this application is, why you should use it +              and how to make it better! +            </Typography> +          </ContentSection> +          <TimerButton registerResult={registerResult} /> +        </div> +      </Window> +      <Window type="secondary" name="Recent solutions"> +        <SmartList +          itemSize={270} +          itemCount={recentSolutions.length} +          renderItem={renderItem} +        /> +      </Window> +    </> +  ); +}; + + +export default Timer; diff --git a/src/pages/Timer/TimerButton/TimerButton.js b/src/pages/Timer/TimerButton/TimerButton.js new file mode 100644 index 0000000..56d3084 --- /dev/null +++ b/src/pages/Timer/TimerButton/TimerButton.js @@ -0,0 +1,119 @@ +import React, { useState, useEffect } from 'react'; + +import { Paper, Typography } from '@material-ui/core'; +import { makeStyles } from "@material-ui/core/styles"; + +const useStyles = makeStyles(theme => ({ +  root: { +    textAlign: 'center', +    padding: theme.spacing(5), +    background: theme.palette.primary.main, +    marginTop: theme.spacing(20), +  }, +})); + +const TimerButton = ({ registerResult }) => { +  const classes = useStyles(); + +  const SPACE = 32; +  const maxCountdown = 15000; +  const [time, setTime] = useState('00:00:00'); +  const [mode, setMode] = useState('idle'); +  const [repeater, setRepeater] = useState(0); + +  useEffect(()=> { +    clearInterval(repeater); +    const timestamp = Date.now(); + +    if (mode === 'countdown') setRepeater(setInterval(() => { +      const timeDelta = maxCountdown - (Date.now() - timestamp); +      if (timeDelta <= 0) setMode('over'); +      setTime(convertTimeToString(timeDelta)); +    }, 10)); + +    if (mode === 'running') setRepeater(setInterval(() => { +      setTime(convertTimeToString(Date.now() - timestamp)); +    }, 10)); + +    if (mode === 'over') { +      setTime('00:00:00'); +    } +  }, [mode]); + +  const handleKeyPress = event => { +    event.preventDefault(); +    if (event.keyCode === SPACE && mode === 'idle' ) setMode('countdown'); +  }; + +  const handleKeyUp = event => { +    clearInterval(repeater); +    if (event.keyCode === SPACE) { +      if (mode === 'running') { +        registerResult(time); +        setMode('idle'); +      } else if (mode === 'over') { +        setMode('idle'); +      } else { +        setMode('running'); +      } +    } +  }; + +  useEffect(() => { +    window.addEventListener('keyup', handleKeyUp); +    window.addEventListener('keypress', handleKeyPress); + +    return () => { +      window.removeEventListener('keyup', handleKeyUp); +      window.removeEventListener('keypress', handleKeyPress); +    }; +  }); + +  const composeHelperText = () => { +    switch (mode) { +      case 'running': return '_'; +      case 'countdown': return 'Release SPACE to begin'; +      case 'over': return 'You are too late!'; +      default: return 'Hold SPACE to start countdown'; +    } +  }; + +  const helperColor = () => { +    switch (mode) { +      case 'running': return 'primary'; +      case 'over': return 'secondary'; +      default: return 'textSecondary'; +    } +  }; + +  return ( +    <Paper elevation={3} className={classes.root}> +      <Typography variant="h1"> {time} </Typography> +      <Typography variant="h5" color={helperColor()}> +        {composeHelperText()} +      </Typography> +    </Paper> +  ); +}; + +const convertTimeToString = timeDelta => { +  let resultTime = ''; + +  const minute = Math.floor(timeDelta / 60000); +  if (minute < 10) resultTime += '0'; +  resultTime += minute + ':'; + +  let second = Math.floor(timeDelta / 1000); +  if (second < 10) resultTime += '0'; +  if (second > 59) second %= 60; +  resultTime += second + ':'; + +  const mill = Math.floor((timeDelta % 1000) / 10); +  if (mill < 10) resultTime += '0'; +  resultTime += mill; + +  return resultTime; +}; + + +export default TimerButton;  |