aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2022-05-04 12:52:25 +0300
committereug-vs <eugene@eug-vs.xyz>2022-05-04 12:52:25 +0300
commitf35c1cf5480f7506442ac4c9170c5e0a1a4a8b15 (patch)
tree94fa0fa38e8a90df08933c05910bea6bed461291 /src/components
parent8dc803f882f31430abb600fba250fdcf3334d9bf (diff)
downloadchrono-cube-ui-f35c1cf5480f7506442ac4c9170c5e0a1a4a8b15.tar.gz
feat: remove material UI and useless functionality
Diffstat (limited to 'src/components')
-rw-r--r--src/components/GithubAvatar/GithubAvatar.tsx39
-rw-r--r--src/components/Loading/Loading.tsx33
-rw-r--r--src/components/SolutionCard/SolutionCard.tsx117
-rw-r--r--src/components/Timer.tsx90
4 files changed, 90 insertions, 189 deletions
diff --git a/src/components/GithubAvatar/GithubAvatar.tsx b/src/components/GithubAvatar/GithubAvatar.tsx
deleted file mode 100644
index 32ac553..0000000
--- a/src/components/GithubAvatar/GithubAvatar.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react';
-
-import {
- Avatar,
- Link,
-} from '@material-ui/core';
-
-interface PropTypes {
- username: string;
-}
-
-const githubUrl = 'https://github.com/';
-const getUserGithubUrl = (username: string): string => githubUrl + username;
-
-const GithubAvatar: React.FC<PropTypes> = ({ username }) => {
- if (username === 'anonymous') return <Avatar/>;
-
- const userGithubUrl = getUserGithubUrl(username);
- const avatarUrl = userGithubUrl + '.png';
- const usernameTokens = username.split(/[ ,.\-_#@;]/g);
- const altText = (
- (usernameTokens.length > 1)?
- (usernameTokens[0][0] + usernameTokens[1][0])
- :
- usernameTokens[0][0]
- ).toUpperCase()
-
- return (
- <Link href={userGithubUrl}>
- <Avatar>
- <img src={avatarUrl} alt={altText} />
- </Avatar>
- </Link>
- )
-};
-
-export { getUserGithubUrl };
-export default GithubAvatar;
-
diff --git a/src/components/Loading/Loading.tsx b/src/components/Loading/Loading.tsx
deleted file mode 100644
index a784be1..0000000
--- a/src/components/Loading/Loading.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React from 'react';
-
-import {
- Card,
- CardHeader,
-} from '@material-ui/core';
-
-import { makeStyles } from '@material-ui/core/styles';
-import CircularProgress from '@material-ui/core/CircularProgress';
-
-
-const useStyles = makeStyles(theme => ({
- root: {
- padding: theme.spacing(1),
- background: theme.palette.background.elevation2,
- },
-}));
-
-const Loading: React.FC = () => {
- const classes = useStyles();
-
- return (
- <Card className={classes.root}>
- <CardHeader
- avatar={(<CircularProgress color="secondary" />)}
- title="Loading"
- subheader="Please, wait."
- />
- </Card>
- )
-};
-
-export default Loading;
diff --git a/src/components/SolutionCard/SolutionCard.tsx b/src/components/SolutionCard/SolutionCard.tsx
deleted file mode 100644
index 7ec8888..0000000
--- a/src/components/SolutionCard/SolutionCard.tsx
+++ /dev/null
@@ -1,117 +0,0 @@
-import React, { useState } from 'react';
-
-import {
- Typography,
- Card,
- CardHeader,
- CardContent,
- IconButton,
- Grid,
- Menu,
- MenuItem,
-} from '@material-ui/core';
-import { Solution } from '../../types';
-
-import { makeStyles } from '@material-ui/core/styles';
-import TimerIcon from '@material-ui/icons/Timer';
-import MoreVertIcon from '@material-ui/icons/MoreVert';
-import DeleteIcon from '@material-ui/icons/Delete';
-
-import GithubAvatar from '../GithubAvatar/GithubAvatar';
-import { del } from '../../requests';
-
-
-const DATE_FORMAT = {
- month: 'long',
- day: 'numeric',
- year: 'numeric',
- hour: '2-digit',
- minute: '2-digit',
-};
-
-const useStyles = makeStyles(theme => ({
- root: {
- padding: theme.spacing(1),
- background: theme.palette.background.elevation2,
-
- '& .MuiTypography-h3': {
- margin: theme.spacing(2),
- },
- },
- menu: {
- '& ul': {
- background: theme.palette.background.elevation3,
- }
- },
-}));
-
-
-interface PropTypes {
- data: Solution;
- removeThisCard: (id: number) => void;
-}
-
-
-const SolutionCard: React.FC<PropTypes> = ({ data, removeThisCard }) => {
- const classes = useStyles();
- const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
-
- const author = data.author? data.author.username : 'anonymous';
- const date = new Date(data.date);
-
- const handleOpenMenu = (event: React.MouseEvent<HTMLButtonElement>): void => {
- setAnchorEl(event.currentTarget);
- };
-
- const handleClose = (): void => {
- setAnchorEl(null);
- };
-
- const handleDelete = (): void => {
- del(`solutions/${data.id}/`).then(() => {
- removeThisCard(data.id);
- });
- handleClose();
- };
-
- return (
- <Card className={classes.root}>
- <CardHeader
- avatar={<GithubAvatar username={author} />}
- title={author}
- subheader={date.toLocaleString('default', DATE_FORMAT)}
- action={
- <IconButton onClick={handleOpenMenu}>
- <MoreVertIcon />
- </IconButton>
- }
- />
- <Menu
- anchorEl={anchorEl}
- open={Boolean(anchorEl)}
- keepMounted
- onClose={handleClose}
- className={classes.menu}
- >
- <MenuItem onClick={handleDelete}>
- <DeleteIcon />
- Delete
- </MenuItem>
- </Menu>
- <CardContent>
- <Grid container direction="row" justify="center" alignItems="center">
- <Grid item>
- <TimerIcon/>
- </Grid>
- <Grid item>
- <Typography variant="h3" color="primary">
- { data.result }
- </Typography>
- </Grid>
- </Grid>
- </CardContent>
- </Card>
- )
-};
-
-export default SolutionCard;
diff --git a/src/components/Timer.tsx b/src/components/Timer.tsx
new file mode 100644
index 0000000..c9d7adf
--- /dev/null
+++ b/src/components/Timer.tsx
@@ -0,0 +1,90 @@
+import React, { useState, useEffect } from 'react';
+import convertTimeToString from '../utils/convertTimeToString';
+
+enum Mode {
+ 'idle',
+ 'countdown',
+ 'running' ,
+ 'over',
+};
+
+const helperText = {
+ [Mode.idle]: 'Hold SPACE to start countdown',
+ [Mode.countdown]: 'Release SPACE to begin',
+ [Mode.running]: 'Go fast!',
+ [Mode.over]: 'You are too late!',
+};
+
+// TODO: add to props
+const registerResult = (result: string): void => {
+ console.log(result)
+};
+
+const Timer: React.FC = () => {
+ const KEY_CODE = 32; // Space key
+ const maxCountdown = 15000;
+
+ const [mode, setMode] = useState<Mode>(Mode.idle);
+ const [displayTime, setDisplayTime] = useState<string>('00:00:00');
+
+ useEffect(() => {
+ const timestamp = Date.now();
+
+ if (mode === Mode.countdown) {
+ const repeater = setInterval(() => {
+ const timeDelta = maxCountdown - (Date.now() - timestamp);
+ if (timeDelta <= 0) setMode(Mode.over);
+ setDisplayTime(convertTimeToString(timeDelta));
+ }, 10);
+ return (): void => clearInterval(repeater);
+ }
+
+ if (mode === Mode.running) {
+ const repeater = setInterval(() => {
+ setDisplayTime(convertTimeToString(Date.now() - timestamp));
+ }, 10);
+ return (): void => clearInterval(repeater);
+ }
+
+ if (mode === Mode.over) {
+ setDisplayTime('00:00:00');
+ }
+ }, [mode]);
+
+ const handleKeyPress = (event: KeyboardEvent): void => {
+ event.preventDefault();
+ if (event.keyCode === KEY_CODE && mode === Mode.idle) setMode(Mode.countdown);
+ };
+
+ const handleKeyUp = (event: KeyboardEvent): void => {
+ if (event.keyCode === KEY_CODE) {
+ if (mode === Mode.running) {
+ registerResult(displayTime);
+ setMode(Mode.idle);
+ } else if (mode === Mode.over) {
+ setMode(Mode.idle);
+ } else {
+ setMode(Mode.running);
+ }
+ }
+ };
+
+ useEffect(() => {
+ window.addEventListener('keyup', handleKeyUp);
+ window.addEventListener('keypress', handleKeyPress);
+
+ return () => {
+ window.removeEventListener('keyup', handleKeyUp);
+ window.removeEventListener('keypress', handleKeyPress);
+ };
+ });
+
+ return (
+ <>
+ <span>{ displayTime }</span>
+ <p>{ helperText[mode] }</p>
+ </>
+ );
+};
+
+export default Timer;