Commit 17849e6b authored by Ermolaev Timur's avatar Ermolaev Timur

Merge branch 'task-111-feature/show-week-calendar-tasks' into 'development'

Task 111 feature/show week calendar tasks

See merge request !88
parents 752c4a67 6b4eb850
...@@ -10,8 +10,8 @@ function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, descripti ...@@ -10,8 +10,8 @@ function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, descripti
if (title) { if (title) {
const startHourInt = parseInt(startHour) const startHourInt = parseInt(startHour)
const endHourInt = parseInt(endHour) const endHourInt = parseInt(endHour)
if (startHourInt >= 8 && startHourInt <= 22) { if (startHourInt >= 8 && startHourInt <= 24) {
if (endHourInt >= 8 && endHourInt <= 22) { if (endHourInt >= 8 && endHourInt <= 24) {
if (startHourInt < endHourInt) { if (startHourInt < endHourInt) {
return true return true
} }
......
import { Grid } from "@mui/material"; import { Grid } from "@mui/material";
import { memo, useEffect, useState } from "react"; 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 ...@@ -36,6 +36,11 @@ const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCell
setIsThisCell(true); setIsThisCell(true);
handleOpen(e) handleOpen(e)
} }
if (week) {
createTaskInCellHandler(dayNumber, hours);
setIsThisCell(true);
handleOpen(e)
}
} }
return <> return <>
...@@ -48,7 +53,7 @@ const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCell ...@@ -48,7 +53,7 @@ const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCell
> >
{children} {children}
{isThisCell ? {isThisCell ?
<DefaultTask /> : null} <DefaultTask week={week}/> : null}
</Grid> </Grid>
</> </>
......
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { memo } from "react"; import { memo } from "react";
const DefaultTaskStyles = { const MonthDefaultTaskStyles = {
position: 'relative', position: 'relative',
height: '30px', height: '30px',
backgroundColor: 'lightgreen', backgroundColor: 'lightgreen',
...@@ -16,12 +16,26 @@ const DefaultTaskStyles = { ...@@ -16,12 +16,26 @@ const DefaultTaskStyles = {
paddingLeft: '5px', paddingLeft: '5px',
zIndex: '5' 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 (<> return (<>
<Box <Box
sx={DefaultTaskStyles} sx={week ? WeekDefaultTaskStyles : MonthDefaultTaskStyles}
> >
<span> <span>
Задача Задача
......
import { Grid } from "@mui/material"; import { Grid } from "@mui/material";
import React, { memo, useEffect, useState } from "react"; 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 }) => { 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 { FormControlLabel, Grid, Switch } from "@mui/material";
import { Box } from "@mui/system"; 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 CalendarRow from "../../CalendarRow/CalendarRow";
import CalendarSmallCell from "../../CalendarSmallCell/CalendarSmallCell"; import CalendarSmallCell from "../../CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "../../CalendarStandartCell/CalendarStandartCell"; import CalendarStandartCell from "../../CalendarStandartCell/CalendarStandartCell";
import CalendarRowDayWeek from "./CalendarRowDayWeek/CalendarRowDayWeek"; import CalendarColumnDayWeek from "./CalendarColumnDayWeek/CalendarColumnDayWeek";
import { getCurrentWeekDayString } from "./Helpers"; 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 ( return (
<> <>
...@@ -47,16 +67,19 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t ...@@ -47,16 +67,19 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t
<CalendarRow week={true}> <CalendarRow week={true}>
{week?.map((weekDay, i) => { {week?.map((weekDay, i) => {
return ( return (
<Grid item key={i} xs={12 / week.length}> <CalendarColumnDayWeek
<CalendarRowDayWeek key={i}
hoursInDay={hoursInDay} hoursInDay={hoursInDay}
tasks={tasks} tasks={tasks}
month={date.month} month={date.month}
year={date.year} year={date.year}
day={weekDay} day={weekDay}
hourFormat={hourFormat} hourFormat={hourFormat}
setCurrentTask={setCurrentTask}
handleOpen={handleOpen}
createTaskInCellHandler={createTaskInCellHandler}
modal={modal.open}
/> />
</Grid>
) )
})} })}
</CalendarRow> </CalendarRow>
...@@ -65,6 +88,23 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t ...@@ -65,6 +88,23 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t
</CalendarRow> </CalendarRow>
</Grid> </Grid>
</Box> </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>
</> </>
); );
} }
......
...@@ -23,7 +23,6 @@ export default function ModalTask({modal, handleClose, children}) { ...@@ -23,7 +23,6 @@ export default function ModalTask({modal, handleClose, children}) {
window.removeEventListener('resize', detectSize) window.removeEventListener('resize', detectSize)
} }
}, [windowDimenion]) }, [windowDimenion])
const modalRef = useRef('')
const getYCordinatesToModal = () => { const getYCordinatesToModal = () => {
...@@ -63,7 +62,7 @@ export default function ModalTask({modal, handleClose, children}) { ...@@ -63,7 +62,7 @@ export default function ModalTask({modal, handleClose, children}) {
aria-describedby="modal-modal-description" aria-describedby="modal-modal-description"
BackdropProps={{ style: { backgroundColor: 'rgba(255,255,255, 0)' } }} BackdropProps={{ style: { backgroundColor: 'rgba(255,255,255, 0)' } }}
> >
<Box sx={style} ref={modalRef}> <Box sx={style}>
{children} {children}
</Box> </Box>
</Modal> </Modal>
......
...@@ -3,23 +3,26 @@ import { useEffect, useState, useMemo, useCallback } from 'react'; ...@@ -3,23 +3,26 @@ import { useEffect, useState, useMemo, useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import WeekCalendarBody from '../../components/Calendars/WeekCalendar/WeekCalendarBody/WeekCalendarBody'; import WeekCalendarBody from '../../components/Calendars/WeekCalendar/WeekCalendarBody/WeekCalendarBody';
import WeekCalendarHeader from '../../components/Calendars/WeekCalendar/WeekCalendarHeader/WeekCalendarHeader' import WeekCalendarHeader from '../../components/Calendars/WeekCalendar/WeekCalendarHeader/WeekCalendarHeader'
import { getWeekInfoString, getWeekFromCurrentDate } from '../../helpers/CalendarHelpers'; import { getWeekInfoString, getWeekFromCurrentDate, dateToISOLikeButLocal } from '../../helpers/CalendarHelpers';
import { fetchCalendarTasks } from '../../store/actions/tasksActions'; import { addCalendarTask, deleteCalendarTask, editCalendarTask, fetchCalendarTasks } from '../../store/actions/tasksActions';
function WeekCalendar() { function WeekCalendar() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { calendarTasks } = useSelector(state => state.tasks); const { calendarTasks } = useSelector(state => state.tasks);
const user = useSelector(state => state.users?.user); 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 [hourFormat, setHourFormat] = useState(false);
const [userId, setUserId] = useState('')
useEffect(() => { useEffect(() => {
const year = new Date().getFullYear() const year = new Date().getFullYear()
const month = new Date().getMonth() const month = new Date().getMonth()
const currentDay = moment().date() const currentDay = moment().date()
setDate({ year: year, month: month, currentDay: currentDay }) setDateNow({ year: year, month: month, currentDay: currentDay })
// dispatch(fetchCalendarTasks()) dispatch(fetchCalendarTasks(user.id))
setUserId(user.id)
}, []) }, [])
const hoursInDay = useMemo(() => { const hoursInDay = useMemo(() => {
...@@ -33,26 +36,110 @@ function WeekCalendar() { ...@@ -33,26 +36,110 @@ function WeekCalendar() {
}, [hourFormat]) }, [hourFormat])
const week = useMemo(() => { const week = useMemo(() => {
return getWeekFromCurrentDate(date.year, date.month, date.currentDay) return getWeekFromCurrentDate(dateNow.year, dateNow.month, dateNow.currentDay)
}, [date]) }, [dateNow])
const weekInfo = useMemo(() => {
return getWeekInfoString(week, dateNow)
}, [dateNow, week])
const incrementWeek = useCallback(() => { const incrementWeek = useCallback(() => {
setDate((prevState) => { setDateNow((prevState) => {
const newDate = new Date(prevState.year, prevState.month, prevState.currentDay + 7) const newDate = new Date(prevState.year, prevState.month, prevState.currentDay + 7)
return { year: newDate.getFullYear(), month: newDate.getMonth(), currentDay: moment(newDate).date() } return { year: newDate.getFullYear(), month: newDate.getMonth(), currentDay: moment(newDate).date() }
}) })
}, []) }, [])
const decrementWeek = useCallback(() => { const decrementWeek = useCallback(() => {
setDate((prevState) => { setDateNow((prevState) => {
const newDate = new Date(prevState.year, prevState.month, prevState.currentDay - 7) const newDate = new Date(prevState.year, prevState.month, prevState.currentDay - 7)
return { year: newDate.getFullYear(), month: newDate.getMonth(), currentDay: moment(newDate).date() } return { year: newDate.getFullYear(), month: newDate.getMonth(), currentDay: moment(newDate).date() }
}) })
}, []) }, [])
const weekInfo = useMemo(() => { const onChangeCurrentTaskHandler = useCallback((e) => {
return getWeekInfoString(week, date) const { name, value } = e.target;
}, [date, week]) 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 ( return (
<> <>
...@@ -62,12 +149,18 @@ function WeekCalendar() { ...@@ -62,12 +149,18 @@ function WeekCalendar() {
weekInfo={weekInfo} weekInfo={weekInfo}
/> />
<WeekCalendarBody <WeekCalendarBody
deleteTaskHandler={deleteTaskHandler}
sendNewTaskHandler={sendNewTaskHandler}
onChangeCurrentTaskHandler={onChangeCurrentTaskHandler}
currentTask={currentTask}
setCurrentTask={setCurrentTask}
tasks={calendarTasks} tasks={calendarTasks}
date={date} date={dateNow}
week={week} week={week}
hourFormat={hourFormat} hourFormat={hourFormat}
setHourFormat={setHourFormat} setHourFormat={setHourFormat}
hoursInDay={hoursInDay} hoursInDay={hoursInDay}
createTaskInCellHandler={createTaskInCellHandler}
/> />
</> </>
); );
......
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