added create & update todo modals

This commit is contained in:
Sergey Yarkov 2020-06-12 20:39:43 +03:00
parent 308bdf3013
commit 7f5d9d260f
10 changed files with 307 additions and 55 deletions

View File

@ -6,6 +6,7 @@ import EditIcon from '@material-ui/icons/Edit';
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
fab: { fab: {
position: 'fixed', position: 'fixed',
zIndex: 9999,
margin: 30, margin: 30,
bottom: theme.spacing(2), bottom: theme.spacing(2),
right: theme.spacing(2), right: theme.spacing(2),

View File

@ -1,31 +1,18 @@
import React from 'react'; import React from 'react';
import Fab from '../../Fab/Fab' import useStyles from './styles'
import { Dialog, DialogContent, DialogTitle, DialogActions, Button, TextField, Select, MenuItem, InputLabel, FormControl, makeStyles } from '@material-ui/core' import { Dialog, DialogContent, DialogTitle, DialogActions, Button, TextField, Select, MenuItem, InputLabel, FormControl } from '@material-ui/core'
import AddIcon from '@material-ui/icons/Add'
const useStyles = makeStyles(() => ({ import categories from '../../../db/categories.json'
dialog: {
width: 500
},
form: {
display: 'flex',
flexDirection: 'column'
},
textField: {
margin: '10px 0px'
},
selectField: {
margin: '10px 0px'
}
}))
const TodosModal = () => { const CreateTodoModal = ({ isModalOpen, handleCloseModal }) => {
const classes = useStyles() const classes = useStyles()
const [isModalOpen, setIsModalOpen] = React.useState(false) const [fieldsData, setFieldsData] = React.useState({
const [selectedCategory, setSelectedCategory] = React.useState(''); title: '',
description: '',
const handleSelectChange = e => { category: '',
setSelectedCategory(e.target.value); deadline: ''
}; })
const handleFormSubmit = e => { const handleFormSubmit = e => {
e.preventDefault() e.preventDefault()
@ -37,23 +24,30 @@ const TodosModal = () => {
deadline: elements.deadline.value deadline: elements.deadline.value
} }
handleCloseModal() handleCloseModal()
console.log(data) setFieldsData({
title: '',
description: '',
category: '',
deadline: ''
})
console.log('Request on create todo:', data)
} }
const handleOpenModal = () => { const handleFieldChange = e => {
setIsModalOpen(true) const target = e.target
} setFieldsData({
title: target.name === 'title' ? target.value : fieldsData.title,
const handleCloseModal = () => { description: target.name === 'description' ? target.value : fieldsData.description,
setIsModalOpen(false) category: target.name === 'category' ? target.value : fieldsData.category,
deadline: target.name === 'deadline' ? target.value : fieldsData.deadline
})
} }
return ( return (
<div> <div>
<Fab typeIcon='add' color="secondary" size='large' ariaLabel="add" handleOpenModal={handleOpenModal} />
<Dialog fullWidth={true} open={isModalOpen} onClose={handleCloseModal} color='default'> <Dialog fullWidth={true} open={isModalOpen} onClose={handleCloseModal} color='default'>
<DialogTitle> <DialogTitle>
Добавить новую запись <AddIcon className={classes.headingIcon} /> Добавить новую запись
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<form onSubmit={handleFormSubmit} noValidate autoComplete="off" className={classes.form}> <form onSubmit={handleFormSubmit} noValidate autoComplete="off" className={classes.form}>
@ -64,6 +58,8 @@ const TodosModal = () => {
placeholder='Название вашей записи' placeholder='Название вашей записи'
variant="outlined" variant="outlined"
className={classes.textField} className={classes.textField}
value={fieldsData.title}
onChange={handleFieldChange}
InputLabelProps={{ InputLabelProps={{
shrink: true, shrink: true,
}} }}
@ -75,6 +71,8 @@ const TodosModal = () => {
placeholder='Описание' placeholder='Описание'
variant="outlined" variant="outlined"
className={classes.textField} className={classes.textField}
value={fieldsData.description}
onChange={handleFieldChange}
InputLabelProps={{ InputLabelProps={{
shrink: true, shrink: true,
}} }}
@ -85,14 +83,11 @@ const TodosModal = () => {
labelId="category-outlined-label" labelId="category-outlined-label"
id="demo-simple-select-outlined" id="demo-simple-select-outlined"
name='category' name='category'
value={selectedCategory} value={fieldsData.category}
onChange={handleSelectChange} onChange={handleFieldChange}
label="Категория" label="Категория"
> >
<MenuItem value=""><em>None</em></MenuItem> {categories.map((category, i) => <MenuItem key={i} value={category._id.$oid}>{category._id.$oid}</MenuItem>)}
<MenuItem value='Категория 1'>Категория 1</MenuItem>
<MenuItem value='Категория 2'>Категория 2</MenuItem>
<MenuItem value='Категория 3'>Категория 3</MenuItem>
</Select> </Select>
</FormControl> </FormControl>
<TextField <TextField
@ -101,6 +96,8 @@ const TodosModal = () => {
variant="outlined" variant="outlined"
type="datetime-local" type="datetime-local"
className={classes.textField} className={classes.textField}
value={fieldsData.deadline}
onChange={handleFieldChange}
InputLabelProps={{ InputLabelProps={{
shrink: true, shrink: true,
}} }}
@ -120,4 +117,4 @@ const TodosModal = () => {
) )
} }
export default TodosModal export default CreateTodoModal

View File

@ -0,0 +1,108 @@
import React from 'react';
import useStyles from './styles'
import { Dialog, DialogContent, DialogTitle, DialogActions, Button, TextField, Select, MenuItem, InputLabel, FormControl } from '@material-ui/core'
import EditIcon from '@material-ui/icons/Edit'
import categories from '../../../db/categories.json'
const UpdateTodoModal = ({ isModalOpen, handleCloseModal, selectedTodo, setSelectedTodo }) => {
const classes = useStyles()
const handleFormSubmit = e => {
e.preventDefault()
const elements = e.target.elements
const data = {
title: elements.title.value,
description: elements.description.value,
category: elements.category.value,
deadline: elements.deadline.value
}
handleCloseModal()
console.log('Request on update:', data)
}
const handleFieldChange = e => {
const target = e.target
setSelectedTodo({
title: target.name === 'title' ? target.value : selectedTodo.title,
description: target.name === 'description' ? target.value : selectedTodo.description,
category: target.name === 'category' ? target.value : selectedTodo.category,
deadline: target.name === 'deadline' ? target.value : selectedTodo.deadline
})
}
return (
<div>
<Dialog fullWidth={true} open={isModalOpen} onClose={handleCloseModal} color='default'>
<DialogTitle className={classes.heading}>
<EditIcon className={classes.headingIcon} />
Изменить запись
</DialogTitle>
<DialogContent>
<form onSubmit={handleFormSubmit} noValidate autoComplete="off" className={classes.form}>
<TextField
name='title'
label="Название вашей записи"
margin="normal"
placeholder='Название вашей записи'
variant="outlined"
className={classes.textField}
value={selectedTodo.title}
onChange={handleFieldChange}
InputLabelProps={{
shrink: true,
}}
/>
<TextField
name='description'
label="Описание"
margin="normal"
placeholder='Описание'
variant="outlined"
className={classes.textField}
value={selectedTodo.description}
onChange={handleFieldChange}
InputLabelProps={{
shrink: true,
}}
/>
<FormControl variant="outlined" className={classes.selectField}>
<InputLabel id="category-outlined-label">Категория</InputLabel>
<Select
labelId="category-outlined-label"
id="demo-simple-select-outlined"
name='category'
value={selectedTodo.category}
onChange={handleFieldChange}
label="Категория"
>
{categories.map((category, i) => <MenuItem key={i} value={category._id.$oid}>{category._id.$oid}</MenuItem>)}
</Select>
</FormControl>
<TextField
name='deadline'
label="Дедлайн"
variant="outlined"
type="datetime-local"
className={classes.textField}
value={selectedTodo.deadline}
onChange={handleFieldChange}
InputLabelProps={{
shrink: true,
}}
/>
<DialogActions>
<Button type='submit' color="default">
Обновить
</Button>
<Button onClick={handleCloseModal} color="secondary">
Закрыть
</Button>
</DialogActions>
</form>
</DialogContent>
</Dialog>
</div>
)
}
export default UpdateTodoModal

View File

@ -0,0 +1,20 @@
import { makeStyles } from '@material-ui/core/styles'
const useStyles = makeStyles(() => ({
form: {
display: 'flex',
flexDirection: 'column'
},
headingIcon: {
marginRight: 10,
verticalAlign: 'text-bottom'
},
textField: {
margin: '10px 0px'
},
selectField: {
margin: '10px 0px'
}
}))
export default useStyles

View File

@ -2,6 +2,7 @@ import React from 'react';
import UpdateTodoModal from '../Modals/Todo/UpdateTodoModal' import UpdateTodoModal from '../Modals/Todo/UpdateTodoModal'
import { Card, CardActions, CardContent, Typography, Grid, IconButton, makeStyles } from '@material-ui/core' import { Card, CardActions, CardContent, Typography, Grid, IconButton, makeStyles } from '@material-ui/core'
import RestoreIcon from '@material-ui/icons/Restore';
import DeleteIcon from '@material-ui/icons/Delete' import DeleteIcon from '@material-ui/icons/Delete'
import AlarmIcon from '@material-ui/icons/Alarm'; import AlarmIcon from '@material-ui/icons/Alarm';
import EditIcon from '@material-ui/icons/Edit'; import EditIcon from '@material-ui/icons/Edit';
@ -33,33 +34,56 @@ const useStyles = makeStyles((theme) => ({
}, },
})) }))
const Todos = ({ data }) => { const Todos = ({ data, fromTrashContainer }) => {
const classes = useStyles() const classes = useStyles()
const [selectedTodo, setSelectedTodo] = React.useState({
title: '',
description: '',
category: '',
deadline: ''
})
const [isModalOpen, setIsModalOpen] = React.useState(false)
const handleOpenModal = todo => {
setSelectedTodo({
title: todo.title,
description: todo.description,
category: todo.categoryId,
deadline: todo.deadline
})
setIsModalOpen(true)
}
const handleCloseModal = () => setIsModalOpen(false)
return ( return (
<> <>
{/* <UpdateTodoModal /> */} {!fromTrashContainer ? <UpdateTodoModal isModalOpen={isModalOpen} handleOpenModal={handleOpenModal} handleCloseModal={handleCloseModal} selectedTodo={selectedTodo} setSelectedTodo={setSelectedTodo} /> : null}
{data.map((e, i) => {data.map((todo, i) =>
<Grid key={i} item xs={12} md={4} lg={3}> <Grid key={i} item xs={12} md={4} lg={3}>
<Card> <Card>
<CardContent> <CardContent>
<Typography className={classes.cardCategoryHeading} color="textSecondary" gutterBottom> <Typography className={classes.cardCategoryHeading} color="textSecondary" gutterBottom>
Категория 1 CategoryId: {todo.categoryId}
<span className={classes.cardAlarm}> <span className={classes.cardAlarm}>
<AlarmIcon className={classes.alarmIcon} color='action' /> <AlarmIcon className={classes.alarmIcon} color='action' />
18:00 {todo.deadline}
</span> </span>
</Typography> </Typography>
<Typography className={classes.cardHeading} variant="h5" component="h2"> <Typography className={classes.cardHeading} variant="h5" component="h2">
Todo 1 {todo.title}
</Typography> </Typography>
<Typography variant="body2" component="p"> <Typography variant="body2" component="p">
But I must explain to you how all this mistaken idea of denouncing pleasure and praising. {todo.description}
</Typography> </Typography>
</CardContent> </CardContent>
<CardActions className={classes.cardActions}> <CardActions className={classes.cardActions}>
<IconButton aria-label="update"> {!fromTrashContainer
<EditIcon /> ? <IconButton onClick={() => handleOpenModal(todo)} aria-label="update">
</IconButton> <EditIcon />
</IconButton>
: <IconButton aria-label="restore">
<RestoreIcon />
</IconButton>
}
<IconButton aria-label="delete" color='secondary'> <IconButton aria-label="delete" color='secondary'>
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>

View File

@ -3,6 +3,8 @@ import Todos from '../../components/Todos/Todos'
import Fab from '../../components/Fab/Fab' import Fab from '../../components/Fab/Fab'
import { Grid, Typography } from '@material-ui/core' import { Grid, Typography } from '@material-ui/core'
import todos from '../../db/todos.json'
// import { useParams } from 'react-router-dom' // import { useParams } from 'react-router-dom'
const Category = () => { const Category = () => {
@ -15,7 +17,8 @@ const Category = () => {
Сортируйте свои повседневные дела используя категории. Сортируйте свои повседневные дела используя категории.
</Typography> </Typography>
</Grid> </Grid>
<Todos data={[1,2,3]} /> {/* Здесь берем значение slug из query и передаем полученные данные в prop data !!!! */}
<Todos data={todos} />
</Grid> </Grid>
) )
} }

View File

@ -1,19 +1,26 @@
import React from 'react'; import React from 'react';
import Fab from '../../components/Fab/Fab'
import Todos from '../../components/Todos/Todos' import Todos from '../../components/Todos/Todos'
import CreateTodoModal from '../../components/Modals/Todo/CreateTodoModal' import CreateTodoModal from '../../components/Modals/Todo/CreateTodoModal'
import { Typography, Grid } from '@material-ui/core' import { Typography, Grid } from '@material-ui/core'
import todosData from '../../db/todos.json'
const TodosContainer = () => { const TodosContainer = () => {
const [isModalOpen, setIsModalOpen] = React.useState(false)
const handleOpenModal = () => setIsModalOpen(true)
const handleCloseModal = () => setIsModalOpen(false)
return ( return (
<> <>
<CreateTodoModal /> <CreateTodoModal isModalOpen={isModalOpen} handleCloseModal={handleCloseModal} />
<Fab typeIcon='add' color="secondary" size='large' ariaLabel="add" handleOpenModal={handleOpenModal} />
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography> <Typography>
Создавайте, редактируйте или удаляйте ваши повседневные дела. Создавайте, редактируйте или удаляйте ваши повседневные дела.
</Typography> </Typography>
</Grid> </Grid>
<Todos data={[1,2,3,4,5,6]} /> <Todos data={todosData} />
</Grid> </Grid>
</> </>
) )

View File

@ -2,6 +2,8 @@ import React from 'react';
import Todos from '../../components/Todos/Todos' import Todos from '../../components/Todos/Todos'
import { Grid, Typography } from '@material-ui/core' import { Grid, Typography } from '@material-ui/core'
import todos from '../../db/todos.json'
const Trash = () => { const Trash = () => {
return ( return (
<Grid container spacing={2}> <Grid container spacing={2}>
@ -10,7 +12,8 @@ const Trash = () => {
Здесь находятся ваши недавно удаленные записи, вы можете их легко восстановить. Здесь находятся ваши недавно удаленные записи, вы можете их легко восстановить.
</Typography> </Typography>
</Grid> </Grid>
<Todos data={[1,2]} /> {/* Здесь также выполняем нужный запрос на удаленные записи в БД !!!!!!!! */}
<Todos data={todos} fromTrashContainer={true} />
</Grid> </Grid>
) )
} }

View File

@ -0,0 +1,33 @@
[{
"_id": {
"$oid": "5ede6bbafed78043ac0339ff"
},
"title": "Category 1",
"description": "some description",
"updatedAt": "2020-04-04",
"createdAt": "2020-01-01"
},{
"_id": {
"$oid": "5ede6bbafed78043ac033a00"
},
"title": "Category 2",
"description": "some description",
"updatedAt": "2020-04-04",
"createdAt": "2020-01-01"
},{
"_id": {
"$oid": "5ede6bbafed78043ac033a01"
},
"title": "Category 3",
"description": "some description",
"updatedAt": "2020-04-04",
"createdAt": "2020-01-01"
},{
"_id": {
"$oid": "5ede83c823d3141d80145f2b"
},
"title": "upd category title",
"description": "upd category description",
"createdAt": "2020-06-08T18:30:32.811Z",
"updatedAt": "2020-06-08T18:32:34.962Z"
}]

56
client/src/db/todos.json Normal file
View File

@ -0,0 +1,56 @@
[{
"_id": {
"$oid": "5ede6a82fed78043ac0339fa"
},
"title": "Todo 1",
"description": "Todo 1 description",
"createdAt": "2020-01-01",
"updatedAt": "2020-04-04",
"status": "open",
"deadline": "2020-06-12T20:18",
"categoryId": "5ede6bbafed78043ac0339ff"
},{
"_id": {
"$oid": "5ede6a82fed78043ac0339fb"
},
"title": "Todo 2",
"description": "Todo 2 description",
"createdAt": "2020-01-01",
"updatedAt": "2020-04-04",
"status": "open",
"deadline": "2020-06-12T20:18",
"categoryId": "5ede6bbafed78043ac0339ff"
},{
"_id": {
"$oid": "5ede6a82fed78043ac0339fc"
},
"title": "Todo 3",
"description": "Todo 3 description",
"createdAt": "2020-01-01",
"updatedAt": "2020-04-04",
"status": "open",
"deadline": "2020-06-12T20:18",
"categoryId": "5ede6bbafed78043ac033a00"
},{
"_id": {
"$oid": "5ede6a82fed78043ac0339fe"
},
"title": "Todo 4",
"description": "Todo 4 description",
"createdAt": "2020-01-01",
"updatedAt": "2020-04-04",
"status": "open",
"deadline": "2020-06-12T20:18",
"categoryId": "5ede6bbafed78043ac033a01"
},{
"_id": {
"$oid": "5ede7ef02ef0cd3c1c8660e8"
},
"title": "Todo 5",
"description": "Todo 5 description",
"createdAt": "2020-01-01",
"updatedAt": "2020-04-04",
"status": "open",
"deadline": "2020-06-12T20:18",
"categoryId": "5ede6bbafed78043ac033a00"
}]