Merge branch 'task-11-feature-my_tasks_page' into 'development'

Task 11 feature my tasks page

See merge request !3
parents 46a799b6 abf6c3c9
This diff is collapsed.
......@@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"-": "^0.0.1",
"@emotion/react": "^11.10.4",
"@emotion/styled": "^11.10.4",
"@mui/icons-material": "^5.10.9",
......@@ -18,6 +19,7 @@
"react-redux": "^8.0.4",
"react-router-dom": "^6.4.2",
"react-scripts": "5.0.1",
"save": "^2.9.0",
"web-vitals": "^2.1.4"
},
"scripts": {
......
......@@ -2,6 +2,7 @@ import {Routes, Route, Outlet, Navigate, BrowserRouter} from "react-router-dom";
import {Container} from "@mui/material";
import {useSelector} from "react-redux";
import AppToolbar from "./components/UI/AppToolBar/AppToolBar";
import MyTasks from './containers/MyTasks/MyTasks'
const ProtectedRoute = ({isAllowed, roles, redirectUrl, children}) => {
const user = useSelector(state => state.users?.user);
......@@ -20,7 +21,7 @@ const App = () => {
<>
<AppToolbar/>
<main>
<Container>
<Container >
<Outlet/>
</Container>
</main>
......@@ -59,7 +60,7 @@ const App = () => {
isAllowed={user}
redirectUrl={"/log-in"}
>
<h1>my tasks page</h1>
<MyTasks/>
</ProtectedRoute>
}/>
......
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
export default function ButtonAppBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Мои задачи
</Typography>
<Button color="inherit">Добавить задачу</Button>
</Toolbar>
</AppBar>
</Box>
);
}
.button {
background-color:rgb(162, 164, 168);
outline: none;
cursor: pointer;
font: inherit;
padding: 5px;
margin: 10px;
font-weight: bold;
border-radius: 2px;
color: #FFF;
border: 1px solid rgb(162, 164, 168);
width: 200px;
height: 50px;
line-height: 35px;
}
.button:hover{
background-color:white;
color: black;
}
\ No newline at end of file
import "./Button.css";
const Button = ({onClick,btnText}) => {
return <button
onClick={onClick}
className="button"
>
{btnText}
</button>
};
export default Button;
\ No newline at end of file
.modal{
width: 200px;
height: 200px;
background-color: rgb(180, 243, 243);
display: flex;
margin:10% 20%;
padding: 30px;
word-break: break-all;
transition-duration:0.5s;
}
.modalBox{
display: flex;
justify-content: space-around;
flex-direction: column;
}
\ No newline at end of file
import { Modal, IconButton } from '@mui/material';
import './TaskModal.css'
const TaskModal = (props) => {
return (
<Modal
aria-labelledby="transition-modal-title"
aria-describedby="transition-modal-description"
className={"modal"}
closeAfterTransition
onClose={props.handleClose}
open={props.open}
>
<div className="modalBox">
{ props.task && props.task.title && (
<div
style={{
width: "200px",
height: "200px",
color: "white",
fontWeight: "600",
}}
>
{props.task.title}
</div>
)}
{props.task && props.task.description && (
<div style={{ width: "200px", height: "200px", color: "white" }}>
{props.task.description}
</div>
)}
<IconButton
sx={{ marginLeft: 0, color: "white" }}
aria-label="close"
onClick={props.handleClose}
>
X
</IconButton>
</div>
</Modal>
);
};
export default TaskModal;
\ No newline at end of file
import * as React from 'react';
import Box from '@mui/material/Box';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';
import DeleteIcon from '@mui/icons-material/Delete';
import { useState } from "react";
import Input from '@mui/material/Input';
import { Done } from '@mui/icons-material';
import {Edit} from '@mui/icons-material'
import TaskModal from '../../components/UI/TaskModal/TaskModal'
import EnhancedTableHead from './MyTasksHeader/MyTasksHeader';
import MyTaskToolBar from '../../components/MyTaskToolBar/MyTaskToolBar'
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
return 1;
}
return 0;
}
function getComparator(order, orderBy) {
return order === 'desc'
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
}
function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) {
return order;
}
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
const CustomTableCell = ({ task, name, onChange, onModalOpen }) => {
return (
<TableCell align="left" style={{ width: "130px", height: "40px" }}>
{task.isEditMode ? (
<Input
value={task[name]}
name={name}
onChange={(e) => onChange(e, task)}
style={{ width: "130px", height: "40px" }}
/>
) : onModalOpen ? (
<span style={{ width: "100%" }} onClick={(e) => onModalOpen(e, task)}>
{task[name]}
</span>
) : (
task[name]
)}
</TableCell>
);
};
export default function EnhancedTable() {
const [order, setOrder] = React.useState('asc');
const [orderBy, setOrderBy] = React.useState('id');
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
const exampleTasks=[
{
user:"first",
title:"задача1",
description:"описание задачи11111",
priority:"A",
author:"Ivan",
executor:"Arman",
dateTimeStart:"26.10.2022",
dateTimeDue:"27.10.2022",
id:1,
dateCreated:"26.10.2022"
},
{
user:"second",
title:"задача2",
description:"описание задачи222222",
author:"Ivan",
executor:"Elena",
priority:"B",
dateTimeStart:"26.10.2022",
dateTimeDue:"27.10.2022",
id:2,
dateCreated:"26.10.2022"
},
{
user:"theird",
title:"задача3",
description:"описание задачи333333bjh,khkuhlhvilv hmgjtycikg mkgyxxkjfkkmgyhkfrdtseygdtjtuliuo8plfyvguh,bb",
author:"Artem",
executor:"Bota",
priority:"B",
dateTimeStart:"30.10.2022",
dateTimeDue:"02.11.2022",
id:3,
dateCreated:"27.10.2022",
}
]
const formattedTasks = exampleTasks.map((t)=> {return {...t, isEditableMode: false}})
const [tasks,setTasks]=useState(formattedTasks)
const onToggleEditMode = id => {
setTasks(state => {
return tasks.map(task => {
if (task.id === id) {
return { ...task, isEditMode: !task.isEditMode };
}
return task;
});
});
};
const onChange = (e, task) => {
const value = e.target.value;
const name = e.target.name;
const { id } = task;
const newTasks = tasks.map(task => {
if (task.id === id) {
return { ...task, [name]: value };
}
return task;
});
setTasks(newTasks);
};
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === 'asc';
setOrder(isAsc ? 'desc' : 'asc');
setOrderBy(property);
};
const deleteTask=()=>{
// удалить по id из selected
}
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
const [modal, setModal] =useState({
open: false,
task: null
});
const onModalOpen = (event, task) => {
console.log(event,task)
event.stopPropagation();
setModal({ ...modal, open: true, task});
};
const handleClose = () => {
setModal({ ...modal, open: false, task: null });
};
return (
<Box sx={{ width: 'fullwidth' }}>
<Paper sx={{ width: '100%', mb: 2 }}>
<MyTaskToolBar/>
<TableContainer>
<Table
sx={{ minWidth: 750 }}
aria-labelledby="tableTitle"
>
<EnhancedTableHead
order={order}
orderBy={orderBy}
onRequestSort={handleRequestSort}
rowCount={tasks.length}
/>
<TableBody>
{stableSort(tasks, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((task, index) => {
return (
<>
<TableRow
hover
key={task.id}
>
<TableCell
component="th"
scope="row"
padding="none"
></TableCell>
<CustomTableCell {...{ task, name: "priority", onChange }} />
<CustomTableCell {...{ task, name: "dateCreated", onChange }} />
<CustomTableCell {...{ task, name: "title", onChange, onModalOpen}} />
<CustomTableCell {...{ task, name: "author", onChange }} />
<CustomTableCell {...{ task, name: "dateTimeStart", onChange }} />
<CustomTableCell {...{ task, name: "dateTimeDue", onChange }} />
<CustomTableCell {...{ task, name: "done", onChange }} />
<TableCell >
{task.isEditMode ? (
<IconButton
aria-label="done"
onClick={() => onToggleEditMode(task.id)}
>
<Done/>
</IconButton>
) : (
<IconButton
aria-label="delete"
onClick={() => onToggleEditMode(task.id)}
>
<Edit/>
</IconButton>
)}
</TableCell>
<TableCell>
<Tooltip title="Delete">
<IconButton onClick={(id)=>{deleteTask(id)}}>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
</>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5,10, 25]}
component="div"
count={tasks.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Paper>
<TaskModal
task={modal.task}
open={modal.open}
handleClose={handleClose}
/>
</Box>
);
}
import * as React from 'react';
import PropTypes from 'prop-types';
import Box from '@mui/material/Box';
import TableCell from '@mui/material/TableCell';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import TableSortLabel from '@mui/material/TableSortLabel';
import { visuallyHidden } from '@mui/utils';
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
return 1;
}
return 0;
}
function getComparator(order, orderBy) {
return order === 'desc'
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
}
// This method is created for cross-browser compatibility, if you don't
// need to support IE11, you can use Array.prototype.sort() directly
function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) {
return order;
}
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
const headCells = [
{
id: 'id',
numeric: true,
disablePadding: true,
label: '',
},
{
id: 'priority',
numeric: false,
disablePadding: true,
label: 'Приоритет',
},
{
id: 'date',
numeric: true,
disablePadding: false,
label: 'Дата',
},
{
id: 'task',
numeric: true,
disablePadding: false,
label: 'Задача',
},
{
id: 'author',
numeric: true,
disablePadding: false,
label: 'Автор',
},
{
id: 'startDate',
numeric: true,
disablePadding: false,
label: 'Дата начала',
},
{
id: 'endDate',
numeric: true,
disablePadding: false,
label: 'Дата завершения',
},
{
id: 'done',
numeric: true,
disablePadding: false,
label: 'Выполнено',
},
{
id: 'change',
numeric: false,
disablePadding: false,
label: '',
},
{
id: 'delete',
numeric: false,
disablePadding: false,
label: '',
},
];
export default function EnhancedTableHead(props) {
const { order, orderBy, rowCount, onRequestSort } =
props;
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
};
return (
<TableHead>
<TableRow>
{headCells.map((headCell) => (
<TableCell
key={headCell.id}
align={'center'}
padding={headCell.disablePadding ? 'none' : 'normal'}
sortDirection={orderBy === headCell.id ? order : false}
>
<TableSortLabel
active={orderBy === headCell.id}
direction={orderBy === headCell.id ? order : 'asc'}
onClick={createSortHandler(headCell.id)}
>
{headCell.label}
{orderBy === headCell.id ? (
<Box component="span" sx={visuallyHidden}>
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
</Box>
) : null}
</TableSortLabel>
</TableCell>
))}
</TableRow>
</TableHead>
);
}
EnhancedTableHead.propTypes = {
onRequestSort: PropTypes.func.isRequired,
order: PropTypes.oneOf(['asc', 'desc']).isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment