Commit f1b96f9e authored by Ibadullina Inabat's avatar Ibadullina Inabat

Merge branch 'development' of…

Merge branch 'development' of ssh://git.attractor-school.com:30022/apollo64/crm-team-one into task-107-fix/add_checking_front
parents 75de717a 17849e6b
......@@ -121,6 +121,7 @@ router.get('/user/:userId', async (req : Request, res : Response): Promise<Respo
router.post('/add-user/', authAdminProject, async (req: Request, res: Response):Promise<Response>=>{
const {userId, projectId, roleProject} = req.body;
console.log("req body" + req.body)
const newMember:Member = new Member();
try{
newMember.user= userId;
......
......@@ -24,7 +24,7 @@ router.get('/', async(req:Request, res:Response):Promise<Response> => {
})
/**create new task */
/**create new task for table MyTask*/
router.post('/', auth, async(req:Request, res:Response):Promise<Response>=>{
const {user,title,description,project,executor,dateTimeStart,dateTimeDue, dateTimeDeadLine,priority} = req.body;
const newTask = new Task();
......@@ -48,7 +48,6 @@ router.post('/', auth, async(req:Request, res:Response):Promise<Response>=>{
},
}
})
console.log ('watcherOfProject ', watcherOfProject)
if (watcherOfProject) return res.send({message:"watcher could nt make tasks"})
newTask.project = project;
} else {
......@@ -94,6 +93,73 @@ router.post('/', auth, async(req:Request, res:Response):Promise<Response>=>{
})
//** create new task for table UsersTasks*/
router.post('/users', auth, async(req:Request, res:Response):Promise<Response>=>{
const {user,title,description,project,executor,dateTimeStart,dateTimeDue, dateTimeDeadLine,priority} = req.body;
const newTask = new Task();
newTask.title = title;
newTask.description = description;
if (project) {
const watcherOfProject = await dataSource
.getRepository(Project)
.findOne({
relations:{
members:true,
},
where:
{
id:project.id,
members:
{
user:{id:user.id},
roleProject:MemberRole.WATCHER,
},
}
})
if (watcherOfProject) return res.send({message:"watcher could nt make tasks"})
newTask.project = project;
} else {
const personalProject = await dataSource
.getRepository(Project)
.findOne({
where:{
members:{
user:{id:user.id},
},
title:"Не определено"
}
})
if(personalProject){
newTask.project = personalProject;
} else {
const newPersonalProject = new Project();
newPersonalProject.title="Не определено";
newPersonalProject.color="green";
await newPersonalProject.save()
newTask.project = newPersonalProject;
const newMember = new Member();
newMember.user= user;
newMember.project=newPersonalProject;
newMember.roleProject = MemberRole.ADMIN;
await newMember.save();
console.log ('newPersonalProject ', newPersonalProject)
}
}
newTask.dateTimeDeadLine=dateTimeDeadLine;
newTask.author= user;
newTask.executor= executor;
newTask.priority = priority;
await newTask.save();
const newDateTimeTask = new DateTimeTask();
newDateTimeTask.dateTimeStart = dateTimeStart
newDateTimeTask.dateTimeDue = dateTimeDue
newDateTimeTask.task = newTask
await newDateTimeTask.save()
return res.send({newTask});
})
/**check tasks of specific user by userID */
router.get('/user/:userId', async (req: Request, res: Response):Promise<Response>=>{
const userId = req.params.userId;
......@@ -272,6 +338,39 @@ router.post('/project',async (req: Request, res: Response):Promise<Response>=>{
/**check other users tasks that are related to the user through common projects, by user token*/
router.get('/users-tasks', auth,async (req: Request, res: Response):Promise<Response>=>{
const {user} = req.body
const projects = await dataSource
.getRepository(Project)
.find(
{ relations:{
members:true,
tasks:{
author:true,
executor:true
}
},
where:{
members:{
user:{
id:user.id
}
}
}})
if (!projects) return res.status(404).send({Message:'projects not found'})
let tasks:Task[] = []
if (projects.length>0) {
for (let project of projects){
if (project?.tasks) {
tasks=tasks.concat(project.tasks)
}
}
}
return res.send({projects, tasks})
})
export default router;
......@@ -11,6 +11,7 @@ import Projects from "./containers/Projects/Projects";
import FullProject from "./containers/FullProject/FullProject";
import NewProject from "./containers/NewProject/NewProject";
import WeekCalendar from "./containers/WeekCalendar/WeekCalendar";
import UsersTasks from "./containers/UsersTasks/UsersTasks";
const ProtectedRoute = ({ isAllowed, roles, redirectUrl, children }) => {
const user = useSelector(state => state.users?.user);
......@@ -117,10 +118,11 @@ const App = () => {
<Route path={"/workers-tasks"} element={
<ProtectedRoute
roles={["superuser"]}
isAllowed={user}
redirectUrl={"/"}
>
<h1>workers tasks page</h1>
<UsersTasks/>
</ProtectedRoute>
} />
......
......@@ -10,8 +10,8 @@ function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, descripti
if (title) {
const startHourInt = parseInt(startHour)
const endHourInt = parseInt(endHour)
if (startHourInt >= 8 && startHourInt <= 22) {
if (endHourInt >= 8 && endHourInt <= 22) {
if (startHourInt >= 8 && startHourInt <= 24) {
if (endHourInt >= 8 && endHourInt <= 24) {
if (startHourInt < endHourInt) {
return true
}
......
import { Grid } from "@mui/material";
import { memo, useEffect, useState } from "react";
import DefaultTask from "../MonthCalendar/MonthCalendarBody/DefaultTask/DefaultTask";
import DefaultTask from "../DefaultTask/DefaultTask";
......@@ -36,6 +36,11 @@ const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCell
setIsThisCell(true);
handleOpen(e)
}
if (week) {
createTaskInCellHandler(dayNumber, hours);
setIsThisCell(true);
handleOpen(e)
}
}
return <>
......@@ -48,7 +53,7 @@ const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCell
>
{children}
{isThisCell ?
<DefaultTask /> : null}
<DefaultTask week={week}/> : null}
</Grid>
</>
......
import { Box } from "@mui/material";
import { memo } from "react";
const DefaultTaskStyles = {
const MonthDefaultTaskStyles = {
position: 'relative',
height: '30px',
backgroundColor: 'lightgreen',
......@@ -16,12 +16,26 @@ const DefaultTaskStyles = {
paddingLeft: '5px',
zIndex: '5'
}
const WeekDefaultTaskStyles = {
boxSizing: 'border-box',
padding: '0 5px',
borderRadius: '2px',
border: '1px solid white',
backgroundColor:'lightgreen',
height: `100%`,
width: `100%`,
zIndex: 5,
textAlign: 'left',
overflow: 'hidden',
textOverflow: 'ellipsis',
}
const DefaultTask = ({ }) => {
const DefaultTask = ({ week }) => {
return (<>
<Box
sx={DefaultTaskStyles}
sx={week ? WeekDefaultTaskStyles : MonthDefaultTaskStyles}
>
<span>
Задача
......
import { Grid } from "@mui/material";
import React, { memo, useEffect, useState } from "react";
import DefaultTask from "../../DefaultTask/DefaultTask";
import DefaultTask from "../../../../DefaultTask/DefaultTask";
const EmptyBox = ({ hourNumber, handleOpen, dayNumber, xs, dragTaskHandler, modal, createTaskInCellHandler, copyTask, createCopyTask }) => {
......
import { useMemo } from "react";
import { getHoursInDayNumbers, getAvailableTasks, getLinesInDay, getSortedTasks } from "../../../../../helpers/CalendarHelpers";
import CalendarStandartCell from "../../../CalendarStandartCell/CalendarStandartCell";
import { useEffect, useRef, useState } from "react";
import { Grid } from "@mui/material";
import CalendarWeekTask from "./CalendarWeekTask/CalendarWeekTask";
function CalendarColumnDayWeek({ hoursInDay, tasks, month, year, day, hourFormat, handleOpen, setCurrentTask, copyTask, createCopyTask, createTaskInCellHandler, modal }) {
const [columnDayHeight, setColumnDayHeight] = useState(0)
const dayColumnRef = useRef('')
useEffect(() => {
setColumnDayHeight(prev => dayColumnRef.current.offsetHeight)
}, [hourFormat])
const hours = useMemo(() => {
return getHoursInDayNumbers(hoursInDay)
}, [hoursInDay])
const availableTasks = useMemo(() => {
return getAvailableTasks(tasks, year, month, day)
}, [tasks, month, year, day])
const sortedTasks = useMemo(() => {
return getSortedTasks(availableTasks)
}, [availableTasks])
const linesInDay = useMemo(() => {
return getLinesInDay(availableTasks, sortedTasks, hoursInDay, hours, hourFormat)
}, [availableTasks, hourFormat, hours, hoursInDay, sortedTasks])
const getBoxesInLine = (line, hoursInDay, sortedTasks, linesInDay) => {
if (line) {
const boxes = []
for (let i = 0; i < line.length; i++) {
if (!isNaN(line[i])) {
} else {
const task = sortedTasks[line[i].split('-')[1]]
const taskIsThere = boxes.find((taskFind) => {
if (taskFind?.task?.id === task.id) return taskFind
return false
})
const step = columnDayHeight / hours.length
if (taskIsThere) {
taskIsThere.lastHour = i
taskIsThere.height += step
let tasksInHour = 0
for (let line of linesInDay) {
if (isNaN(line[i])) {
tasksInHour++
}
}
if (tasksInHour > taskIsThere.tasksInHour) {
taskIsThere.tasksInHour = tasksInHour
}
} else {
let tasksInHour = 0
for (let line of linesInDay) {
if (isNaN(line[i])) {
tasksInHour++
}
}
boxes.push({
tasksInHour: tasksInHour,
top: step * i,
height: step,
firstHour: i,
lastHour: i,
task: sortedTasks[line[i].split('-')[1]]
})
}
}
}
return boxes
}
}
return (<>
<Grid item xs={12 / 7} ref={dayColumnRef} sx={{ position: 'relative' }}>
{linesInDay?.map((line, i) => {
const boxes = getBoxesInLine(line, hoursInDay, sortedTasks, linesInDay)
return (<>
{boxes.map((task, index) => {
const amount = task.tasksInHour
const oneTaskPrecentWidth = 100 / amount
const left = oneTaskPrecentWidth * dayColumnRef.current.offsetWidth / 100 * i
const zIndex = 10 + i
const oneTaskWidth = dayColumnRef.current.offsetWidth - (oneTaskPrecentWidth * dayColumnRef.current.offsetWidth / 100) * i
return (
<CalendarWeekTask
key={index}
width={oneTaskWidth}
height={task.height}
left={left}
task={task.task}
top={task.top}
zIndex={zIndex}
handleOpen={handleOpen}
setCurrentTask={setCurrentTask}
modal={modal}
>
</CalendarWeekTask>
)
})}
</>)
})}
{hoursInDay?.map((hour, i) => {
return (
<CalendarStandartCell
key={i}
week={true}
createTaskInCellHandler={createTaskInCellHandler}
handleOpen={handleOpen}
dayNumber={day}
hours={hour}
modal={modal}
>
</CalendarStandartCell>
)
})}
</Grid>
</>);
}
export default CalendarColumnDayWeek;
\ No newline at end of file
import { Box } from "@mui/material"
import { useEffect, useState } from "react"
function CalendarWeekTask({ height, width, left, top, task, zIndex, handleOpen, setCurrentTask, modal}) {
const [zIndexStyle, setZIndexStyle] = useState(10)
const [color, setColor] = useState('')
useEffect(() => {
if (task.priority) {
if (task.priority === 'A') setColor('rgb(32, 138, 250)')
if (task.priority === 'B') setColor('lightgreen')
if (task.priority === 'C') setColor('yellow')
} else {
setColor('rgb(171, 157, 157);')
}
setZIndexStyle(zIndex)
}, [task])
useEffect(() => {
if (!modal) {
setZIndexStyle(zIndex)
}
}, [modal])
const onClickTaskHandler = (e, task) => {
e.stopPropagation();
setCurrentTask((prevState) => {
return {
...task,
infoForCell: {
...task.infoForCell,
endHour: task.infoForCell.endHour + 1
}
}
});
setZIndexStyle(100)
handleOpen(e)
}
const styles = {
boxSizing: 'border-box',
borderRadius: '3px',
border: '1px solid white',
backgroundColor: color,
height: `${height - 1}px`,
width: `${width - 1}px`,
position: 'absolute',
left: left,
top: top,
zIndex: zIndexStyle,
textAlign: 'left',
overflow: 'hidden',
textOverflow: 'ellipsis',
'&:hover': {
cursor: 'pointer',
boxShadow: 'inset 0 0 100px 100px rgba(255, 255, 255, 0.3)'
},
}
return (
<Box
onClick={(e)=>{onClickTaskHandler(e, task)}}
sx={styles}>
<span style={{textOverflow: 'ellipsis', padding: '5px 0 0 5px'}}>
{task.title}
</span>
</Box>);
}
export default CalendarWeekTask;
\ No newline at end of file
import { useMemo } from "react";
import { getHoursInDayNumbers, getAvailableTasks, getLinesInDay, getSortedTasks } from "../../../../../helpers/CalendarHelpers";
import CalendarStandartCell from "../../../CalendarStandartCell/CalendarStandartCell";
function CalendarRowDayWeek({ hoursInDay, tasks, month, year, day, hourFormat }) {
const hours = useMemo(() => {
return getHoursInDayNumbers(hoursInDay)
}, [hoursInDay])
const availableTasks = useMemo(() => {
return getAvailableTasks(tasks, year, month, day)
}, [tasks, month, year, day])
const sortedTasks = useMemo(() => {
return getSortedTasks(availableTasks)
}, [availableTasks])
const linesInDay = useMemo(() => {
return getLinesInDay(availableTasks, sortedTasks, hoursInDay, hours, hourFormat)
}, [availableTasks, hourFormat, hours, hoursInDay, sortedTasks])
return (<>
{hoursInDay?.map((hour, i) => {
return (
<CalendarStandartCell key={i} week={true}>
</CalendarStandartCell>)
})}
</>);
}
export default CalendarRowDayWeek;
\ No newline at end of file
import { FormControlLabel, Grid, Switch } from "@mui/material";
import { Box } from "@mui/system";
import { useState } from "react";
import ModalTask from "../../../UI/ModalTask/ModalTask";
import MonthCalendarModalContent from "../../CalendarModalTaskContent/CalendarModalTaskContent";
import CalendarRow from "../../CalendarRow/CalendarRow";
import CalendarSmallCell from "../../CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "../../CalendarStandartCell/CalendarStandartCell";
import CalendarRowDayWeek from "./CalendarRowDayWeek/CalendarRowDayWeek";
import CalendarColumnDayWeek from "./CalendarColumnDayWeek/CalendarColumnDayWeek";
import { getCurrentWeekDayString } from "./Helpers";
function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, tasks }) {
function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, tasks, currentTask, setCurrentTask, onChangeCurrentTaskHandler, deleteTaskHandler, sendNewTaskHandler, createTaskInCellHandler }) {
const [modal, setModal] = useState({ open: false, y: 0, x: 0, });
const handleOpen = (e) => {
setModal({
open: true,
yClickСordinates: e.clientY,
xClickСordinates: e.clientX,
yDivClick: e.nativeEvent.offsetY,
xDivClick: e.nativeEvent.offsetX,
yDiv: e.target.offsetHeight,
xDiv: e.target.offsetWidth,
})
};
const handleClose = () => {
setModal({ ...modal, open: false })
setCurrentTask({})
};
return (
<>
......@@ -47,16 +67,19 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t
<CalendarRow week={true}>
{week?.map((weekDay, i) => {
return (
<Grid item key={i} xs={12 / week.length}>
<CalendarRowDayWeek
hoursInDay={hoursInDay}
tasks={tasks}
month={date.month}
year={date.year}
day={weekDay}
hourFormat={hourFormat}
/>
</Grid>
<CalendarColumnDayWeek
key={i}
hoursInDay={hoursInDay}
tasks={tasks}
month={date.month}
year={date.year}
day={weekDay}
hourFormat={hourFormat}
setCurrentTask={setCurrentTask}
handleOpen={handleOpen}
createTaskInCellHandler={createTaskInCellHandler}
modal={modal.open}
/>
)
})}
</CalendarRow>
......@@ -65,6 +88,23 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t
</CalendarRow>
</Grid>
</Box>
<ModalTask
modal={modal}
handleClose={() => { handleClose() }}
>
<MonthCalendarModalContent
title={currentTask.title}
description={currentTask.description}
priority={currentTask.priority}
id={currentTask.id}
startHour={currentTask.infoForCell?.startHour}
endHour={currentTask.infoForCell?.endHour}
onChangeCurrentTaskHandler={(e) => { onChangeCurrentTaskHandler(e) }}
sendNewTaskHandler={() => { sendNewTaskHandler(); handleClose() }}
deleteTaskHandler={() => { deleteTaskHandler(currentTask.id); handleClose() }}
/>
</ModalTask>
</>
);
}
......
import { Grid } from "@mui/material";
const CalendarRow = ({children, week}) => {
return <>
<Grid
container
align='center'
sx={{borderBottom: week ? null : '1px solid black', borderRight: '1px solid black', borderLeft: '1px solid black'}}
>
{children}
</Grid>
</>
};
export default CalendarRow;
import { Grid } from "@mui/material";
import { memo, useMemo} from "react";
import CalendarStandartCell from "../CalendarStandartCell.js/CalendarStandartCell";
import CalendarTask from "../CalendarTask/CalendarTask";
import EmptyBox from "./EmptyBox/EmptyBox";
import { getAvailableTasks, getBoxesInLine, getLinesInDay, getSortedTasks } from "./Helpers";
const CalendarRowDay = ({xs, hoursInDay, createTaskInCellHandler, currentTask, handleOpen, modal, setCurrentTask, year, month, tasks, day, hourFormat, setCurrentLine, currentLine, dragTaskHandler, createCopyTask, setCopyTask, copyTask}) => {
const hours = useMemo(()=>{
return hoursInDay.map((hour)=>parseInt(hour.split(':')[0]))},
[hoursInDay])
const availableTasks = useMemo(() => {
return getAvailableTasks(tasks, year, month, day.dayNumber)
}, [tasks, month, year, day.dayNumber])
const sortedTasks = useMemo(() => {
return getSortedTasks(availableTasks)
}, [availableTasks])
const linesInDay = useMemo(() => {
return getLinesInDay(availableTasks, sortedTasks, hoursInDay, hours, hourFormat)
}, [availableTasks, hourFormat, hours, hoursInDay, sortedTasks])
return <>
<Grid
container
item
xs={10.8}
align='center'
sx={{position: 'relative'}}
>
{hoursInDay.map((hour, i)=>{
return (
<CalendarStandartCell
linesInDay={linesInDay}
key={i}
item xs={xs}
createTaskInCellHandler={createTaskInCellHandler}
hours={hour}
dragTaskHandler={dragTaskHandler}
dayNumber={day.dayNumber}
currentTask={currentTask}
handleOpen={handleOpen}
modal={modal}
>
</CalendarStandartCell>
)
})}
<Grid sx={{position: 'absolute', top: '0'}} container item xs={12}>
{linesInDay?.map((line, i)=>{
const boxes = getBoxesInLine(line, hoursInDay, sortedTasks)
return(
<Grid key={i} container sx={{height: '35px', backgroundColor: 'rgb(0,0,0,0)', marginBottom: '5px'}}>
{boxes.map((box, index)=>{
if (box.task) {
return (<Grid
item xs={box.xs}
key={box.task.id}
sx={{height: '35px', marginBottom: '5px'}}
>
<CalendarTask
dragTaskHandler={dragTaskHandler}
setCurrentLine={()=>{setCurrentLine(day.dayNumber)}}
currentTask={currentTask}
currentLine={currentLine}
hour={parseInt(hours[index])}
line={day.dayNumber}
task={box.task}
setCurrentTask={setCurrentTask}
handleOpen={handleOpen}
setCopyTask={setCopyTask}
/>
</Grid>)
} else {
return (<EmptyBox
key={index}
modal={modal}
dayNumber={day.dayNumber}
hourNumber={box.hour}
handleOpen={handleOpen}
dragTaskHandler={dragTaskHandler}
createCopyTask={createCopyTask}
copyTask={copyTask}
createTaskInCellHandler={createTaskInCellHandler}
xs={box.xs}
>
</EmptyBox>)
}
})}
</Grid>)
})}
</Grid>
<Grid container sx={{height: '35px', backgroundColor: 'rgb(0,0,0,0)', marginBottom: '5px', position: 'absolute', bottom: '0'}}>
{hoursInDay.map((hour, i)=>{
const hourNumber = parseInt(hour)
return(<EmptyBox
key={i}
modal={modal}
dayNumber={day.dayNumber}
hourNumber={hourNumber}
handleOpen={handleOpen}
dragTaskHandler={dragTaskHandler}
createCopyTask={createCopyTask}
copyTask={copyTask}
createTaskInCellHandler={createTaskInCellHandler}
xs={xs}
>
</EmptyBox>)
})}
</Grid>
</Grid>
</>
};
export default memo(CalendarRowDay, (prevProps, nextProps)=>{
if(!prevProps.modal) return false
if(nextProps.modal) return true
});
import { Grid} from "@mui/material";
import React, { memo, useEffect, useState} from "react";
import DefaultTask from "../../DefaultTask/DefaultTask";
const EmptyBox = ({hourNumber, handleOpen, dayNumber, xs, dragTaskHandler, modal, createTaskInCellHandler, copyTask, createCopyTask}) => {
const [isThisCell, setIsThisCell] = useState(false)
useEffect(()=>{
if(!modal) {
setIsThisCell(false);
}
}, [modal])
const onClickHandler = (e, dayNumber, hour) => {
if (copyTask) {
createCopyTask(dayNumber, hour)
} else {
createTaskInCellHandler(dayNumber, hour);
setIsThisCell(true);
handleOpen(e)
}
}
const dragOverHandler = (e) => {
e.preventDefault();
}
const dropHandler = (e) => {
e.stopPropagation()
e.preventDefault();
dragTaskHandler(dayNumber, hourNumber)
}
return(<Grid
onDragOver={(e)=>{dragOverHandler(e)}}
onDrop={(e)=>{dropHandler(e)}}
onClick={(e)=>{onClickHandler(e, dayNumber, hourNumber)}}
className='test_empty_box'
item xs={xs} sx={{
height: '40px',
backgroundColor: 'rgb(0,0,0,0)',
zIndex: '6',
cursor: copyTask ? 'pointer' : 'default'
}}>
{isThisCell ?
<DefaultTask/> : ' '}
</Grid>)
};
export default memo(EmptyBox, (prevProps, nextProps)=>{
if(!prevProps.modal) return false
if(nextProps.modal) return true
});
\ No newline at end of file
const taskIsAvailableInCell = (task, hour, hourDiffEnd, hourDiff, hourFormat) => {
if (((task.infoForCell.endHour <= hour || task.infoForCell.startHour <= hour) && (task.infoForCell.endHour > hour))
|| (!hourFormat && task.infoForCell.startHour >= hour && task.infoForCell.endHour < hour + hourDiff)
|| (!hourFormat && task.infoForCell.startHour === hour + hourDiffEnd && task.infoForCell.endHour > hour)
|| (task.infoForCell.endMinute <= 59 && task.infoForCell.endHour === hour)) {
return true
} else {
return false
}
}
const lastPlaceInLineForTask = (task, hour, hourDiffEnd, hourFormat) => {
if ((task.infoForCell.endMinute === 59 && task.infoForCell.endHour === hour + hourDiffEnd) || (!hourFormat && task.infoForCell.endMinute === 59 && task.infoForCell.endHour === hour)) {
return true
} else {
return false
}
}
export const getLinesInDay = (availableTasks, sortedTasks, hoursInDay, hours, hourFormat) => {
let hourDiff
let hourDiffEnd
const lines = []
if (hourFormat) {
hourDiff = 1
hourDiffEnd = 0
} else {
hourDiff = 2
hourDiffEnd = 1
}
if (availableTasks.length) {
lines.push(hoursInDay.map((hour)=>parseInt(hour.split(':')[0])))
for (let k = 0; k < sortedTasks.length; k++) {
let skipLine = false
for (let j = 0; j < lines.length; j++) {
const line = lines[j]
const task = sortedTasks[k]
if (skipLine) {
skipLine = false
break;
}
for (let i = 0; i < line.length; i++) {
const hour = hours[i]
let havePlace = true
if (taskIsAvailableInCell(task, hour, hourDiffEnd, hourDiff, hourFormat)) {
if (!isNaN(line[i])) {
for (let a = 0; a < hours.length; a++) {
const hour = hours[a]
if (lastPlaceInLineForTask(task, hour, hourDiffEnd, hourFormat)) {
if (isNaN(line[a])) {
havePlace = false
break;
}
}
}
if (!havePlace) {
if (j + 1 === lines.length) {
lines.push(hoursInDay.map((hour)=>parseInt(hour.split(':')[0])))
}
havePlace = true
break;
}
line[i] += `-${k}`
if (lastPlaceInLineForTask(task, hour, hourDiffEnd, hourFormat)) {
skipLine = true
break;
}
} else {
if (j + 1 === lines.length) {
lines.push(hoursInDay.map((hour)=>parseInt(hour.split(':')[0])))
}
break;
}
}
}
}
}
}
return lines
}
export const getSortedTasks = (availableTasks) => {
if (availableTasks.length) {
const newSortedArr = [...availableTasks].sort(function(a,b){
const durattionFirstDate = a.infoForCell.endHour - a.infoForCell.startHour
const durattionSecondDate = b.infoForCell.endHour - b.infoForCell.startHour
return durattionSecondDate - durattionFirstDate;
})
return newSortedArr
}
}
export const getAvailableTasks = (tasks, year, month, dayNumber) => {
const tasksInDay = tasks.filter((task)=> {
if (year === task.infoForCell.startYear) {
if (month + 1 === task.infoForCell.startMonth) {
if (dayNumber === task.infoForCell.startDay) {
return task
} else {return false}
} else {return false}
} else {return false}
})
return tasksInDay
}
export const getBoxesInLine = (line, hoursInDay, sortedTasks) => {
if (line) {
let xs = 12/hoursInDay.length
const boxes = []
for (let i = 0; i < line.length; i++) {
if (!isNaN(line[i])) {
// if (boxes[boxes.length -1]?.task === null) {
// boxes[boxes.length -1].xs += xs
// } else {
boxes.push({xs: xs, task: null, hour: line[i]})
// }
} else {
const task = sortedTasks[line[i].split('-')[1]]
const taskIsThere = boxes.find((taskFind)=>{
if (taskFind?.task?.id === task.id) return taskFind
return false
})
if (taskIsThere) {
taskIsThere.xs +=xs
} else {
boxes.push({
xs: xs,
task: sortedTasks[line[i].split('-')[1]]})
}
}
}
return boxes
}
}
\ No newline at end of file
import { Grid } from "@mui/material";
import { memo } from "react";
const CalendarSmallCell = ({children, xs, week}) => {
return <>
<Grid align='center' item xs={xs} sx={{borderRight: week ? null : '1px solid black', height: week ? '40px' : null, borderBottom: week ? '1px solid black' : null,}}>
{children}
</Grid>
</>
};
export default memo(CalendarSmallCell);
\ No newline at end of file
import { Grid} from "@mui/material";
import { memo, useEffect, useState } from "react";
import DefaultTask from "../DefaultTask/DefaultTask";
const CalendarStandartCell = ({children, xs, hours, dayNumber, createTaskInCellHandler, handleOpen, modal, dragTaskHandler, linesInDay, week}) => {
const [isThisCell, setIsThisCell] = useState(false)
const cellClass = {
position: 'relative',
height: linesInDay?.length ? `${40*linesInDay.length+35}px` : `${40}px`,
borderRight: '1px solid black',
borderBottom: week ?'1px solid black' : null,
}
useEffect(()=>{
if(!modal) {
setIsThisCell(false);
}
}, [modal])
const dragOverHandler = (e) => {
e.preventDefault();
}
const dropHandler = (e) => {
e.stopPropagation()
e.preventDefault();
dragTaskHandler(dayNumber, parseInt(hours.split(':')[0]))
}
const onClickHandler = (e) => {
if (linesInDay?.length) {
createTaskInCellHandler(dayNumber, hours);
setIsThisCell(true);
handleOpen(e)
}
}
return <>
<Grid
item xs={xs}
sx={cellClass}
onClick={(e)=>{onClickHandler(e)}}
onDragOver={(e)=>{dragOverHandler(e)}}
onDrop={(e)=>{dropHandler(e)}}
>
{children}
{isThisCell ?
<DefaultTask/> : null}
</Grid>
</>
};
export default memo(CalendarStandartCell, (prevProps, nextProps)=>{
if(!prevProps.modal) return false
if(nextProps.modal) return true
});
\ No newline at end of file
import { Grid} from "@mui/material";
import React, { memo, useEffect, useState} from "react";
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
const CalendarTask = ({setCurrentTask, handleOpen, task, line, setCurrentLine, setCopyTask}) => {
const [color, setColor] = useState('')
useEffect(() => {
if (task.priority) {
if (task.priority === 'A') setColor('rgb(32, 138, 250)')
if (task.priority === 'B') setColor('lightgreen')
if (task.priority === 'C') setColor('yellow')
} else {
setColor('rgb(171, 157, 157);')
}
}, [task])
const onClickTaskHandler = (e, task) => {
e.stopPropagation();
setCurrentTask((prevState)=>{
return {
...task,
infoForCell: {
...task.infoForCell,
endHour: task.infoForCell.endHour + 1
}
}
});
handleOpen(e)
}
const dragLeaveHandler = (e) => {
e.target.style.boxShadow = 'none'
}
const dragStartHandler = (e, line, task) => {
setCurrentLine()
setCurrentTask(task);
}
const dragEndHandler = (e) => {
e.target.style.boxShadow = 'none'
}
return (<>
<Grid
draggable={true}
onDragLeave={(e)=>{dragLeaveHandler(e)}}
onDragStart={(e)=>{dragStartHandler(e, line, task)}}
onDragEnd={(e)=>{dragEndHandler(e)}}
sx={{ position: 'relative', height: '30px', backgroundColor: color, borderRadius: '10px', margin: '5px 10px', display: 'flex', alignItems: 'center', zIndex: '5', justifyContent: 'space-between', padding: '0 15px'}}
onClick={(e)=>{onClickTaskHandler(e, task)}}
>
<span style={{maxWidth: '60%', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>
{task.title}
</span>
<ContentCopyIcon sx={{width: '20px', cursor: 'pointer'}} onClick={(e)=>{e.stopPropagation(); setCopyTask(task)}}>
</ContentCopyIcon>
</Grid>
</>)
};
export default memo(CalendarTask);
\ No newline at end of file
import { Box } from "@mui/material";
import { memo } from "react";
const DefaultTaskStyles = {
position: 'relative',
height: '30px',
backgroundColor: 'lightgreen',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
borderRadius: '10px',
margin: '5px 10px',
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'center',
paddingLeft: '5px',
zIndex: '5'
}
const DefaultTask = ({}) => {
return (<>
<Box
sx={DefaultTaskStyles}
>
<span>
Задача
</span>
</Box>
</>)
};
export default memo(DefaultTask);
\ No newline at end of file
import { Box, FormControlLabel, Switch} from "@mui/material";
import { useState } from "react";
import CalendarRow from "./CalendarRow/CalendarRow";
import CalendarSmallCell from "./CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "./CalendarStandartCell.js/CalendarStandartCell";
import ModalTask from "../../UI/ModalTask/ModalTask";
import MonthCalendarModalContent from "../MonthCalendarModalContent/MonthCalendarModalContent";
import CalendarRowDay from "./CalendarRowDay/CalendarRowDay";
function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, currentTask, setCurrentTask, hourFormat, setHourFormat, onChangeCurrentTaskHandler, sendNewTaskHandler, deleteTaskHandler, cellSizes, hoursInDay, daysInMonth, dragTaskHandler, createCopyTask, setCopyTask, copyTask}) {
const [currentLine, setCurrentLine] = useState('')
const [modal, setModal] = useState({open:false, y: 0, x: 0,});
const handleOpen = (e) => {
setModal( {
open: true,
yClickСordinates: e.clientY,
xClickСordinates: e.clientX,
yDivClick: e.nativeEvent.offsetY,
xDivClick: e.nativeEvent.offsetX,
yDiv: e.target.offsetHeight,
xDiv: e.target.offsetWidth,
})
};
const handleClose = () => {
setModal({...modal, open: false})
setCurrentTask({})
};
return (
<Box style={{marginBottom: '30px'}}>
<div style={{position: 'sticky', top: '0px', zIndex: '10', backgroundColor: 'lightgrey'}}>
<CalendarRow
>
<CalendarSmallCell xs={1.2}>
<FormControlLabel
control={<Switch color="primary" checked={hourFormat} onChange={()=>{setHourFormat(()=>!hourFormat)}}/>}
label="1 час"
labelPlacement="end"
/>
</CalendarSmallCell>
{hoursInDay?.map((hours, i)=>{
return (
<CalendarStandartCell key={i} xs={cellSizes.standarCell}>
{hours}
</CalendarStandartCell>
)
})}
</CalendarRow>
</div>
{daysInMonth?.map((day, i)=>{
return (
<CalendarRow
key={i}
>
<CalendarSmallCell xs={cellSizes.smallCell}>{day.dayNumber}</CalendarSmallCell>
<CalendarSmallCell xs={cellSizes.smallCell}>{day.dayOfWeek}</CalendarSmallCell>
<CalendarRowDay
dragTaskHandler={dragTaskHandler}
xs={cellSizes.dayCell}
createTaskInCellHandler={createTaskInCellHandler}
hoursInDay={hoursInDay}
currentTask={currentTask}
handleOpen={handleOpen}
currentLine={currentLine}
setCurrentLine={setCurrentLine}
modal={modal.open}
setCurrentTask={setCurrentTask}
year={year}
month={month}
tasks={tasks}
day={day}
hourFormat={hourFormat}
createCopyTask={createCopyTask}
copyTask={copyTask}
setCopyTask={setCopyTask}
>
</CalendarRowDay>
</CalendarRow>
)
})}
<ModalTask
modal={modal}
handleClose={()=>{handleClose()}}
>
<MonthCalendarModalContent
title={currentTask.title}
description={currentTask.description}
priority={currentTask.priority}
startHour={currentTask.infoForCell?.startHour}
endHour={currentTask.infoForCell?.endHour}
onChangeCurrentTaskHandler={(e)=>{ onChangeCurrentTaskHandler(e)}}
sendNewTaskHandler={()=>{sendNewTaskHandler(); handleClose()}}
deleteTaskHandler={()=>{deleteTaskHandler(currentTask.id); handleClose()}}
/>
</ModalTask>
</Box>
);
}
export default MonthCalendarBody;
\ No newline at end of file
import { Box, Typography } from '@mui/material';
import { memo } from 'react';
import ArrowDecrementButton from '../../../UI/ArrowDecrementButton/ArrowDecrementButton';
import ArrowIncrementButton from '../../../UI/ArrowIncrementButton/ArrowIncrementButton';
function MonthAndYearInfo({currentMonthString, year, incrementMonth, decrementMonth}) {
return (
<>
<Box
sx={{
flexGrow: 1,
display: 'flex',
alignItems: 'center',
gap: '10px'
}}
id='test_month_info'
>
<ArrowDecrementButton
onClick={decrementMonth}
/>
<Box sx={{ flexBasis: '150px' }}>
<Typography
variant="h6"
sx={{
display: 'flex',
justifyContent: 'center',
}}
>
{currentMonthString}
</Typography>
<Typography align='center'>{year}</Typography>
</Box>
<ArrowIncrementButton
onClick={incrementMonth}
/>
</Box>
</> );
}
export default memo(MonthAndYearInfo);
\ No newline at end of file
import { AppBar, Toolbar} from '@mui/material';
import { Box } from '@mui/system';
import MonthAndYearInfo from './MonthAndYearInfo/MonthAndYearInfo';
import СustomSelect from '../../UI/СustomSelect/СustomSelect'
const workers = [{value: '', text: '--выберите сотрудника--'}, {value: 'Василий', text: 'Василий'}, {value: 'Никита', text: 'Никита'}]
const types = [{value: 'Месяц', text: 'Месяц'}, {value: 'Неделя', text: 'Неделя'}]
function MonthCalendarHeader({ currentMonthString, decrementMonth, incrementMonth, calendarType, onChangeWorkerHandler, onChangeCalendarTypeHandler, worker, year}) {
return (
<>
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<MonthAndYearInfo
currentMonthString={currentMonthString}
decrementMonth={decrementMonth}
incrementMonth={incrementMonth}
year={year}
/>
<СustomSelect
value={worker}
onChange={(e)=>{onChangeWorkerHandler(e)}}
label={'Сотрудник'}
id={'worker'}
items={workers}
/>
<div style={{marginLeft: '20px'}}>
<СustomSelect
value={calendarType}
onChange={(e)=>{onChangeCalendarTypeHandler(e)}}
label={'Календарь'}
id={'calendar-type'}
items={types}
/>
</div>
</Toolbar>
</AppBar>
</Box>
</>
);
}
export default MonthCalendarHeader;
\ No newline at end of file
import { Button, TextField } from "@mui/material";
import { memo } from "react";
import CustomSelect from '../../UI/СustomSelect/СustomSelect'
const priorities = [{value: null, text: '--Приоритет--'}, {value: 'A', text: 'A'}, {value: 'B', text: 'B'}, {value: 'C', text: 'C'}]
function MonthCalendarModalContent({title, onChangeCurrentTaskHandler, description, priority, sendNewTaskHandler, deleteTaskHandler, startHour, endHour}) {
return (<>
<TextField
id="task-description-title"
value={title}
label="Название"
variant="outlined"
sx={{marginBottom: '30px'}}
name='title'
onChange={(e)=>{onChangeCurrentTaskHandler(e)}}
/>
<TextField
id="task-description"
multiline
rows={4}
value={description}
label="Описание"
variant="outlined"
sx={{marginBottom: '30px'}}
name='description'
onChange={(e)=>{onChangeCurrentTaskHandler(e)}}
/>
<CustomSelect
defaultValue={null}
value={priority}
name={'priority'}
variant={'outlined'}
onChange={(e)=>{onChangeCurrentTaskHandler(e)}}
label={'Приоритет'}
id={'priority-type'}
items={priorities}
/>
<div style={{display: 'flex', gap: '20px', margin: '20px 0'}}>
<TextField
id="task-startHour"
value={startHour}
label="От"
variant="outlined"
name='startHour'
onChange={(e)=>{onChangeCurrentTaskHandler(e)}}
/>
<TextField
id="task-endHour"
value={endHour}
label="До"
variant="outlined"
name='endHour'
onChange={(e)=>{onChangeCurrentTaskHandler(e)}}
/>
</div>
<div style={{display: 'flex', gap: '20px', margin: '10px 0'}}>
<Button id='test_button_save_task'onClick={sendNewTaskHandler}>Сохранить</Button>
<Button onClick={deleteTaskHandler}>Удалить</Button>
</div>
</>);
}
export default memo(MonthCalendarModalContent);
\ No newline at end of file
......@@ -12,13 +12,18 @@ const CustomTableCell = ({
onModalOpen,
placeholder,
user,
width,
}) => {
const styles = placeholder ? { width: "100%" } : { width: "auto" };
const styles = { width: width, padding: "1px 16px 1px 1px" };
const inputStyles = placeholder
? { width: "100%", padding: "1px" }
: { padding: "1px" };
const divStyle = {
display: "flex",
justifyContent: "space-between",
flexDirection: "column",
fontSize: "12px",
fontSize: "12px",
};
const duration = moment.duration(
......@@ -34,7 +39,7 @@ const CustomTableCell = ({
<TableCell
onClick={(e) => (onModalOpen ? onModalOpen(e, task) : null)}
align="left"
// style={styles}
style={styles}
>
{(task.isEditMode &&
onChange &&
......@@ -46,7 +51,7 @@ const CustomTableCell = ({
value={value}
name={name}
onChange={(e) => onChange(e, task)}
style={styles}
style={inputStyles}
/>
) : name !== "dateTimeStart" ? (
<span>{value}</span>
......
......@@ -21,10 +21,7 @@ import BasicSelect from "../UI/Select/Select";
import { addTask } from "../../store/actions/tasksActions";
import TaskModal from "./TaskModal/TaskModal";
export default function NewTaskForm({
projects,
setAddTaskForm,
}) {
export default function NewTaskForm({ projects, setAddTaskForm }) {
const dispatch = useDispatch();
const user = useSelector((state) => state.users.user);
const currentDateTime = new Date();
......@@ -103,8 +100,9 @@ export default function NewTaskForm({
{header.map((headCell) => (
<TableCell
key={headCell.id}
align="center"
align="left"
padding={headCell.disablePadding ? "none" : "normal"}
style={{ paddingLeft: "0" }}
>
{headCell.label}
</TableCell>
......@@ -113,9 +111,9 @@ export default function NewTaskForm({
</TableHead>
<TableBody>
<TableRow hover key={task.id}>
<TableCell component="th" scope="row" padding="none"></TableCell>
<TableCell>
<TableRow hover key={task.id} style={{ paddingLeft: "40px" }}>
<TableCell style={{ width: "40px", padding: "0" }}></TableCell>
<TableCell style={{ width: "8%", paddingLeft: "0" }}>
<BasicSelect
items={[
{ value: "A", title: "A" },
......@@ -134,8 +132,10 @@ export default function NewTaskForm({
task,
name: "createdAt",
value: moment(task.createdAt).format("DD-MM-YYYY hh:mm A"),
width: "15%",
}}
/>
<CustomTableCell
{...{
task,
......@@ -143,11 +143,12 @@ export default function NewTaskForm({
value: task.title,
onModalOpen,
user: user,
placeholder: "Кликните для ввода информации по задаче"
placeholder: "Кликните для ввода информации по задаче",
width: "auto",
}}
/>
<TableCell>
<TableCell style={{ width: "15%", paddingLeft: "0" }}>
<BasicSelect
items={projects.map((e) => ({
value: e?.id,
......@@ -168,7 +169,7 @@ export default function NewTaskForm({
/>
</TableCell> */}
<TableCell>
<TableCell style={{ width: "20%", paddingLeft: "0" }}>
<MaterialUIPickers
task={task}
name="dateTimeDeadLine"
......@@ -176,7 +177,7 @@ export default function NewTaskForm({
/>
</TableCell>
<TableCell>
<TableCell style={{ width: "5%" }}>
<Tooltip title="Добавить">
<IconButton size="large" onClick={handleAddTask}>
<AddBox fontSize="large" />
......@@ -184,16 +185,15 @@ export default function NewTaskForm({
</Tooltip>
</TableCell>
</TableRow>
</TableBody>
</Table>
<TaskModal
task={task}
open={modal}
handleClose={handleClose}
onChange={onChange}
user={user}
/>
task={task}
open={modal}
handleClose={handleClose}
onChange={onChange}
user={user}
/>
</TableContainer>
<Divider />
</>
......
......@@ -31,10 +31,10 @@ const TableRowTask= ({
deleteHandle,
handleEditTask,
deleteDateTimeTask,
// handleEditDateTimeTask,
onChange,
onModalOpen,
onProjectChange,
onExecutorChange,
uniqueProjects,
onAuthorChange,
onDateChange,
......@@ -144,6 +144,10 @@ const TableRowTask= ({
/>
)}
<CustomTableCell
{...{
task,
......
......@@ -23,7 +23,6 @@ export default function ModalTask({modal, handleClose, children}) {
window.removeEventListener('resize', detectSize)
}
}, [windowDimenion])
const modalRef = useRef('')
const getYCordinatesToModal = () => {
......@@ -63,7 +62,7 @@ export default function ModalTask({modal, handleClose, children}) {
aria-describedby="modal-modal-description"
BackdropProps={{ style: { backgroundColor: 'rgba(255,255,255, 0)' } }}
>
<Box sx={style} ref={modalRef}>
<Box sx={style}>
{children}
</Box>
</Modal>
......
import * as React from "react";
import TableCell from "@mui/material/TableCell";
import Input from "@mui/material/Input";
import moment from "moment";
const CustomTableCell = ({
task,
name,
value,
value2,
onChange,
onModalOpen,
placeholder,
user,
}) => {
const styles = placeholder ? { width: "100%" } : { width: "auto" };
const divStyle = {
display: "flex",
justifyContent: "space-between",
flexDirection: "column",
fontSize: "12px",
};
const duration = moment.duration(
moment(task?.dateTimeTasks[0]?.dateTimeDue).diff(
moment(task?.dateTimeTasks[0]?.dateTimeStart)
)
);
const hours = Math.round(duration.asHours());
if (task) {
return (
<>
<TableCell
onClick={(e) => (onModalOpen ? onModalOpen(e, task) : null)}
align="left"
// style={styles}
>
{(task.isEditMode &&
onChange &&
name !== "author" &&
task.author?.id === user?.id) ||
placeholder ? (
<Input
placeholder={placeholder}
value={value}
name={name}
onChange={(e) => onChange(e, task)}
style={styles}
/>
) : name !== "dateTimeStart" ? (
<span>{value}</span>
) : (
<div style={divStyle}>
<span>{value}</span>
<span>{value2}</span>
<span>часы:{hours}</span>
</div>
)}
</TableCell>
</>
);
}
};
export default CustomTableCell;
import * as React from "react";
import TextField from "@mui/material/TextField";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
export default function MaterialUIPickers(props) {
return (
<LocalizationProvider
dateAdapter={AdapterMoment}
sx={{ width: "100%", fontSize: 5, fontWeight: "200" }}
>
<DateTimePicker
inputFormat="DD-MM-YY kk:mm A"
disabled={props.task.readOnly}
renderInput={(params) => (
<TextField
{...params}
sx={{ width: "auto", fontWeight: "200", fontSize: 5 }}
name={props.name}
/>
)}
value={props.task[props.name]}
onChange={(newValue) => {
props.onChange(props.task.id, newValue, props.name);
}}
/>
</LocalizationProvider>
);
}
import * as React from "react";
import {
Table,
TableBody,
TableCell,
TableContainer,
TableRow,
TableHead,
IconButton,
Tooltip,
Typography,
Divider,
} from "@mui/material";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AddBox } from "@mui/icons-material";
import moment from "moment";
import CustomTableCell from "./CustomTableCell";
import MaterialUIPickers from "./DateTimePicker/DateTimePicker";
import BasicSelect from "../UI/Select/Select";
import { addTask } from "../../store/actions/tasksActions";
import TaskModal from "./TaskModal/TaskModal";
export default function NewTaskForm({
projects,
currentProject,
setAddTaskForm,
}) {
const dispatch = useDispatch();
const user = useSelector((state) => state.users.user);
const currentDateTime = new Date();
const dateTime = moment(currentDateTime).utc().format();
const [task, setTask] = useState({
id: 0,
title: "",
description: "",
createdAt: dateTime,
dateTimeStart: null,
dateTimeDeadLine: null,
dateTimeTasks: [],
dateTimeDue: null,
project: projects[0],
accomplish: "opened",
priority: "B",
author: { id: user.id },
authorDisplayName: user.displayName,
executor:null,
isEditMode: true,
});
const [modal, setModal] = useState(false);
const onModalOpen = (event, task) => {
event.stopPropagation();
setModal(true);
};
const handleClose = () => {
setModal(false);
};
const onChange = (e, task) => {
const value = e.target.value;
const name = e.target.name;
const newTask = { ...task, [name]: value };
setTask(newTask);
};
const onProjectChange = (e, task) => {
const value = e.target.value;
const project = projects.find((e) => e.id === value);
const newTask = { ...task };
newTask.project = project;
setTask(newTask);
};
const onExecutorChange = (e, task) => {
const value = e.target.value;
const executor = projects.find((e) => e.id === value);
const newTask = { ...task };
newTask.executor = executor;
setTask(newTask);
};
const onDateChange = (id, value, property) => {
const newTask = {
...task,
[property]: moment.parseZone(value, "DD/MM/YYYY", true).format(),
};
setTask(newTask);
};
const handleAddTask = () => {
dispatch(addTask(task));
setAddTaskForm();
};
return (
<>
<Divider>
<Typography variant="overline">Добавить новую задачу</Typography>
</Divider>
<TableContainer
style={{
backgroundColor: "#E8E8E8",
marginBottom: "2em",
}}
>
<Table sx={{ minWidth: 600 }} aria-labelledby="tableTitle">
<TableHead>
<TableRow>
{header.map((headCell) => (
<TableCell
key={headCell.id}
align="center"
padding={headCell.disablePadding ? "none" : "normal"}
>
{headCell.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
<TableRow hover key={task.id}>
<TableCell component="th" scope="row" padding="none"></TableCell>
<TableCell>
<BasicSelect
items={[
{ value: "A", title: "A" },
{ value: "B", title: "B" },
{ value: "C", title: "C" },
]}
task={task}
value={task.priority}
onChange={onChange}
name="priority"
/>
</TableCell>
<CustomTableCell
{...{
task,
name: "createdAt",
value: moment(task.createdAt).format("DD-MM-YYYY hh:mm A"),
}}
/>
<CustomTableCell
{...{
task,
name: "title",
value: task.title,
onModalOpen,
user: user,
placeholder: "Кликните для ввода информации по задаче"
}}
/>
<TableCell>
<BasicSelect
items={projects.map((e) => ({
value: e?.id,
title: e?.title,
}))}
task={task}
onChange={onProjectChange}
name="project"
value={task.project?.id}
/>
</TableCell>
<TableCell>
<BasicSelect
items={currentProject.members.map((member) => ({
value: member?.id,
title: member?.displayName,
}))}
task={task}
onChange={onExecutorChange}
name="executor"
value={task.executor?.id}
/>
</TableCell>
{/* <TableCell>
<MaterialUIPickers
task={task}
name="dateTimeStart"
onChange={onDateChange}
/>
</TableCell> */}
<TableCell>
<MaterialUIPickers
task={task}
name="dateTimeDeadLine"
onChange={onDateChange}
/>
</TableCell>
<TableCell>
<Tooltip title="Добавить">
<IconButton size="large" onClick={handleAddTask}>
<AddBox fontSize="large" />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
</TableBody>
</Table>
<TaskModal
task={task}
open={modal}
handleClose={handleClose}
onChange={onChange}
user={user}
/>
</TableContainer>
<Divider />
</>
);
}
export const header = [
{
id: "id",
numeric: true,
disablePadding: true,
label: "",
},
{
id: "priority",
numeric: false,
disablePadding: true,
label: "Приоритет",
},
{
id: "createdAt",
numeric: true,
disablePadding: false,
label: "Дата создания",
},
{
id: "title",
numeric: false,
disablePadding: false,
label: "Заголовок",
},
{
id: "projectName",
numeric: true,
disablePadding: false,
label: "Проект",
},
{
id: "executorName",
numeric: false,
disablePadding: false,
label: "Исполнитель",
},
{
id: "dateTimeDue",
numeric: true,
disablePadding: false,
label: "Дедлайн",
},
{
id: "add",
numeric: false,
disablePadding: false,
label: "",
},
];
.modal{
display: flex;
flex-direction: column;
padding: 10px;
align-items: center;
position: absolute;
top: 200px;
left: 200px;
width: 300px;
height: 300px;
background-color: white;
border: 2px solid #000;
box-shadow: 24px;
border-radius:5px
}
.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";
import { Done } from "@mui/icons-material";
import Input from "@mui/material/Input";
import TextField from "@mui/material/Input";
const TaskModal = ({handleClose,open,task,onChange,user }) => {
return (
<Modal
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
BackdropProps={{ style: { backgroundColor: 'rgba(255,255,255, 0)' } }}
closeAfterTransition
onClose={handleClose}
open={open}
>
{task?.isEditMode && task.author.id===user.id ? (
<div className="modal">
<Input
label="название"
color="secondary"
value={task.title}
name="title"
onChange={(e) => onChange(e, task)}
style={{
width: "auto",
fontWeight: "600",
height: "40px",
fontWeight: "600",
width:"280px",
margin:"10px",
padding:"5px",
border: '2px solid #D3D3D3',
borderRadius:"5px"
}}
/>
<TextField
label="описание"
value={task.description}
name="description"
onChange={(e) => onChange(e, task)}
multiline={true}
sx={{
fontWeight: "400",
width:"280px",
margin:"10px",
padding:"5px",
border: '2px solid #D3D3D3',
borderRadius:"5px",
height:"300px",
whiteSpace:"normal"
}}
/>
<IconButton aria-label="done" onClick={handleClose}
sx={{margingBottom:"5px",marginTop:"auto"}}>
<Done />
</IconButton>
</div>
) : (
<div className="modal">
{task && task.title && (
<div
style={{
height: "40px",
fontWeight: "600",
width:"280px",
margin:"10px",
padding:"5px",
border: '2px solid #D3D3D3',
borderRadius:"5px"
}}
>
{task.title}
</div>
)}
{task && task.description && (
<div
style={{margin:"10px",
border: '2px solid #D3D3D3',
borderRadius:"5px",
width:"280px",
height: "200px",
margin:"10px",
padding:"5px",
}}>
{task.description}
</div>
)}
<IconButton
aria-label="close"
onClick={handleClose}
sx={{margingBottom:"5px",marginTop:"auto"}}
>
X
</IconButton>
</div>
)}
</Modal>
);
};
export default TaskModal;
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 MultipleSelect from '../UI/MultipleSelect/MultipleSelect';
import Add from "@mui/icons-material/Add";
import Close from "@mui/icons-material/Close";
export default function MyTaskToolBar({projects,onClose,projectName,setProjectName,formStatus,onClick}) {
let projectsFilter =
<></>
if (projects) {
projectsFilter=
<MultipleSelect
projects={projects}
onClose={onClose}
projectName={projectName}
setProjectName={setProjectName}
/>
}
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Задачи сотрудников
</Typography>
{projectsFilter}
<Button
color={formStatus === true ? "info" : "inherit"}
style={{
backgroundColor: formStatus === true ? "white" : "inherit",
}}
onClick={onClick}
>
{formStatus === true ? (
<>
<Close />
<span style={{ lineHeight: "16px" }}>Скрыть задачу</span>
</>
) : (
<>
<Add />
<span style={{ lineHeight: "16px" }}>Добавить задачу</span>
</>
)}
</Button>
</Toolbar>
</AppBar>
</Box>
);
}
export const getCurrentWeekDayString = (dayNumber) => {
if (dayNumber <= 6 && dayNumber >= 0) {
return ["ПН","ВТ","СР","ЧТ","ПТ","СБ","ВС"][dayNumber];
} else {
return null
}
}
\ No newline at end of file
import { FormControlLabel, Grid, Switch } from "@mui/material";
import { Box } from "@mui/system";
import CalendarRow from "../../MonthCalendar/MonthCalendarBody/CalendarRow/CalendarRow";
import CalendarSmallCell from "../../MonthCalendar/MonthCalendarBody/CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "../../MonthCalendar/MonthCalendarBody/CalendarStandartCell.js/CalendarStandartCell";
import { getCurrentWeekDayString } from "./Helpers";
function WeekCalendarBody({week, hoursInDay, hourFormat, setHourFormat}) {
return (
<>
<Box style={{marginBottom: '30px'}}>
<Box style={{position: 'sticky', top: '0px', zIndex: '10', backgroundColor: 'lightgrey'}}>
<CalendarRow
>
<CalendarSmallCell xs={1}>
<FormControlLabel
control={<Switch color="primary" checked={hourFormat} onChange={()=>{setHourFormat(()=>!hourFormat)}}/>}
label="1 час"
labelPlacement="end"
/>
</CalendarSmallCell>
{week?.map((weekDay, i)=>{
return (
<CalendarStandartCell key={i} xs={11/week.length}>
<span style={{display: 'block', fontWeight: "600"}}>{weekDay}</span>
<span style={{marginBottom: '10px'}}>{getCurrentWeekDayString(i)}</span>
</CalendarStandartCell>
)
})}
</CalendarRow>
</Box>
<Grid container>
<CalendarRow week={true}>
<Grid item xs={0.995} flexDirection='column'>
{hoursInDay?.map((hour, i)=>{
return (
<CalendarSmallCell key={i} week={true}>
{hour}
</CalendarSmallCell>)
})}
</Grid>
<Grid item xs={11.005}>
<CalendarRow week={true}>
{week?.map((weekDay, i)=>{
return (
<Grid item key={i} xs={12/week.length}>
{hoursInDay?.map((hour, i)=>{
return (
<CalendarStandartCell key={i} week={true}>
</CalendarStandartCell>)
})}
</Grid>)
})}
</CalendarRow>
</Grid>
</CalendarRow>
</Grid>
</Box>
</>
);
}
export default WeekCalendarBody;
\ No newline at end of file
import { AppBar, Toolbar} from '@mui/material';
import { Box } from '@mui/system';
import WeekCalendarHeaderInfo from './WeekCalendarHeaderInfo/WeekCalendarHeaderInfo';
function WeekCalendarHeader({decrementWeek, incrementWeek, weekInfo}) {
return (
<>
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<WeekCalendarHeaderInfo
decrementWeek={decrementWeek}
incrementWeek={incrementWeek}
weekInfo={weekInfo}
/>
</Toolbar>
</AppBar>
</Box>
</>
);
}
export default WeekCalendarHeader;
\ No newline at end of file
import ArrowDecrementButton from '../../../UI/ArrowDecrementButton/ArrowDecrementButton';
import ArrowIncrementButton from '../../../UI/ArrowIncrementButton/ArrowIncrementButton';
import { Box } from '@mui/system';
import {Typography} from '@mui/material';
function WeekCalendarHeaderInfo({decrementWeek, incrementWeek, weekInfo}) {
return (
<>
<Box sx={{width: '40%', marginBottom: '15px'}}>
<h2>Цель недели: Наладить режим сна</h2>
<Box sx={{display: 'flex', alignItems: 'center'}}>
<ArrowDecrementButton
onClick={()=>{decrementWeek()}}
/>
<Typography
variant="h6"
sx={{
flexBasis: '250px',
display: 'flex',
justifyContent: 'center',
}}
>
{weekInfo}
</Typography>
<ArrowIncrementButton
onClick={()=>{incrementWeek()}}
/>
</Box>
</Box>
</>
);
}
export default WeekCalendarHeaderInfo;
\ No newline at end of file
......@@ -6,6 +6,7 @@ export const workerMenuButtons = [
{ text: 'Проекты', path: '/projects' },
{ text: 'Неделя', path: '/week' },
{ text: 'Месяц', path: '/month' },
{ text: 'Задачи Сотрудников', path: '/workers-tasks' },
{ text: 'Мои задачи', path: '/my-tasks' }
]
......
......@@ -19,7 +19,6 @@ import TableRowTask from "../../components/MyTasksCompoments/TableRowTask/TableR
export default function EnhancedTable() {
const dispatch = useDispatch();
const tasks = useSelector((state) => state.tasks.tasks);
......@@ -29,31 +28,33 @@ export default function EnhancedTable() {
const [order, setOrder] = useState("asc");
const [orderBy, setOrderBy] = useState("id");
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] =useState(5);
const [rowsPerPage, setRowsPerPage] = useState(5);
const [modal, setModal] = useState({
open: false,
task: null,
});
const [projects,setProjects]=useState(['1','2'])
const [projects, setProjects] = useState(["1", "2"]);
useEffect(() => {
dispatch(fetchAllTasks());
filterProjectsNamesFromTasks()
filterProjectsNamesFromTasks();
}, [dispatch]);
useEffect(() => {
if (tasks && tasks?.length > 0) {
setRecievedTasks(tasks);
}
}, [dispatch, tasks?.length]);
useEffect(() => {
dispatch(fetchAllTasks());
}, [addTaskForm, setAddTaskForm]);
useEffect(() => {
dispatch(fetchAllTasks());
}, [addTaskForm, setAddTaskForm]);
const handleRequestSort = ( property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};
......@@ -72,7 +73,6 @@ useEffect(() => {
const name = e.target.name;
const { id } = task;
const newTasks = recievedTasks.map((task) => {
console.log(task)
if (task.id === id) {
return { ...task, [name]: value };
}
......@@ -108,7 +108,7 @@ useEffect(() => {
});
setRecievedTasks(newTasks);
};
const onProjectChange = (e, task) => {
const value = e.target.value;
const project = uniqueProjects.find((e) => e.id === value);
......@@ -120,12 +120,11 @@ useEffect(() => {
updated.projectName = project.title;
return updated;
}
return task;
return task;
});
setRecievedTasks(newTasks);
};
const onToggleEditMode = (id) => {
const newTasks = recievedTasks.map((task) => {
if (task.id === id) {
......@@ -154,9 +153,9 @@ useEffect(() => {
setRecievedTasks(newTasks);
};
const handleEditTask= (task)=>{
dispatch(editTask(task))
}
const handleEditTask = (task) => {
dispatch(editTask(task));
};
const deleteHandle = (id) => {
dispatch(deleteTask(id));
......@@ -186,37 +185,36 @@ useEffect(() => {
const [projectName, setProjectName] = React.useState([]);
const [filterProjectTumbler, setFilterProjectTumbler] = React.useState(false);
const onClose=(projectName)=>{
let tasksFilteredByProject = tasks
if (projectName.length>0) {
tasksFilteredByProject = tasks.filter(task=>projectName.includes(task.project?.title))
const onClose = (projectName) => {
let tasksFilteredByProject = tasks;
if (projectName.length > 0) {
tasksFilteredByProject = tasks.filter((task) =>
projectName.includes(task.project?.title)
);
}
setRecievedTasks(tasksFilteredByProject)
setFilterProjectTumbler(true)
}
const rawProjects= tasks?.map(task=>task.project)
setRecievedTasks(tasksFilteredByProject);
setFilterProjectTumbler(true);
};
const rawProjects = tasks?.map((task) => task.project);
const filterProjectsNamesFromTasks = ()=>{
const filterProjectsNamesFromTasks = () => {
if (tasks && tasks?.length > 0) {
let rawSetProjectNames = []
for (let project of rawProjects){
if (project===null){
} else{
rawSetProjectNames.push(project.title)
let rawSetProjectNames = [];
for (let project of rawProjects) {
if (project === null) {
} else {
rawSetProjectNames.push(project.title);
}
}
let uniqueTitlesProjects = [...new Set(rawSetProjectNames)];
setProjects(uniqueTitlesProjects)
setProjects(uniqueTitlesProjects);
}
}
};
const uniqueProjects = rawProjects?.reduce((results, value, index) => {
const exist = results.find((v) => {
return v !== null && v.id === value?.id
});
return v !== null && v.id === value?.id;
});
if (!exist && value !== null) {
results.push(value);
}
......@@ -243,14 +241,13 @@ console.log('tasks', tasks)
setProjectName={setProjectName}
/>
{addTaskForm ? (
{addTaskForm ? (
<NewTaskForm
projects={uniqueProjects}
setAddTaskForm={()=>setAddTaskForm(false)}
/>
setAddTaskForm={() => setAddTaskForm(false)}
/>
) : null}
<TableContainer>
<Table sx={{ minWidth: 600 }} aria-labelledby="tableTitle">
<EnhancedTableHead
......@@ -260,7 +257,6 @@ console.log('tasks', tasks)
rowCount={tasks.length}
/>
<TableBody>
{stableSort(recievedTasks, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((task, index) => {
......@@ -310,7 +306,6 @@ console.log('tasks', tasks)
}
}
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
......
......@@ -13,36 +13,42 @@ const headCells = [
numeric: true,
disablePadding: true,
label: "",
canSort: true,
},
{
id: "priority",
numeric: false,
disablePadding: true,
label: "Приоритет",
canSort: true,
},
{
id: "createdAt",
numeric: true,
disablePadding: false,
label: "Дата создания",
canSort: true,
},
{
id: "title",
numeric: true,
disablePadding: false,
label: "Заголовок",
canSort: true,
},
{
id: "projectName",
numeric: true,
disablePadding: false,
label: "Проект",
canSort: true,
},
{
id: "authorDisplayName",
numeric: true,
disablePadding: false,
label: "Автор",
canSort: true,
},
{
......@@ -50,38 +56,44 @@ const headCells = [
numeric: true,
disablePadding: false,
label: "Дата и время выполнения",
canSort: false,
},
{
id: "dateTimeDue",
id: "dateTimeDeadLine",
numeric: true,
disablePadding: false,
label: "Дедлайн",
canSort: true,
},
{
id: "accomplish",
numeric: true,
disablePadding: false,
label: "Статус",
canSort: true,
},
{
id: "change",
numeric: false,
disablePadding: false,
label: "",
canSort: false,
},
{
id: "delete",
numeric: false,
disablePadding: false,
label: "",
canSort: false,
},
];
export default function EnhancedTableHead({ order, orderBy, rowCount, onRequestSort }) {
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
};
export default function EnhancedTableHead({
order,
orderBy,
rowCount,
onRequestSort,
}) {
return (
<TableHead>
......@@ -89,22 +101,31 @@ export default function EnhancedTableHead({ order, orderBy, rowCount, onRequestS
{headCells.map((headCell) => (
<TableCell
key={headCell.id}
align={"center"}
align={"left"}
padding={headCell.disablePadding ? "none" : "normal"}
sortDirection={orderBy === headCell.id ? order : false}
sortDirection={
headCell.canSort && orderBy === headCell.id ? order : false
}
style={{ paddingLeft: "0" }}
>
<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>
{headCell.canSort ? (
<TableSortLabel
active={orderBy === headCell.id}
direction={orderBy === headCell.id ? order : "asc"}
onClick={() => onRequestSort(headCell.id)}
>
{headCell.label}
{orderBy === headCell.id ? (
<Box component="span" sx={visuallyHidden}>
{order === "desc"
? "sorted descending"
: "sorted ascending"}
</Box>
) : null}
</TableSortLabel>
) : (
<span>{headCell.label}</span>
)}
</TableCell>
))}
</TableRow>
......
This diff is collapsed.
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";
const headCells = [
{
id: "id",
numeric: true,
disablePadding: true,
label: "",
},
{
id: "priority",
numeric: false,
disablePadding: true,
label: "Приоритет",
},
{
id: "createdAt",
numeric: true,
disablePadding: false,
label: "Дата создания",
},
{
id: "title",
numeric: true,
disablePadding: false,
label: "Заголовок",
},
{
id: "projectName",
numeric: true,
disablePadding: false,
label: "Проект",
},
{
id: "executorDisplayName",
numeric: true,
disablePadding: false,
label: "Исполнитель",
},
{
id: "authorDisplayName",
numeric: true,
disablePadding: false,
label: "Автор",
},
{
id: "dateTimeStart",
numeric: true,
disablePadding: false,
label: "Дата и время выполнения",
},
{
id: "dateTimeDue",
numeric: true,
disablePadding: false,
label: "Дедлайн",
},
{
id: "accomplish",
numeric: true,
disablePadding: false,
label: "Статус",
},
{
id: "change",
numeric: false,
disablePadding: false,
label: "",
},
{
id: "delete",
numeric: false,
disablePadding: false,
label: "",
},
];
export default function UsersTasksHeader({ order, orderBy, rowCount, onRequestSort }) {
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>
);
}
UsersTasksHeader.propTypes = {
onRequestSort: PropTypes.func.isRequired,
order: PropTypes.oneOf(["asc", "desc"]).isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired,
};
......@@ -3,23 +3,26 @@ import { useEffect, useState, useMemo, useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import WeekCalendarBody from '../../components/Calendars/WeekCalendar/WeekCalendarBody/WeekCalendarBody';
import WeekCalendarHeader from '../../components/Calendars/WeekCalendar/WeekCalendarHeader/WeekCalendarHeader'
import { getWeekInfoString, getWeekFromCurrentDate } from '../../helpers/CalendarHelpers';
import { fetchCalendarTasks } from '../../store/actions/tasksActions';
import { getWeekInfoString, getWeekFromCurrentDate, dateToISOLikeButLocal } from '../../helpers/CalendarHelpers';
import { addCalendarTask, deleteCalendarTask, editCalendarTask, fetchCalendarTasks } from '../../store/actions/tasksActions';
function WeekCalendar() {
const dispatch = useDispatch();
const { calendarTasks } = useSelector(state => state.tasks);
const user = useSelector(state => state.users?.user);
const [date, setDate] = useState({ year: '', month: '', currentDay: '' })
const [dateNow, setDateNow] = useState({ year: '', month: '', currentDay: '' })
const [currentTask, setCurrentTask] = useState({ title: '', description: '', priority: null, infoForCell: { startHour: null, endHour: null } })
const [hourFormat, setHourFormat] = useState(false);
const [userId, setUserId] = useState('')
useEffect(() => {
const year = new Date().getFullYear()
const month = new Date().getMonth()
const currentDay = moment().date()
setDate({ year: year, month: month, currentDay: currentDay })
// dispatch(fetchCalendarTasks())
setDateNow({ year: year, month: month, currentDay: currentDay })
dispatch(fetchCalendarTasks(user.id))
setUserId(user.id)
}, [])
const hoursInDay = useMemo(() => {
......@@ -33,26 +36,110 @@ function WeekCalendar() {
}, [hourFormat])
const week = useMemo(() => {
return getWeekFromCurrentDate(date.year, date.month, date.currentDay)
}, [date])
return getWeekFromCurrentDate(dateNow.year, dateNow.month, dateNow.currentDay)
}, [dateNow])
const weekInfo = useMemo(() => {
return getWeekInfoString(week, dateNow)
}, [dateNow, week])
const incrementWeek = useCallback(() => {
setDate((prevState) => {
setDateNow((prevState) => {
const newDate = new Date(prevState.year, prevState.month, prevState.currentDay + 7)
return { year: newDate.getFullYear(), month: newDate.getMonth(), currentDay: moment(newDate).date() }
})
}, [])
const decrementWeek = useCallback(() => {
setDate((prevState) => {
setDateNow((prevState) => {
const newDate = new Date(prevState.year, prevState.month, prevState.currentDay - 7)
return { year: newDate.getFullYear(), month: newDate.getMonth(), currentDay: moment(newDate).date() }
})
}, [])
const weekInfo = useMemo(() => {
return getWeekInfoString(week, date)
}, [date, week])
const onChangeCurrentTaskHandler = useCallback((e) => {
const { name, value } = e.target;
if (name === 'startHour' || name === 'endHour') {
setCurrentTask((prevState) => {
return {
...prevState,
infoForCell: {
...prevState.infoForCell,
[name]: value
}
}
});
} else {
setCurrentTask((prevState) => {
return {
...prevState,
[name]: value
}
});
}
}, []);
const createTaskInCellHandler = (dayNumber, dayHour) => {
let hour
if (!isNaN(dayHour)) {
hour = dayHour
} else {
hour = parseInt(dayHour.split(':')[0])
}
let hourDue
if (hourFormat) {
hourDue = hour + 1
} else {
hourDue = hour + 2
}
const newTask = {
title: "Задача",
description: "описание",
priority: null,
dateTimeStart: dateToISOLikeButLocal(new Date(dateNow.year, dateNow.month, dayNumber, hour, 0)),
dateTimeDue: dateToISOLikeButLocal(new Date(dateNow.year, dateNow.month, dayNumber, hourDue, 59)),
infoForCell: {
startHour: hour,
endHour: hourDue,
startDay: dayNumber
}
}
setCurrentTask((newTask))
}
const sendNewTaskHandler = async () => {
const timeEndHour = currentTask.infoForCell.endHour
const timeStartHour = currentTask.infoForCell.startHour
const day = currentTask.infoForCell.startDay
const due = dateToISOLikeButLocal(new Date(dateNow.year, dateNow.month, day, timeEndHour - 1, 59))
const start = dateToISOLikeButLocal(new Date(dateNow.year, dateNow.month, day, timeStartHour, 0))
if (currentTask.id) {
const newTask = {
...currentTask,
dateTimeStart: start,
dateTimeDue: due,
taskId: currentTask.mainTaskId
}
delete newTask.infoForCell
await dispatch(editCalendarTask(newTask, currentTask.id, userId))
} else {
const newTask = {
...currentTask,
dateTimeStart: start,
dateTimeDue: due,
executor: userId,
author: user.id,
dateTimeDeadLine: due,
}
delete newTask.infoForCell
delete newTask.id
await dispatch(addCalendarTask(newTask, userId))
}
}
const deleteTaskHandler = async (taskId) => {
dispatch(deleteCalendarTask(taskId, userId))
}
return (
<>
......@@ -62,12 +149,18 @@ function WeekCalendar() {
weekInfo={weekInfo}
/>
<WeekCalendarBody
deleteTaskHandler={deleteTaskHandler}
sendNewTaskHandler={sendNewTaskHandler}
onChangeCurrentTaskHandler={onChangeCurrentTaskHandler}
currentTask={currentTask}
setCurrentTask={setCurrentTask}
tasks={calendarTasks}
date={date}
date={dateNow}
week={week}
hourFormat={hourFormat}
setHourFormat={setHourFormat}
hoursInDay={hoursInDay}
createTaskInCellHandler={createTaskInCellHandler}
/>
</>
);
......
import axios from "../../axiosPlanner";
import { CREATE_MEMBER_SUCCESS, CREATE_PROJECT_SUCCESS, DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, FETCH_ALL_USER_PROJECTS_SUCCESS, FETCH_MEMBERS_ERROR, FETCH_MEMBERS_REQUEST, FETCH_MEMBERS_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
import { showNotification } from "./commonActions";
......
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