diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/App.css | 48 | ||||
-rw-r--r-- | src/App.js | 40 | ||||
-rw-r--r-- | src/RuzCard.js | 94 | ||||
-rw-r--r-- | src/RuzDialog.js | 138 | ||||
-rw-r--r-- | src/RuzList.js | 159 | ||||
-rw-r--r-- | src/index.html | 1 | ||||
-rw-r--r-- | src/signin.js | 117 |
7 files changed, 542 insertions, 55 deletions
diff --git a/src/App.css b/src/App.css index 3837551..e69de29 100644 --- a/src/App.css +++ b/src/App.css @@ -1,48 +0,0 @@ -.App { - height: 100%; - min-height: 400px; - text-align: center; - display: flex; - flex-direction: column; - justify-content: stretch; -} - -.App-flex { - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} - -.App-heading { - background-color: #222; - color: #f8f8f8; - font-size: 6vh; - box-shadow: 0px 4px 4vh 4px rgba(34,34,34,0.9); - z-index: 2; -} - -.App-react { - color: #00d8ff; - text-decoration: overline underline; -} - -.App-logo { - max-height: 30vh; - max-width: 30vh; -} - -.App-instructions { - background-color: #f8f8f8; - color: #222; - font-size: 3vh; - line-height: 1.5; - padding: 0 1em; -} - -.App-instructions code { - background-color: #222; - color: #00d8ff; - padding: .2em .3em; - border-radius: .2em; -} @@ -1,16 +1,42 @@ -import './App.css' +import SignIn from './signin.js'; +import Container from '@material-ui/core/Container'; +import Grid from '@material-ui/core/Grid'; +import RuzList from './RuzList.js'; +//import RuzSearch from './RuzSearch.js'; +import { makeStyles, ThemeProvider, useTheme, createMuiTheme } from '@material-ui/core/styles'; import React, {Component} from 'react' +const theme = createMuiTheme({ + palette: { + type: 'dark', + background: { + paper: '#121212', + default: '#121212', + }, + primary: { + main: '#BB86FC', + }, + secondary: { + main: '#03DAC6', + }, + } +}); + class App extends Component { render() { - return <div className="App"> - <div className="App-heading App-flex"> - <h2>Welcome to <span className="App-react">React</span></h2> - </div> + return <div className=""> + <ThemeProvider theme={theme}> + <Grid container spacing={0}> + <Grid item xs={12} md={6} lg={6}> + <RuzList /> + </Grid> + <Grid item xs={12} md={6} lg={6}> + {/* <SignIn /> */} + </Grid> + </Grid> + </ThemeProvider> <div className="App-instructions App-flex"> - <img className="App-logo" src={require('./react.svg')}/> - <p>Edit <code>src/App.js</code> and save to hot reload your changes.</p> </div> </div> } diff --git a/src/RuzCard.js b/src/RuzCard.js new file mode 100644 index 0000000..4b0a39a --- /dev/null +++ b/src/RuzCard.js @@ -0,0 +1,94 @@ +import React, { useState } from 'react'; +import { makeStyles, useTheme } from '@material-ui/core/styles'; +import Card from '@material-ui/core/Card'; +import CardContent from '@material-ui/core/CardContent'; +import CardMedia from '@material-ui/core/CardMedia'; +import Typography from '@material-ui/core/Typography'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemAvatar from '@material-ui/core/ListItemAvatar'; +import ListItemText from '@material-ui/core/ListItemText'; +import { Button, useMediaQuery, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@material-ui/core'; + + +const useStyles = makeStyles(theme => ({ + card: { + display: 'flex', + }, + details: { + display: 'flex', + flexDirection: 'column', + }, + content: { + flex: '1 0 auto', + }, + inline: { + display: 'inline', + }, + seminarCard: { + color: 'limegreen', + }, + examCard: { + color: 'red', + }, +})); + + +function class_by_type (type, classes) { + let classname = null; + switch (type) { + case 'Семинар': + classname = classes.seminarCard; + break; + case 'Экзамен': + classname = classes.examCard; + break; + default: + return; + } + + return classname; +} + + +export default function RuzCard(props) { + const classes = useStyles(); + const theme = useTheme(); + const dialogFullScreen = useMediaQuery(theme.breakpoints.down('sm')); + const [open, setOpen] = useState(false); + + const handleClickOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + + + return ( + <ListItem alignItems="flex-start" button onClick={props.onClick}> + <ListItemAvatar> + <div> + <Typography variant="body2">{props.item.beginLesson}</Typography><br /> + <Typography variant="body2" color="secondary">{props.item.endLesson}</Typography> + </div> + </ListItemAvatar> + <ListItemText + primary={props.item.discipline} + secondary={ + <React.Fragment> + {props.item.auditorium}<br /> + <Typography + component="span" + variant="body2" + className={class_by_type(props.item.kindOfWork, classes)} + color="textPrimary" + > + {props.item.kindOfWork} + </Typography> + </React.Fragment> + } + /> + </ListItem> + ) +}
\ No newline at end of file diff --git a/src/RuzDialog.js b/src/RuzDialog.js new file mode 100644 index 0000000..5a8e8ea --- /dev/null +++ b/src/RuzDialog.js @@ -0,0 +1,138 @@ +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { Dialog, DialogContent, DialogContentText, DialogTitle, DialogActions, Button, List } from '@material-ui/core'; +import { useMediaQuery, useTheme } from '@material-ui/core'; +import { Divider, ListItem, ListItemAvatar, ListItemText } from '@material-ui/core'; +import { AppBar, Toolbar, IconButton, Typography } from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; + + +const useStyles = makeStyles(theme => ({ + paper: { + marginTop: theme.spacing(3), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: '100%', + }, + schedule: { + width: '100%', + backgroundColor: theme.palette.background.paper, + }, + avatar: { + margin: theme.spacing(1), + backgroundColor: theme.palette.secondary.main, + }, + stickyHeader: { + background: 'inherit', + }, + fixUl: { + padding: 0, + background: 'inherit', + }, + centerProgress: { + position: 'absolute', + top: '50%', + verticalAlign: 'middle', + }, + dateHeader: { + textTransform: 'capitalize', + color: 'teal', + }, + mobileBar: { + position: 'relative', + }, + mobileTitle: { + marginLeft: theme.spacing(2), + flex: 1, + }, +})); + +function RuzDialogCard(props) { + + return ( + <ListItem alignItems="flex-start"> + <ListItemText + primary={props.entry.description} + /> + </ListItem> + ) +} + +function RuzDialogList(props) { + const item = props.item; + const classes = useStyles(); + + const entries = [ + { description: `${item.building}` }, + { description: `${item.lecturer}` }, + ]; + + return ( + <List className={classes.schedule}> + {entries.map(entry => { + return ( + <React.Fragment> + <RuzDialogCard entry={entry} /> + <Divider /> + </React.Fragment> + );} + )} + </List> + ) +} + +function MobileNavBar(props) { + + const classes = useStyles(); + const closeAction = props.closeAction; + const title = props.title; + + return ( + <AppBar className={classes.mobileBar}> + <Toolbar> + <IconButton edge="start" color="inherit" onClick={closeAction} aria-label="close"> + <CloseIcon /> + </IconButton> + <Typography variant="h6" className={classes.mobileTitle}> + {title} + </Typography> + </Toolbar> + </AppBar> + ); +} + +export default function RuzDialog(props) { + if (!props.open) + return <React.Fragment /> + + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const closeAction = props.dialogCloseAction; + + return ( + <Dialog + fullScreen={isMobile} + fullWidth={true} + maxWidth="xs" + open={true} + onClose={closeAction} + aria-labelledby="ruz-dialog-title" + > + { + isMobile ? + <MobileNavBar closeAction={closeAction} title={props.dialog.discipline} /> + : + <DialogTitle id="responsive-dialog-title">{props.dialog.discipline}</DialogTitle> + } + <DialogContent> + <RuzDialogList item={props.dialog} /> + </DialogContent> + <DialogActions> + <Button onClick={closeAction} color="primary" autoFocus> + close + </Button> + </DialogActions> + </Dialog> + ); +} diff --git a/src/RuzList.js b/src/RuzList.js new file mode 100644 index 0000000..c31c4aa --- /dev/null +++ b/src/RuzList.js @@ -0,0 +1,159 @@ +import React, { useState } from 'react'; +import Avatar from '@material-ui/core/Avatar'; +import Button from '@material-ui/core/Button'; +import CssBaseline from '@material-ui/core/CssBaseline'; +import TextField from '@material-ui/core/TextField'; +import FormControlLabel from '@material-ui/core/FormControlLabel'; +import Checkbox from '@material-ui/core/Checkbox'; +import Link from '@material-ui/core/Link'; +import Grid from '@material-ui/core/Grid'; +import Box from '@material-ui/core/Box'; +import ScheduleIcon from '@material-ui/icons/Schedule'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; +import Container from '@material-ui/core/Container'; +import Divider from '@material-ui/core/Divider'; +import List from '@material-ui/core/List'; +import ListSubheader from '@material-ui/core/ListSubheader'; +import { CircularProgress } from '@material-ui/core'; +import { useTheme } from '@material-ui/core/styles'; +import { useMediaQuery, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@material-ui/core'; + +import axios from 'axios'; + +import RuzCard from './RuzCard.js'; +import RuzDialog from './RuzDialog.js'; + + +const useStyles = makeStyles(theme => ({ + paper: { + marginTop: theme.spacing(3), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: '100%', + }, + schedule: { + width: '100%', + backgroundColor: theme.palette.background.paper, + }, + avatar: { + margin: theme.spacing(1), + backgroundColor: theme.palette.secondary.main, + }, + stickyHeader: { + background: 'inherit', + }, + fixUl: { + padding: 0, + background: 'inherit', + }, + centerProgress: { + position: 'absolute', + top: '50%', + verticalAlign: 'middle', + }, + dateHeader: { + textTransform: 'capitalize', + color: 'teal', + }, +})); + + +function RuzListDate(props) { + const items = props.items; + const date = new Date(props.date); + const datestring = date.toLocaleDateString('ru-RU', {weekday: 'short', day: 'numeric', month: 'long'}) + const classes = useStyles(); + + return ( + <React.Fragment key={`ruzdate-inner-${props.date}`}> + <ListSubheader className={classes.dateHeader}> + {datestring} + </ListSubheader> + { + items.map(item => { + return ( + <React.Fragment> + <RuzCard onClick={() => props.onClickForward(item)} item={item} /> + <Divider variant="inset" /> + </React.Fragment> + ); + }) + } + </React.Fragment> + ); +} + + +export default function RuzList(props) { + const classes = useStyles(); + + const [ items, setItems ] = useState([]); + const [ needUpdate, setNeedUpdate ] = useState(true); + const [ openDialog, setOpenDialog ] = useState(null); + + if (needUpdate) { + axios({ + method: 'GET', + url: 'http://cors.hell.fcked.net/api/schedule/group/11235', + params: { + start: '2019.12.16', + finish: '2019.12.23', + lng: '1', + }, + }).then(resp => { + setNeedUpdate(false); + + const data = {}; + for (let [id, item] of resp.data.entries()) { + if (!item) continue; + item.id = id; + item.date in data + ? + data[item.date].push(item) + : + data[item.date] = [item]; + } + setItems(data); + }); + } + + console.log(openDialog); + const dialogCloseAction = () => { + setOpenDialog(null); + } + + let progressBar = (<React.Fragment />); + if (needUpdate) { + progressBar = (<CircularProgress className={classes.centerProgress} />); + } + + const dates = [...Object.keys(items)].sort(); + + return ( + <Container component="main" maxWidth="xs"> + <CssBaseline /> + <RuzDialog dialog={openDialog} open={openDialog !== null} dialogCloseAction={dialogCloseAction} /> + <div className={classes.paper}> + <Avatar className={classes.avatar}> + <ScheduleIcon /> + </Avatar> + {progressBar} + <List className={classes.schedule} hidden={items.needUpdate}> + { + dates.map(date => { + return ( + <li key={`ruzdate-${date}`} className={classes.stickyHeader}> + <ul className={classes.fixUl}> + <RuzListDate onClickForward={setOpenDialog} items={items[date]} date={date} /> + </ul> + </li> + ) + }) + } + </List> + </div> + </Container> + ); +} diff --git a/src/index.html b/src/index.html index d0bdd15..4c8a34e 100644 --- a/src/index.html +++ b/src/index.html @@ -4,6 +4,7 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta http-equiv="x-ua-compatible" content="ie=edge"> + <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" /> <title>fcked-rt</title> <meta name="description" content=""> </head> diff --git a/src/signin.js b/src/signin.js new file mode 100644 index 0000000..4d7ed4f --- /dev/null +++ b/src/signin.js @@ -0,0 +1,117 @@ +import React from 'react'; +import Avatar from '@material-ui/core/Avatar'; +import Button from '@material-ui/core/Button'; +import CssBaseline from '@material-ui/core/CssBaseline'; +import TextField from '@material-ui/core/TextField'; +import FormControlLabel from '@material-ui/core/FormControlLabel'; +import Checkbox from '@material-ui/core/Checkbox'; +import Link from '@material-ui/core/Link'; +import Grid from '@material-ui/core/Grid'; +import Box from '@material-ui/core/Box'; +import LockOutlinedIcon from '@material-ui/icons/LockOutlined'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; +import Container from '@material-ui/core/Container'; + +function Copyright() { + return ( + <Typography variant="body2" color="textSecondary" align="center"> + {'Copyright © '} + <Link color="inherit" href="https://material-ui.com/"> + Your Website + </Link>{' '} + {new Date().getFullYear()} + {'.'} + </Typography> + ); +} + +const useStyles = makeStyles(theme => ({ + paper: { + marginTop: theme.spacing(8), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + }, + avatar: { + margin: theme.spacing(1), + backgroundColor: theme.palette.secondary.main, + }, + form: { + width: '100%', // Fix IE 11 issue. + marginTop: theme.spacing(1), + }, + submit: { + margin: theme.spacing(3, 0, 2), + }, +})); + +export default function SignIn() { + const classes = useStyles(); + + return ( + <Container component="main" maxWidth="xs"> + <CssBaseline /> + <div className={classes.paper}> + <Avatar className={classes.avatar}> + <LockOutlinedIcon /> + </Avatar> + <Typography component="h1" variant="h5"> + Sign in + </Typography> + <form className={classes.form} noValidate> + <TextField + variant="outlined" + margin="normal" + required + fullWidth + id="email" + label="Email Address" + name="email" + autoComplete="email" + autoFocus + /> + <TextField + variant="outlined" + margin="normal" + required + fullWidth + name="password" + label="Password" + type="password" + id="password" + autoComplete="current-password" + /> + <FormControlLabel + control={<Checkbox value="remember" color="primary" />} + label="Remember me" + /> + <Button + type="submit" + fullWidth + variant="contained" + color="primary" + className={classes.submit} + > + Sign In + </Button> + <Grid container> + <Grid item xs> + <Link href="#" variant="body2"> + Forgot password? + </Link> + </Grid> + <Grid item> + <Link href="#" variant="body2"> + {"Don't have an account? Sign Up"} + </Link> + </Grid> + </Grid> + </form> + </div> + <Box mt={8}> + <Copyright /> + </Box> + </Container> + ); +} |