aboutsummaryrefslogtreecommitdiff
path: root/src/pages
diff options
context:
space:
mode:
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/Contribute/Contribute.tsx149
-rw-r--r--src/pages/Profile/Profile.tsx95
-rw-r--r--src/pages/Profile/Registration.tsx85
-rw-r--r--src/pages/Scoreboard/Scoreboard.tsx70
-rw-r--r--src/pages/Timer/Timer.tsx102
-rw-r--r--src/pages/Timer/TimerButton.tsx130
6 files changed, 0 insertions, 631 deletions
diff --git a/src/pages/Contribute/Contribute.tsx b/src/pages/Contribute/Contribute.tsx
deleted file mode 100644
index 67f2b8a..0000000
--- a/src/pages/Contribute/Contribute.tsx
+++ /dev/null
@@ -1,149 +0,0 @@
-import React from 'react';
-
-import {
- Typography,
- Button,
- List,
- ListItem,
- Link,
- Divider,
- makeStyles,
-} from '@material-ui/core';
-
-import TrendingUpIcon from '@material-ui/icons/TrendingUp';
-import BugReportIcon from '@material-ui/icons/BugReport';
-import NewReleasesIcon from '@material-ui/icons/NewReleases';
-
-import { Window, ContentSection } from 'react-benzin';
-import GithubAvatar, { getUserGithubUrl } from '../../components/GithubAvatar/GithubAvatar';
-
-import developers from '../../developers.json';
-
-const useStyles = makeStyles(theme => ({
- mono: {
- padding: theme.spacing(4),
-
- '& .MuiAvatar-root': {
- marginRight: theme.spacing(2),
- width: theme.spacing(6),
- height: theme.spacing(6),
- }
- },
-}));
-
-
-
-
-const Contribute: React.FC = () => {
- const classes = useStyles();
-
- return (
- <Window type="mono">
- <div className={classes.mono}>
- <ContentSection sectionName="Thank You for using ChronoCube!">
- <p>
- ChronoCube is an Open-Source application, and we welcome anyone who desires to help our project!
- </p>
- <Button
- variant="contained"
- color="primary"
- startIcon={<TrendingUpIcon />}
- href="https://github.com/users/Eug-VS/projects/3"
- >
- Track our progress
- </Button>
- </ContentSection>
- <ContentSection sectionName="Technology stack">
- <p> We only use modern and most relevant technologies to achieve the best results! </p>
- <ul>
- <li><Link href="https://www.django-rest-framework.org/">
- Django REST Framework
- </Link></li>
- <li><Link href="https://reactjs.org/">
- React.js
- </Link></li>
- <li><Link href="https://material-ui.com/">
- Material UI components
- </Link></li>
- </ul>
- <p> Special thanks to other Open-Source projects which made ChronoCube possible: </p>
- <ul>
- <li><Link href="https://github.com/bvaughn/react-window">
- react-window
- </Link></li>
- </ul>
- </ContentSection>
- <ContentSection sectionName="How can I contribute to the project?">
- <p> Thank You for considering helping our project! </p>
- <p>
- All the development process is being tracked on
- the <Link href="https://github.com/users/Eug-VS/projects/3">KanBan board</Link>.
- You can always check it to see what is the current state of the project.
- To contribute your code, fork our repository and then open
- a <Link href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests">
- Pull Request</Link>. We will carefully review and, hopefully, accept it!
- If you are unfamiliar with this kind of workflow, we recommend
- reading <Link href="https://github.com/features/project-management/">GitHub guidelines</Link>.
- </p>
- <p>
- We always welcome newcomers! If you are unfamiliar with certain technologies or even with the
- development in general, it is great time to start learning something new!
- Our community will kindly assist every your step, and with us you can easily become
- highly-evaluated developer!
- </p>
- <Button
- variant="contained"
- color="primary"
- startIcon={<NewReleasesIcon />}
- href="https://github.com/Eug-VS/chrono-cube/issues/new"
- >
- Suggest feature
- </Button>
- <Button
- variant="contained"
- color="primary"
- startIcon={<BugReportIcon />}
- href="https://github.com/Eug-VS/chrono-cube/issues/new"
- >
- Report a bug
- </Button>
- </ContentSection>
- <ContentSection sectionName="Developers">
- <List>
- {
- developers.map(developer => (
- <div key={developer.username}>
- <ListItem>
- <GithubAvatar username={developer.username} />
- <div>
- <Link href={getUserGithubUrl(developer.username)}>{developer.username}</Link>
- <Typography component="div" color="textSecondary">
- {developer.role}
- </Typography>
- </div>
- </ListItem>
- <Divider variant="middle" />
- </div>
- ))
- }
- <ListItem>
- <GithubAvatar username="anonymous" />
- You can be here!
- </ListItem>
- </List>
- <Button
- variant="contained"
- color="primary"
- size="large"
- href="https://github.com/users/Eug-VS/projects/3"
- >
- Join us!
- </Button>
- </ContentSection>
- </div>
- </Window>
- );
-};
-
-
-export default Contribute;
diff --git a/src/pages/Profile/Profile.tsx b/src/pages/Profile/Profile.tsx
deleted file mode 100644
index 83acb30..0000000
--- a/src/pages/Profile/Profile.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import React, { useState, useEffect } from 'react';
-
-import {
- Button,
- makeStyles,
-} from '@material-ui/core';
-
-import Registration from './Registration';
-import {
- Window,
- ContentSection,
- SmartList,
-} from 'react-benzin';
-import { User, Solution, RenderPropTypes } from '../../types';
-
-import SolutionCard from '../../components/SolutionCard/SolutionCard';
-
-import { get } from '../../requests';
-
-
-const useStyles = makeStyles(theme => ({
- primary: {
- padding: theme.spacing(4),
- },
- cell: {
- padding: theme.spacing(5),
- },
-}));
-
-
-interface PropTypes {
- user: User;
- setUser: (user: User) => void;
-}
-
-
-const Profile: React.FC<PropTypes> = ({ user, setUser }) => {
- const classes = useStyles();
-
- const [profileSolutions, setProfileSolutions] = useState<Solution[]>([]);
-
- const handleLogout = (): void => {
- setUser({ username: 'anonymous', id: null });
- localStorage.clear();
- };
-
- useEffect(() => {
- get(`solutions/?author=${user.id}`).then(response => {
- setProfileSolutions(response.data.reverse());
- });
- }, [user]);
-
- const removeSolution = (id: number): void => {
- setProfileSolutions(profileSolutions.filter((solution => solution.id !== id)));
- };
-
- const renderItem: React.FC<RenderPropTypes> = ({ index, style }) => {
- return (
- <div style={style} className={classes.cell}>
- <SolutionCard data={profileSolutions[index]} removeThisCard={removeSolution} />
- </div>
- );
- };
-
- return (
- <>
- <Window type="primary">
- <div className={classes.primary}>
- { user.id? (
- <ContentSection sectionName={`Welcome back, ${user.username}!`}>
- <p> Total amount of solutions: {profileSolutions.length} </p>
- <p> You can always log out from your account! </p>
- <Button variant="contained" color="secondary" onClick={handleLogout}>
- Logout
- </Button>
- </ContentSection>
- ): (
- <Registration setUser={setUser} />
- )
- }
- </div>
- </Window>
- <Window type="secondary" name="History">
- <SmartList
- itemSize={270}
- itemCount={profileSolutions.length}
- renderItem={renderItem}
- />
- </Window>
- </>
- )
-};
-
-
-export default Profile;
diff --git a/src/pages/Profile/Registration.tsx b/src/pages/Profile/Registration.tsx
deleted file mode 100644
index a5e0f3e..0000000
--- a/src/pages/Profile/Registration.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import React, {useState} from 'react';
-
-import {
- TextField,
- Button,
- Checkbox,
- FormControlLabel,
- Grid,
-} from '@material-ui/core';
-import { User } from '../../types';
-
-import { ContentSection } from 'react-benzin';
-import { get, post } from '../../requests';
-
-
-interface PropTypes {
- setUser: (user: User) => void;
-}
-
-const Registration: React.FC<PropTypes> = ({ setUser }) => {
-
- const [username, setUsername] = useState<string>('');
- const [isRememberMe, setIsRememberMe] = useState<boolean>(false);
-
- const handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
- setUsername(event.target.value);
- };
-
- const handleCheck = (event: React.ChangeEvent<HTMLInputElement>): void => {
- setIsRememberMe(event.target.checked);
- };
-
- const handleSubmit = (): void => {
- if (username !== '') {
- post('users/', { username })
- .then(response => {
- const user = response.data;
- setUser(user);
- if (isRememberMe) {
- localStorage.setItem('userId', user.id);
- }
- })
- .catch(err => {
- get('users/').then(response => {
- const user = response.data.filter((user: User) => user.username === username)[0];
- setUser(user);
- if (isRememberMe) {
- localStorage.setItem('userId', user.id);
- }
- });
- });
- }
- };
-
- return (
- <ContentSection sectionName="Tell us who you are">
- <p> Choose yourself a username to track your progress and compete with others: </p>
- <Grid container direction="column">
- <Grid item>
- <TextField
- variant="outlined"
- color="secondary"
- label="Username"
- value={username}
- onChange={handleChange}
- />
- </Grid>
- <Grid item>
- <FormControlLabel
- control={<Checkbox color="secondary" onChange={handleCheck} />}
- label="Remember me"
- />
- </Grid>
- <Grid item>
- <Button variant="contained" color="secondary" onClick={handleSubmit}>
- Submit!
- </Button>
- </Grid>
- </Grid>
- </ContentSection>
- );
-};
-
-
-export default Registration;
diff --git a/src/pages/Scoreboard/Scoreboard.tsx b/src/pages/Scoreboard/Scoreboard.tsx
deleted file mode 100644
index e4185bd..0000000
--- a/src/pages/Scoreboard/Scoreboard.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import React, { useEffect, useState } from 'react';
-
-import { makeStyles } from '@material-ui/core/styles';
-
-import { Window, SmartList } from 'react-benzin';
-import { Solution, RenderPropTypes } from '../../types';
-
-import SolutionCard from '../../components/SolutionCard/SolutionCard';
-import Loading from '../../components/Loading/Loading';
-
-import { get } from '../../requests';
-
-
-const useStyles = makeStyles(theme => ({
- cell: {
- display: 'flex',
- justifyContent: 'center',
- padding: theme.spacing(4),
-
- '& .MuiCard-root': {
- width: '30%',
- }
- }
-}));
-
-
-const Scoreboard: React.FC = () => {
- const classes = useStyles();
- const [solutions, setSolutions] = useState<Solution[]>([]);
-
- const updateSolutions = (): void => {
- get('scoreboard/').then(response => {
- setSolutions(response.data);
- });
- };
-
- const removeSolution = (id: number): void => {
- updateSolutions();
- };
-
- useEffect(() => {
- setTimeout(updateSolutions, 300);
- }, []);
-
- const renderItem: React.FC<RenderPropTypes> = ({ index, style }) => {
- return (
- <div style={style} className={classes.cell}>
- <SolutionCard data={solutions[index]} removeThisCard={removeSolution}/>
- </div>
- )
- };
-
- return (
- <Window type="mono">
- { solutions.length === 0 &&
- <div className={classes.cell}>
- <Loading/>
- </div>
- }
- <SmartList
- itemSize={300}
- itemCount={solutions.length}
- renderItem={renderItem}
- />
- </Window>
- )
-};
-
-
-export default Scoreboard;
diff --git a/src/pages/Timer/Timer.tsx b/src/pages/Timer/Timer.tsx
deleted file mode 100644
index a890815..0000000
--- a/src/pages/Timer/Timer.tsx
+++ /dev/null
@@ -1,102 +0,0 @@
-import React from 'react';
-
-import { post } from '../../requests';
-
-import {
- Window,
- ContentSection,
- SmartList,
-} from 'react-benzin';
-import { User, Solution, RenderPropTypes } from '../../types';
-
-import TimerButton from './TimerButton';
-import SolutionCard from '../../components/SolutionCard/SolutionCard';
-
-import { Button, makeStyles } from '@material-ui/core';
-
-
-const useStyles = makeStyles(theme => ({
- primary: {
- padding: theme.spacing(4),
- },
- cell: {
- padding: theme.spacing(5),
- },
-}));
-
-
-interface PropTypes {
- user: User;
- recentSolutions: Solution[];
- setRecentSolutions: (newRecentSolutions: Solution[]) => void;
- setPage: (newPage: string) => void;
-}
-
-
-const Timer: React.FC<PropTypes> = ({ user, recentSolutions, setRecentSolutions, setPage }) => {
- const classes = useStyles();
-
- const registerResult = (result: string): void => {
- const solution = { 'author_id': user.id, result };
- post('solutions/', solution).then(response => {
- setRecentSolutions([response.data].concat(recentSolutions));
- });
- };
-
- const handleLearnMore = (): void => {
- setPage('contribute');
- };
-
- const handleLogin = (): void => {
- setPage('profile');
- };
-
- const removeSolution = (id: number): void => {
- setRecentSolutions(recentSolutions.filter((solution => solution.id !== id)));
- };
-
- const renderItem: React.FC<RenderPropTypes> = ({ 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!">
- <p>
- ChronoCube is a professional speedcubing timer.
- Share your results publicly - let everyone see your progress and
- achievements!
- Every speedcuber will benefit
- from using it - both amateur and professional!
- </p>
- <Button variant="contained" color="primary" onClick={handleLearnMore}> Learn more </Button>
- </ContentSection>
- {user.id === null &&
- <ContentSection sectionName="Log into an account">
- <p> Tell us your name so we can track your progress</p>
- <Button variant="contained" color="primary" onClick={handleLogin} size="large"> Login </Button>
- </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.tsx b/src/pages/Timer/TimerButton.tsx
deleted file mode 100644
index 0a3bf38..0000000
--- a/src/pages/Timer/TimerButton.tsx
+++ /dev/null
@@ -1,130 +0,0 @@
-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.background.elevation3,
- marginTop: theme.spacing(10),
- },
-}));
-
-
-interface PropTypes {
- registerResult: (result: string) => void;
-}
-
-type Mode = 'idle' | 'countdown' | 'running' | 'over';
-
-
-const TimerButton: React.FC<PropTypes> = ({ registerResult }) => {
- const classes = useStyles();
-
- const SPACE = 32;
- const maxCountdown = 15000;
- const [time, setTime] = useState<string>('00:00:00');
- const [mode, setMode] = useState<Mode>('idle');
-
- useEffect(()=> {
- const timestamp = Date.now();
-
- if (mode === 'countdown') {
- const repeater = setInterval(() => {
- const timeDelta = maxCountdown - (Date.now() - timestamp);
- if (timeDelta <= 0) setMode('over');
- setTime(convertTimeToString(timeDelta));
- }, 10);
- return (): void => clearInterval(repeater);
- }
-
- if (mode === 'running') {
- const repeater = setInterval(() => {
- setTime(convertTimeToString(Date.now() - timestamp));
- }, 10);
- return (): void => clearInterval(repeater);
- }
-
- if (mode === 'over') {
- setTime('00:00:00');
- }
- }, [mode]);
-
- const handleKeyPress = (event: KeyboardEvent): void => {
- event.preventDefault();
- if (event.keyCode === SPACE && mode === 'idle' ) setMode('countdown');
- };
-
- const handleKeyUp = (event: KeyboardEvent): void => {
- 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 (): void => {
- window.removeEventListener('keyup', handleKeyUp);
- window.removeEventListener('keypress', handleKeyPress);
- };
- });
-
- const composeHelperText = (): string => {
- switch (mode) {
- case 'running': return 'Go fast!';
- case 'countdown': return 'Release SPACE to begin';
- case 'over': return 'You are too late!';
- default: return 'Hold SPACE to start countdown';
- }
- };
-
- const helperColor = (): 'primary' | 'secondary' | 'textSecondary' => {
- switch (mode) {
- case 'running': return 'primary';
- case 'over': return 'secondary';
- default: return 'textSecondary';
- }
- };
-
- return (
- <Paper className={classes.root}>
- <Typography variant="h1"> {time} </Typography>
- <Typography variant="h5" color={helperColor()}>
- {composeHelperText()}
- </Typography>
- </Paper>
- );
-};
-
-const convertTimeToString = (timeDelta: number): string => {
- let resultTime = '';
-
- const minute = Math.floor(timeDelta / 60000);
- if (minute < 10) resultTime += '0';
- resultTime += minute + ':';
-
- let second = Math.floor(timeDelta / 1000);
- if (second > 59) second %= 60;
- if (second < 10) resultTime += '0';
- resultTime += second + ':';
-
- const mill = Math.floor((timeDelta % 1000) / 10);
- if (mill < 10) resultTime += '0';
- resultTime += mill;
-
- return resultTime;
-};
-
-
-export default TimerButton;