mirror of
https://github.com/sergeyyarkov/todo-app.git
synced 2026-10-11 10:29:14 +03:00
added create & update todo modals
This commit is contained in:
parent
308bdf3013
commit
7f5d9d260f
@ -6,6 +6,7 @@ import EditIcon from '@material-ui/icons/Edit';
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
fab: {
|
||||
position: 'fixed',
|
||||
zIndex: 9999,
|
||||
margin: 30,
|
||||
bottom: theme.spacing(2),
|
||||
right: theme.spacing(2),
|
||||
|
||||
@ -1,31 +1,18 @@
|
||||
import React from 'react';
|
||||
import Fab from '../../Fab/Fab'
|
||||
import { Dialog, DialogContent, DialogTitle, DialogActions, Button, TextField, Select, MenuItem, InputLabel, FormControl, makeStyles } from '@material-ui/core'
|
||||
import useStyles from './styles'
|
||||
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(() => ({
|
||||
dialog: {
|
||||
width: 500
|
||||
},
|
||||
form: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
},
|
||||
textField: {
|
||||
margin: '10px 0px'
|
||||
},
|
||||
selectField: {
|
||||
margin: '10px 0px'
|
||||
}
|
||||
}))
|
||||
import categories from '../../../db/categories.json'
|
||||
|
||||
const TodosModal = () => {
|
||||
const CreateTodoModal = ({ isModalOpen, handleCloseModal }) => {
|
||||
const classes = useStyles()
|
||||
const [isModalOpen, setIsModalOpen] = React.useState(false)
|
||||
const [selectedCategory, setSelectedCategory] = React.useState('');
|
||||
|
||||
const handleSelectChange = e => {
|
||||
setSelectedCategory(e.target.value);
|
||||
};
|
||||
const [fieldsData, setFieldsData] = React.useState({
|
||||
title: '',
|
||||
description: '',
|
||||
category: '',
|
||||
deadline: ''
|
||||
})
|
||||
|
||||
const handleFormSubmit = e => {
|
||||
e.preventDefault()
|
||||
@ -37,23 +24,30 @@ const TodosModal = () => {
|
||||
deadline: elements.deadline.value
|
||||
}
|
||||
handleCloseModal()
|
||||
console.log(data)
|
||||
setFieldsData({
|
||||
title: '',
|
||||
description: '',
|
||||
category: '',
|
||||
deadline: ''
|
||||
})
|
||||
console.log('Request on create todo:', data)
|
||||
}
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setIsModalOpen(true)
|
||||
}
|
||||
|
||||
const handleCloseModal = () => {
|
||||
setIsModalOpen(false)
|
||||
const handleFieldChange = e => {
|
||||
const target = e.target
|
||||
setFieldsData({
|
||||
title: target.name === 'title' ? target.value : fieldsData.title,
|
||||
description: target.name === 'description' ? target.value : fieldsData.description,
|
||||
category: target.name === 'category' ? target.value : fieldsData.category,
|
||||
deadline: target.name === 'deadline' ? target.value : fieldsData.deadline
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Fab typeIcon='add' color="secondary" size='large' ariaLabel="add" handleOpenModal={handleOpenModal} />
|
||||
<Dialog fullWidth={true} open={isModalOpen} onClose={handleCloseModal} color='default'>
|
||||
<DialogTitle>
|
||||
Добавить новую запись
|
||||
<AddIcon className={classes.headingIcon} /> Добавить новую запись
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<form onSubmit={handleFormSubmit} noValidate autoComplete="off" className={classes.form}>
|
||||
@ -64,6 +58,8 @@ const TodosModal = () => {
|
||||
placeholder='Название вашей записи'
|
||||
variant="outlined"
|
||||
className={classes.textField}
|
||||
value={fieldsData.title}
|
||||
onChange={handleFieldChange}
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
@ -75,6 +71,8 @@ const TodosModal = () => {
|
||||
placeholder='Описание'
|
||||
variant="outlined"
|
||||
className={classes.textField}
|
||||
value={fieldsData.description}
|
||||
onChange={handleFieldChange}
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
@ -85,14 +83,11 @@ const TodosModal = () => {
|
||||
labelId="category-outlined-label"
|
||||
id="demo-simple-select-outlined"
|
||||
name='category'
|
||||
value={selectedCategory}
|
||||
onChange={handleSelectChange}
|
||||
value={fieldsData.category}
|
||||
onChange={handleFieldChange}
|
||||
label="Категория"
|
||||
>
|
||||
<MenuItem value=""><em>None</em></MenuItem>
|
||||
<MenuItem value='Категория 1'>Категория 1</MenuItem>
|
||||
<MenuItem value='Категория 2'>Категория 2</MenuItem>
|
||||
<MenuItem value='Категория 3'>Категория 3</MenuItem>
|
||||
{categories.map((category, i) => <MenuItem key={i} value={category._id.$oid}>{category._id.$oid}</MenuItem>)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<TextField
|
||||
@ -101,6 +96,8 @@ const TodosModal = () => {
|
||||
variant="outlined"
|
||||
type="datetime-local"
|
||||
className={classes.textField}
|
||||
value={fieldsData.deadline}
|
||||
onChange={handleFieldChange}
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
@ -120,4 +117,4 @@ const TodosModal = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export default TodosModal
|
||||
export default CreateTodoModal
|
||||
@ -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
|
||||
20
client/src/components/Modals/Todo/styles.js
Normal file
20
client/src/components/Modals/Todo/styles.js
Normal 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
|
||||
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import UpdateTodoModal from '../Modals/Todo/UpdateTodoModal'
|
||||
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 AlarmIcon from '@material-ui/icons/Alarm';
|
||||
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 [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 (
|
||||
<>
|
||||
{/* <UpdateTodoModal /> */}
|
||||
{data.map((e, i) =>
|
||||
{!fromTrashContainer ? <UpdateTodoModal isModalOpen={isModalOpen} handleOpenModal={handleOpenModal} handleCloseModal={handleCloseModal} selectedTodo={selectedTodo} setSelectedTodo={setSelectedTodo} /> : null}
|
||||
{data.map((todo, i) =>
|
||||
<Grid key={i} item xs={12} md={4} lg={3}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography className={classes.cardCategoryHeading} color="textSecondary" gutterBottom>
|
||||
Категория 1
|
||||
CategoryId: {todo.categoryId}
|
||||
<span className={classes.cardAlarm}>
|
||||
<AlarmIcon className={classes.alarmIcon} color='action' />
|
||||
18:00
|
||||
{todo.deadline}
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography className={classes.cardHeading} variant="h5" component="h2">
|
||||
Todo 1
|
||||
{todo.title}
|
||||
</Typography>
|
||||
<Typography variant="body2" component="p">
|
||||
But I must explain to you how all this mistaken idea of denouncing pleasure and praising.
|
||||
{todo.description}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions className={classes.cardActions}>
|
||||
<IconButton aria-label="update">
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
{!fromTrashContainer
|
||||
? <IconButton onClick={() => handleOpenModal(todo)} aria-label="update">
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
: <IconButton aria-label="restore">
|
||||
<RestoreIcon />
|
||||
</IconButton>
|
||||
}
|
||||
<IconButton aria-label="delete" color='secondary'>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
|
||||
@ -3,6 +3,8 @@ import Todos from '../../components/Todos/Todos'
|
||||
import Fab from '../../components/Fab/Fab'
|
||||
import { Grid, Typography } from '@material-ui/core'
|
||||
|
||||
import todos from '../../db/todos.json'
|
||||
|
||||
// import { useParams } from 'react-router-dom'
|
||||
|
||||
const Category = () => {
|
||||
@ -14,8 +16,9 @@ const Category = () => {
|
||||
<Typography>
|
||||
Сортируйте свои повседневные дела используя категории.
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Todos data={[1,2,3]} />
|
||||
</Grid>
|
||||
{/* Здесь берем значение slug из query и передаем полученные данные в prop data !!!! */}
|
||||
<Todos data={todos} />
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,19 +1,26 @@
|
||||
import React from 'react';
|
||||
import Fab from '../../components/Fab/Fab'
|
||||
import Todos from '../../components/Todos/Todos'
|
||||
import CreateTodoModal from '../../components/Modals/Todo/CreateTodoModal'
|
||||
import { Typography, Grid } from '@material-ui/core'
|
||||
|
||||
import todosData from '../../db/todos.json'
|
||||
|
||||
const TodosContainer = () => {
|
||||
const [isModalOpen, setIsModalOpen] = React.useState(false)
|
||||
const handleOpenModal = () => setIsModalOpen(true)
|
||||
const handleCloseModal = () => setIsModalOpen(false)
|
||||
return (
|
||||
<>
|
||||
<CreateTodoModal />
|
||||
<CreateTodoModal isModalOpen={isModalOpen} handleCloseModal={handleCloseModal} />
|
||||
<Fab typeIcon='add' color="secondary" size='large' ariaLabel="add" handleOpenModal={handleOpenModal} />
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<Typography>
|
||||
Создавайте, редактируйте или удаляйте ваши повседневные дела.
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Todos data={[1,2,3,4,5,6]} />
|
||||
<Todos data={todosData} />
|
||||
</Grid>
|
||||
</>
|
||||
)
|
||||
|
||||
@ -2,6 +2,8 @@ import React from 'react';
|
||||
import Todos from '../../components/Todos/Todos'
|
||||
import { Grid, Typography } from '@material-ui/core'
|
||||
|
||||
import todos from '../../db/todos.json'
|
||||
|
||||
const Trash = () => {
|
||||
return (
|
||||
<Grid container spacing={2}>
|
||||
@ -10,7 +12,8 @@ const Trash = () => {
|
||||
Здесь находятся ваши недавно удаленные записи, вы можете их легко восстановить.
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Todos data={[1,2]} />
|
||||
{/* Здесь также выполняем нужный запрос на удаленные записи в БД !!!!!!!! */}
|
||||
<Todos data={todos} fromTrashContainer={true} />
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
33
client/src/db/categories.json
Normal file
33
client/src/db/categories.json
Normal 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
56
client/src/db/todos.json
Normal 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"
|
||||
}]
|
||||
Loading…
x
Reference in New Issue
Block a user