Merge branch 'development' of…

Merge branch 'development' of ssh://git.attractor-school.com:30022/apollo64/crm-team-one into task-110-enhance/CRUD_author_tasks
parents 83e48c87 f766ad1f
...@@ -71,15 +71,6 @@ const App = () => { ...@@ -71,15 +71,6 @@ const App = () => {
</ProtectedRoute> </ProtectedRoute>
} /> } />
<Route path={"/week/:id"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<WeekCalendar />
</ProtectedRoute>
} />
<Route path={"/month"} element={ <Route path={"/month"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
...@@ -89,15 +80,6 @@ const App = () => { ...@@ -89,15 +80,6 @@ const App = () => {
</ProtectedRoute> </ProtectedRoute>
} /> } />
<Route path={"/month/:id"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<MonthCalendar></MonthCalendar>
</ProtectedRoute>
} />
<Route path={"/my-tasks"} element={ <Route path={"/my-tasks"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
......
...@@ -2,26 +2,11 @@ import { Button, TextField } from "@mui/material"; ...@@ -2,26 +2,11 @@ import { Button, TextField } from "@mui/material";
import { memo } from "react"; import { memo } from "react";
import { priorities } from "../../../constants"; import { priorities } from "../../../constants";
import CustomSelect from '../../UI/СustomSelect/СustomSelect' import CustomSelect from '../../UI/СustomSelect/СustomSelect'
import { isValidate } from "./Helpers";
function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, description, priority, sendNewTaskHandler, deleteTaskHandler, startHour, endHour, id }) { function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, description, priority, sendNewTaskHandler, deleteTaskHandler, startHour, endHour, id }) {
const isValidate = () => {
if (title) {
const startHourInt = parseInt(startHour)
const endHourInt = parseInt(endHour)
if (startHourInt >= 8 && startHourInt <= 22) {
if (endHourInt >= 8 && endHourInt <= 22) {
if (startHourInt < endHourInt) {
return true
}
}
} else {
return false
}
}
}
return (<> return (<>
<TextField <TextField
id="task-description-title" id="task-description-title"
...@@ -72,7 +57,7 @@ function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, descripti ...@@ -72,7 +57,7 @@ function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, descripti
/> />
</div> </div>
<div style={{ display: 'flex', gap: '20px', margin: '10px 0' }}> <div style={{ display: 'flex', gap: '20px', margin: '10px 0' }}>
<Button id='test_button_save_task' onClick={sendNewTaskHandler} disabled={!isValidate()}>Сохранить</Button> <Button id='test_button_save_task' onClick={sendNewTaskHandler} disabled={!isValidate(title, startHour, endHour)}>Сохранить</Button>
<Button onClick={deleteTaskHandler} disabled={!id}>Удалить</Button> <Button onClick={deleteTaskHandler} disabled={!id}>Удалить</Button>
</div> </div>
</>); </>);
......
export const isValidate = (title, startHour, endHour) => {
if (title) {
const startHourInt = parseInt(startHour)
const endHourInt = parseInt(endHour)
if (startHourInt >= 8 && startHourInt <= 24) {
if (endHourInt >= 8 && endHourInt <= 24) {
if (startHourInt < endHourInt) {
return true
}
}
} else {
return false
}
}
}
\ No newline at end of file
import { Autocomplete, Button, TextField } from "@mui/material"; import { Autocomplete, Button, TextField } from "@mui/material";
import { memo } from "react"; import { memo } from "react";
import CustomAutocomplete from "../../UI/CustomAutocomplete/CustomAutocomplete";
function CalendarModalWorkerContent({ allUserProjects, onChangeProjectHandler, onChangeWorkerHandler, workerInfo, workers, handleClose, onChangeCalendarUser}) { function CalendarModalWorkerContent({ allUserProjects, onChangeProjectHandler, onChangeWorkerHandler, workerInfo, workers, handleClose, onChangeCalendarUser }) {
return (<> return (<>
<Autocomplete <CustomAutocomplete
id="choose-project" name={'project'}
freeSolo label={'Проекты'}
options={allUserProjects} options={allUserProjects}
getOptionLabel={(item) => item.title || ""}
onChange={onChangeProjectHandler} onChange={onChangeProjectHandler}
name={"project"}
value={workerInfo.project} value={workerInfo.project}
renderInput={(params) => <TextField getOptionLabel={(item) => item.title || ""}
style={{ marginBottom: "15px" }} style={{ marginBottom: '15px' }}
label={"Проект"}
state={workerInfo.project}
{...params} />}
/> />
{workerInfo.project ? {workerInfo.project ?
<> <>
<Autocomplete <CustomAutocomplete
id="choose-worker" name={'worker'}
freeSolo label={'Участник'}
options={workers} options={workers}
getOptionLabel={(item) => item?.user?.displayName || ""} onChange={onChangeWorkerHandler}
onChange={(e, value) => { onChangeWorkerHandler(e, value) }}
name={"worker"}
value={workerInfo.worker} value={workerInfo.worker}
renderInput={(params) => <TextField getOptionLabel={(item) => item?.user?.displayName || ""}
label={"Участник"} style={{ marginBottom: '15px' }}
state={workerInfo.worker}
{...params} />}
/> />
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '10px 0' }}> <div style={{ display: 'flex', justifyContent: 'space-between', margin: '10px 0' }}>
<Button onClick={()=>{onChangeCalendarUser()}} >Выбрать</Button> <Button onClick={() => { onChangeCalendarUser() }} >Выбрать</Button>
<Button onClick={() => handleClose()}>Отмена</Button> <Button onClick={() => handleClose()}>Отмена</Button>
</div> </div>
</> </>
......
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";
const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCellHandler, handleOpen, modal, dragTaskHandler, linesInDay, week }) => { const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCellHandler, handleOpen, modal, dragTaskHandler, linesInDay, week, copyTask, createCopyTask, month}) => {
const [isThisCell, setIsThisCell] = useState(false) const [isThisCell, setIsThisCell] = useState(false)
const cellClass = { const cellClass = {
...@@ -30,12 +30,22 @@ const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCell ...@@ -30,12 +30,22 @@ const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCell
e.preventDefault(); e.preventDefault();
dragTaskHandler(dayNumber, parseInt(hours.split(':')[0])) dragTaskHandler(dayNumber, parseInt(hours.split(':')[0]))
} }
const onClickHandler = (e) => { const onClickHandler = (e) => {
if (linesInDay?.length) { if (linesInDay?.length) {
createTaskInCellHandler(dayNumber, hours); createTaskInCellHandler(dayNumber, hours);
setIsThisCell(true); setIsThisCell(true);
handleOpen(e) handleOpen(e)
} }
if (week) {
if (copyTask) {
createCopyTask(dayNumber, parseInt(hours.split(':')[0]), month)
} else {
createTaskInCellHandler(dayNumber, hours, month);
setIsThisCell(true);
handleOpen(e)
}
}
} }
return <> return <>
...@@ -48,7 +58,7 @@ const CalendarStandartCell = ({ children, xs, hours, dayNumber, createTaskInCell ...@@ -48,7 +58,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 { FormControlLabel, Switch } from "@mui/material";
import { memo } from "react";
const HourFormatSwitch = ({ hourFormat, setHourFormat }) => {
return (<>
<FormControlLabel
control={<Switch color="primary" checked={hourFormat} onChange={() => { setHourFormat(() => !hourFormat) }} />}
label="1 час"
labelPlacement="end"
/>
</>)
};
export default memo(HourFormatSwitch);
\ No newline at end of file
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import Modal from '@mui/material/Modal'; import Modal from '@mui/material/Modal';
import { useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
export default function ModalTask({modal, handleClose, children}) { export default function ModalTask({ modal, handleClose, children, week }) {
const [windowDimenion, detectHW] = useState({ const [windowDimenion, detectHW] = useState({
winWidth: window.innerWidth, winWidth: window.innerWidth,
...@@ -23,23 +23,31 @@ export default function ModalTask({modal, handleClose, children}) { ...@@ -23,23 +23,31 @@ export default function ModalTask({modal, handleClose, children}) {
window.removeEventListener('resize', detectSize) window.removeEventListener('resize', detectSize)
} }
}, [windowDimenion]) }, [windowDimenion])
const modalRef = useRef('')
const getYCordinatesToModal = useCallback(() => {
const getYCordinatesToModal = () => { if (week) {
if (windowDimenion.winHeight > modal.yClickСordinates + 450) { if (windowDimenion.winHeight > modal.yClickСordinates + 450) {
return modal.yClickСordinates - modal.yDiv - modal.yDivClick return modal.yClickСordinates - modal.yDivClick
} else {
return modal.yClickСordinates - 450
}
} else { } else {
return modal.yClickСordinates - modal.yDiv - modal.yDivClick - ((modal.yClickСordinates + 450) - windowDimenion.winHeight) - 30 if (windowDimenion.winHeight > modal.yClickСordinates + 450) {
return modal.yClickСordinates - modal.yDiv - modal.yDivClick
} else {
return modal.yClickСordinates - modal.yDiv - modal.yDivClick - ((modal.yClickСordinates + 450) - windowDimenion.winHeight) - 30
}
} }
} }, [windowDimenion.winHeight, modal])
const getXCordinatesToModal = () => {
const getXCordinatesToModal = useCallback(() => {
if (windowDimenion.winWidth > modal.xClickСordinates + 270 + modal.xDiv) { if (windowDimenion.winWidth > modal.xClickСordinates + 270 + modal.xDiv) {
return modal.xClickСordinates + modal.xDiv - modal.xDivClick + 10 return modal.xClickСordinates + modal.xDiv - modal.xDivClick + 10
} else { } else {
return windowDimenion.winWidth - (windowDimenion.winWidth - modal.xClickСordinates) - modal.xDivClick - 270 - 80 return windowDimenion.winWidth - (windowDimenion.winWidth - modal.xClickСordinates) - modal.xDivClick - 270 - 80
} }
} }, [windowDimenion.winWidth, modal])
const style = { const style = {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
...@@ -63,7 +71,7 @@ export default function ModalTask({modal, handleClose, children}) { ...@@ -63,7 +71,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>
......
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 { Box, FormControlLabel, Switch } from "@mui/material"; import { Box, FormControlLabel, Switch } from "@mui/material";
import { useState } from "react"; import { useCallback, useState } from "react";
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 ModalTask from "../../../UI/ModalTask/ModalTask" import ModalTask from "../../ModalTask/ModalTask"
import MonthCalendarModalContent from "../../CalendarModalTaskContent/CalendarModalTaskContent"; import MonthCalendarModalContent from "../../CalendarModalTaskContent/CalendarModalTaskContent";
import CalendarRowDay from "./CalendarRowDay/CalendarRowDay"; import CalendarRowDay from "./CalendarRowDay/CalendarRowDay";
...@@ -12,7 +12,7 @@ function MonthCalendarBody({ month, year, tasks, createTaskInCellHandler, curren ...@@ -12,7 +12,7 @@ function MonthCalendarBody({ month, year, tasks, createTaskInCellHandler, curren
const [currentLine, setCurrentLine] = useState('') const [currentLine, setCurrentLine] = useState('')
const [modal, setModal] = useState({ open: false, y: 0, x: 0, }); const [modal, setModal] = useState({ open: false, y: 0, x: 0, });
const handleOpen = (e) => { const handleOpen = useCallback((e) => {
setModal({ setModal({
open: true, open: true,
yClickСordinates: e.clientY, yClickСordinates: e.clientY,
...@@ -22,12 +22,12 @@ function MonthCalendarBody({ month, year, tasks, createTaskInCellHandler, curren ...@@ -22,12 +22,12 @@ function MonthCalendarBody({ month, year, tasks, createTaskInCellHandler, curren
yDiv: e.target.offsetHeight, yDiv: e.target.offsetHeight,
xDiv: e.target.offsetWidth, xDiv: e.target.offsetWidth,
}) })
}; },[])
const handleClose = () => { const handleClose = useCallback(() => {
setModal({ ...modal, open: false }) setModal({ ...modal, open: false })
setCurrentTask({}) setCurrentTask({})
}; }, [modal, setCurrentTask])
return ( return (
<Box style={{ marginBottom: '30px' }}> <Box style={{ marginBottom: '30px' }}>
......
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";
import { getTasksWithInfoForPosition, getWidthLeftZIndex } from "./Helpers";
function CalendarColumnDayWeek({ hoursInDay, tasks, month, year, day, hourFormat, handleOpen, setCurrentTask, copyTask, setCopyTask, createCopyTask, createTaskInCellHandler, modal }) {
const [columnDaySize, setColumnDaySize] = useState({ width: 0, height: 0 })
const dayColumnRef = useRef('')
useEffect(() => {
setColumnDaySize(prev => { return { height: dayColumnRef.current.offsetHeight, width: dayColumnRef.current.offsetWidth } })
}, [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 (<>
<Grid item xs={12 / 7} ref={dayColumnRef} sx={{ position: 'relative' }}>
{linesInDay?.map((line, i) => {
const boxes = getTasksWithInfoForPosition(line, sortedTasks, linesInDay, columnDaySize.height, hours)
return (<>
{boxes.map((task) => {
const { width, left, zIndex } = getWidthLeftZIndex(task, columnDaySize.width, i)
return (
<CalendarWeekTask
key={task.task.id}
width={width}
height={task.height}
left={left}
task={task.task}
top={task.top}
zIndex={zIndex}
handleOpen={handleOpen}
setCurrentTask={setCurrentTask}
modal={modal}
month={month}
setCopyTask={setCopyTask}
>
</CalendarWeekTask>
)
})}
</>)
})}
{hoursInDay?.map((hour, i) => {
return (
<CalendarStandartCell
key={i}
week={true}
createTaskInCellHandler={createTaskInCellHandler}
handleOpen={handleOpen}
dayNumber={day}
hours={hour}
modal={modal}
copyTask={copyTask}
createCopyTask={createCopyTask}
month={month}
>
</CalendarStandartCell>
)
})}
</Grid>
</>);
}
export default CalendarColumnDayWeek;
\ No newline at end of file
import { Box } from "@mui/material"
import { useEffect, useState, memo, useCallback, useMemo } from "react"
import { getColorTaskByPriority } from "../../../../../../helpers/CalendarHelpers"
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
function CalendarWeekTask({ height, width, left, top, task, zIndex, handleOpen, setCurrentTask, modal, setCopyTask, month }) {
const [zIndexStyle, setZIndexStyle] = useState(10)
const color = useMemo(() => {
return getColorTaskByPriority(task.priority)
}, [task.priority])
useEffect(() => {
if (!modal) {
setZIndexStyle(zIndex)
}
}, [modal, zIndex])
const onClickTaskHandler = useCallback((e, task) => {
e.stopPropagation();
setCurrentTask((prevState) => {
return {
...task,
infoForCell: {
...task.infoForCell,
endHour: task.infoForCell.endHour + 1,
month: month
}
}
});
setZIndexStyle(100)
handleOpen(e)
}, [handleOpen, setCurrentTask, month])
const styles = {
boxSizing: 'border-box',
borderRadius: '3px',
border: '1px solid white',
backgroundColor: color,
height: `${height - 1}px`,
width: `${width - 1}px`,
position: 'absolute',
display: 'flex',
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>
<ContentCopyIcon sx={{ marginLeft: 'auto', marginTop: '5px'}} onClick={(e) => { e.stopPropagation(); setCopyTask(task) }}>
</ContentCopyIcon>
</Box>);
}
export default memo(CalendarWeekTask);
\ No newline at end of file
export const getTasksWithInfoForPosition = (line, sortedTasks, linesInDay, columnDayHeight, hours) => {
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.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,
task: sortedTasks[line[i].split('-')[1]]
})
}
}
}
return boxes
}
}
export const getWidthLeftZIndex = (task, dayColumnWidth, i) => {
const amount = task.tasksInHour
const oneTaskPrecentWidth = 100 / amount
const left = oneTaskPrecentWidth * dayColumnWidth / 100 * i
const zIndex = 10 + i
const oneTaskWidth = dayColumnWidth - (oneTaskPrecentWidth * dayColumnWidth / 100) * i
return { width: oneTaskWidth, left: left, zIndex: zIndex }
}
\ 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
...@@ -4,4 +4,19 @@ export const getCurrentWeekDayString = (dayNumber) => { ...@@ -4,4 +4,19 @@ export const getCurrentWeekDayString = (dayNumber) => {
} else { } else {
return null return null
} }
}
export const getMonthToDayColumn = (week, weekDay, month) => {
if (week[0] > week[6]) {
if (weekDay < week[0]) {
if (month === 11) {
return 0
}
return month + 1
} else {
return month
}
} else {
return month
}
} }
\ No newline at end of file
import { FormControlLabel, Grid, Switch } from "@mui/material"; import { Grid } from "@mui/material";
import { Box } from "@mui/system"; import { Box } from "@mui/system";
import { useCallback, useState } from "react";
import ModalTask from "../../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 HourFormatSwitch from "../../HourFormatSwitch/HourFormatSwitch";
import { getCurrentWeekDayString } from "./Helpers"; import CalendarColumnDayWeek from "./CalendarColumnDayWeek/CalendarColumnDayWeek";
import { getCurrentWeekDayString, getMonthToDayColumn } from "./Helpers";
function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, tasks }) { function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, tasks, currentTask, setCurrentTask, onChangeCurrentTaskHandler, deleteTaskHandler, sendNewTaskHandler, createTaskInCellHandler, copyTask, setCopyTask, createCopyTask }) {
const [modal, setModal] = useState({ open: false, y: 0, x: 0, });
const handleOpen = useCallback((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 = useCallback(() => {
setModal({ ...modal, open: false })
setCurrentTask({})
}, [setCurrentTask, modal]);
return ( return (
<> <>
...@@ -15,10 +36,9 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t ...@@ -15,10 +36,9 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t
<CalendarRow <CalendarRow
> >
<CalendarSmallCell xs={1}> <CalendarSmallCell xs={1}>
<FormControlLabel <HourFormatSwitch
control={<Switch color="primary" checked={hourFormat} onChange={() => { setHourFormat(() => !hourFormat) }} />} hourFormat={hourFormat}
label="1 час" setHourFormat={setHourFormat}
labelPlacement="end"
/> />
</CalendarSmallCell> </CalendarSmallCell>
{week?.map((weekDay, i) => { {week?.map((weekDay, i) => {
...@@ -47,16 +67,22 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t ...@@ -47,16 +67,22 @@ 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={getMonthToDayColumn(week, weekDay, date.month)}
year={date.year} year={date.year}
day={weekDay} day={weekDay}
hourFormat={hourFormat} hourFormat={hourFormat}
/> setCurrentTask={setCurrentTask}
</Grid> handleOpen={handleOpen}
createTaskInCellHandler={createTaskInCellHandler}
modal={modal.open}
copyTask={copyTask}
setCopyTask={setCopyTask}
createCopyTask={createCopyTask}
/>
) )
})} })}
</CalendarRow> </CalendarRow>
...@@ -65,6 +91,24 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t ...@@ -65,6 +91,24 @@ function WeekCalendarBody({ week, hoursInDay, hourFormat, setHourFormat, date, t
</CalendarRow> </CalendarRow>
</Grid> </Grid>
</Box> </Box>
<ModalTask
modal={modal}
handleClose={() => { handleClose() }}
week={true}
>
<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 { AppBar, Toolbar } from '@mui/material'; import { AppBar, Toolbar } from '@mui/material';
import { Box } from '@mui/system'; import { Box } from '@mui/system';
import { memo } from 'react';
import WeekCalendarHeaderInfo from './WeekCalendarHeaderInfo/WeekCalendarHeaderInfo'; import WeekCalendarHeaderInfo from './WeekCalendarHeaderInfo/WeekCalendarHeaderInfo';
...@@ -26,4 +27,4 @@ function WeekCalendarHeader({ decrementWeek, incrementWeek, weekInfo }) { ...@@ -26,4 +27,4 @@ function WeekCalendarHeader({ decrementWeek, incrementWeek, weekInfo }) {
); );
} }
export default WeekCalendarHeader; export default memo(WeekCalendarHeader);
\ No newline at end of file \ No newline at end of file
...@@ -2,6 +2,7 @@ import ArrowDecrementButton from '../../../../UI/ArrowDecrementButton/ArrowDecre ...@@ -2,6 +2,7 @@ import ArrowDecrementButton from '../../../../UI/ArrowDecrementButton/ArrowDecre
import ArrowIncrementButton from '../../../../UI/ArrowIncrementButton/ArrowIncrementButton'; import ArrowIncrementButton from '../../../../UI/ArrowIncrementButton/ArrowIncrementButton';
import { Box } from '@mui/system'; import { Box } from '@mui/system';
import { Typography } from '@mui/material'; import { Typography } from '@mui/material';
import { memo } from 'react';
...@@ -34,4 +35,4 @@ function WeekCalendarHeaderInfo({ decrementWeek, incrementWeek, weekInfo }) { ...@@ -34,4 +35,4 @@ function WeekCalendarHeaderInfo({ decrementWeek, incrementWeek, weekInfo }) {
); );
} }
export default WeekCalendarHeaderInfo; export default memo(WeekCalendarHeaderInfo);
\ No newline at end of file \ No newline at end of file
...@@ -77,7 +77,7 @@ const MemberForm = ({ onSubmit, members }) => { ...@@ -77,7 +77,7 @@ const MemberForm = ({ onSubmit, members }) => {
id="free-solo-demo" id="free-solo-demo"
freeSolo freeSolo
options={users} options={users}
getOptionLabel={(item) => item.displayName || ""} getOptionLabel={(item) => (members[0]?.user?.displayName !== item.displayName) ? (item.displayName || "") : ""}
onChange={memberChangeHandler} onChange={memberChangeHandler}
name={"userId"} name={"userId"}
value={state.user} value={state.user}
......
...@@ -41,7 +41,7 @@ const ProfileBlock = () => { ...@@ -41,7 +41,7 @@ const ProfileBlock = () => {
onClick={handleClick} onClick={handleClick}
id='test_greetings' id='test_greetings'
> >
Hello, {user?.displayName} Привет, {user?.displayName}
</Button> </Button>
<Menu <Menu
anchorEl={anchorEl} anchorEl={anchorEl}
...@@ -49,9 +49,9 @@ const ProfileBlock = () => { ...@@ -49,9 +49,9 @@ const ProfileBlock = () => {
onClose={handleClose} onClose={handleClose}
> >
<MenuItem component={NavLink} to="/profile/test" color="inherit" onClick={handleClose}>Profile</MenuItem> <MenuItem component={NavLink} to="/profile/test" color="inherit" onClick={handleClose}>Профиль</MenuItem>
<MenuItem onClick={()=>{switchUser()}}>Поменять юзера</MenuItem> <MenuItem onClick={()=>{switchUser()}}>Поменять юзера</MenuItem>
<MenuItem onClick={()=>{logout()}}>Logout</MenuItem> <MenuItem onClick={()=>{logout()}}>Выйти</MenuItem>
</Menu> </Menu>
<SwitchUserModal <SwitchUserModal
open={openSwitchUser} open={openSwitchUser}
......
...@@ -31,8 +31,11 @@ const ProjectForm = ({onSubmit}) => { ...@@ -31,8 +31,11 @@ const ProjectForm = ({onSubmit}) => {
e.preventDefault(); e.preventDefault();
let project = {title: state.title} let project = {title: state.title}
console.log(project); console.log(project);
onSubmit(project); if (project.title === "") {
alert("Нельзя создать проект без названия")
} else {
onSubmit(project);
}
}; };
const inputChangeHandler = (e) => { const inputChangeHandler = (e) => {
......
...@@ -25,7 +25,7 @@ const ProjectItem = ({ title, tasks, id }) => { ...@@ -25,7 +25,7 @@ const ProjectItem = ({ title, tasks, id }) => {
<CardActions> <CardActions>
<IconButton component={Link} to={"/projects/" + id}> <IconButton component={Link} to={"/projects/" + id}>
<ArrowForwardIcon /> <ArrowForwardIcon />
</IconButton> </IconButton>
</CardActions> </CardActions>
</Card> </Card>
</Grid> </Grid>
......
...@@ -5,7 +5,7 @@ import { useDispatch, useSelector } from "react-redux"; ...@@ -5,7 +5,7 @@ import { useDispatch, useSelector } from "react-redux";
import DeleteIcon from "@mui/icons-material/Delete"; import DeleteIcon from "@mui/icons-material/Delete";
import { deleteMember } from "../../../store/actions/projectsActions"; import { deleteMember } from "../../../store/actions/projectsActions";
const ProjectMembersItem = ({ displayName, roleProject, id, roleProjectOfAuthor, userId, members }) => { const ProjectMembersItem = ({ displayName, roleProject, id, roleProjectOfAuthor, userId, members, authorOfProject }) => {
console.log(displayName) console.log(displayName)
const dispatch = useDispatch(); const dispatch = useDispatch();
const user = useSelector(state => state.users) const user = useSelector(state => state.users)
...@@ -36,15 +36,14 @@ const ProjectMembersItem = ({ displayName, roleProject, id, roleProjectOfAuthor, ...@@ -36,15 +36,14 @@ const ProjectMembersItem = ({ displayName, roleProject, id, roleProjectOfAuthor,
</strong> </strong>
<strong> <strong>
{roleProjectOfAuthor === "admin" ? {(members.filter(e => e.user.displayName === authorOfProject).length > 0) ?
(<strong> (<strong>
<Tooltip title="Удалить"> <Tooltip title="Удалить">
<IconButton <IconButton
onClick={(id) => { onClick={(id) => {
deleteHandle(userId); deleteHandle(userId);
}} }}
> > {(displayName !== authorOfProject) ? <DeleteIcon style={{ marginTop: "-5px" }} /> : null}
<DeleteIcon style={{ marginTop: "-5px" }} />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</strong>) : null} </strong>) : null}
......
import {Grid} from "@mui/material"; import {Grid} from "@mui/material";
import ProjectMembersItem from "../ProjectMembersItem/ProjectMembersItem"; import ProjectMembersItem from "../ProjectMembersItem/ProjectMembersItem";
const ProjectMembersList = ({members, roleProjectOfAuthor}) => { const ProjectMembersList = ({members, roleProjectOfAuthor, authorOfProject}) => {
console.log("members ", members) console.log("members ", members)
return ( return (
<Grid item container direction="column" spacing={1}> <Grid item container direction="column" spacing={1}>
...@@ -14,6 +14,7 @@ const ProjectMembersList = ({members, roleProjectOfAuthor}) => { ...@@ -14,6 +14,7 @@ const ProjectMembersList = ({members, roleProjectOfAuthor}) => {
roleProjectOfAuthor={roleProjectOfAuthor} roleProjectOfAuthor={roleProjectOfAuthor}
userId={member?.user?.id} userId={member?.user?.id}
members={members} members={members}
authorOfProject={authorOfProject}
/> />
})} })}
</Grid> </Grid>
......
import { Autocomplete, TextField } from "@mui/material";
import { memo } from "react";
function CustomAutocomplete({ options, onChange, value, name, label, style, getOptionLabel }) {
return (<>
<Autocomplete
id={name}
freeSolo
options={options}
getOptionLabel={getOptionLabel}
onChange={(e, value) => { onChange(e, value) }}
name={name}
value={value}
renderInput={(params) => <TextField
style={style}
label={label}
state={value}
{...params} />}
/>
</>);
}
export default memo(CustomAutocomplete);
\ No newline at end of file
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
...@@ -60,7 +60,7 @@ const FullProject = () => { ...@@ -60,7 +60,7 @@ const FullProject = () => {
</div> </div>
<ProjectMembersList users={users} project={project} members={project?.project?.members} roleProjectOfAuthor={project?.project?.members[0]?.roleProject} /> <ProjectMembersList users={users} project={project} members={project?.project?.members} roleProjectOfAuthor={project?.project?.members[0]?.roleProject} authorOfProject={project?.project?.members[0]?.user.displayName}/>
</strong> </strong>
<strong> <strong>
<br></br> <br></br>
......
import { useEffect, useCallback, useState, useMemo } from 'react'; import { useEffect, useCallback, useState, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useNavigate, useParams } from 'react-router-dom';
import CalendarModalWorkerContent from '../../components/Calendars/CalendarModalWorkerContent/CalendarModalWorkerContent'; import CalendarModalWorkerContent from '../../components/Calendars/CalendarModalWorkerContent/CalendarModalWorkerContent';
import MonthCalendarBody from '../../components/Calendars/MonthCalendar/MonthCalendarBody/MonthCalendarBody'; import MonthCalendarBody from '../../components/Calendars/MonthCalendar/MonthCalendarBody/MonthCalendarBody';
import MonthCalendarHeader from '../../components/Calendars/MonthCalendar/MonthCalendarHeader/MonthCalendarHeader'; import MonthCalendarHeader from '../../components/Calendars/MonthCalendar/MonthCalendarHeader/MonthCalendarHeader';
...@@ -12,11 +11,10 @@ import { fetchCurrentCalendarDisplayName } from '../../store/actions/usersAction ...@@ -12,11 +11,10 @@ import { fetchCurrentCalendarDisplayName } from '../../store/actions/usersAction
function MonthCalendar() { function MonthCalendar() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate()
const { calendarTasks } = useSelector(state => state.tasks); const { calendarTasks } = useSelector(state => state.tasks);
const { user, currentCalendarDisplayName } = useSelector(state => state.users); const { user, currentCalendarDisplayName } = useSelector(state => state.users);
const { allUserProjects, project } = useSelector(state => state.projects) const { allUserProjects, project } = useSelector(state => state.projects)
const params = useParams()
const [hourFormat, setHourFormat] = useState(false); const [hourFormat, setHourFormat] = useState(false);
const [dateNow, setDateNow] = useState({ month: '', year: '' }) const [dateNow, setDateNow] = useState({ month: '', year: '' })
...@@ -25,6 +23,7 @@ function MonthCalendar() { ...@@ -25,6 +23,7 @@ function MonthCalendar() {
const [copyTask, setCopyTask] = useState(null) const [copyTask, setCopyTask] = useState(null)
const [cellSizes, setCellSizes] = useState({}) const [cellSizes, setCellSizes] = useState({})
const [userId, setUserId] = useState('') const [userId, setUserId] = useState('')
const [userCalendarId, setUserCalendarId] = useState(null)
const [modal, setModal] = useState(false) const [modal, setModal] = useState(false)
useEffect(() => { useEffect(() => {
...@@ -32,22 +31,25 @@ function MonthCalendar() { ...@@ -32,22 +31,25 @@ function MonthCalendar() {
month: new Date().getMonth(), month: new Date().getMonth(),
year: new Date().getFullYear(), year: new Date().getFullYear(),
}) })
if (params.id) { }, [dispatch])
setUserId(params.id)
dispatch(fetchCalendarTasks(params.id)) useEffect(() => {
dispatch(fetchCurrentCalendarDisplayName(params.id)) if (userCalendarId) {
setUserId(userCalendarId)
dispatch(fetchCalendarTasks(userCalendarId))
dispatch(fetchCurrentCalendarDisplayName(userCalendarId))
} else { } else {
setUserId(user.id) setUserId(user.id)
dispatch(fetchCalendarTasks(user.id)) dispatch(fetchCalendarTasks(user.id))
dispatch(fetchCurrentCalendarDisplayName(user.id)) dispatch(fetchCurrentCalendarDisplayName(user.id))
} }
}, [dispatch]) }, [userCalendarId, dispatch, user.id])
useEffect(() => { useEffect(() => {
if (workerInfo.project) { if (workerInfo.project) {
dispatch(fetchProject(workerInfo.project.id)) dispatch(fetchProject(workerInfo.project.id))
} }
}, [workerInfo.project]) }, [workerInfo.project, dispatch])
const hoursInDay = useMemo(() => { const hoursInDay = useMemo(() => {
let arr let arr
...@@ -120,7 +122,7 @@ function MonthCalendar() { ...@@ -120,7 +122,7 @@ function MonthCalendar() {
} }
}, []); }, []);
const createTaskInCellHandler = (dayNumber, dayHour) => { const createTaskInCellHandler = useCallback((dayNumber, dayHour) => {
let hour let hour
if (!isNaN(dayHour)) { if (!isNaN(dayHour)) {
hour = dayHour hour = dayHour
...@@ -146,9 +148,9 @@ function MonthCalendar() { ...@@ -146,9 +148,9 @@ function MonthCalendar() {
} }
} }
setCurrentTask((newTask)) setCurrentTask((newTask))
} }, [dateNow.month, dateNow.year, hourFormat])
const dragTaskHandler = async (dayNumber, hour) => { const dragTaskHandler = useCallback(async (dayNumber, hour) => {
const hourDiff = currentTask.infoForCell.endHour - currentTask.infoForCell.startHour const hourDiff = currentTask.infoForCell.endHour - currentTask.infoForCell.startHour
const lastHour = hoursInDay[hoursInDay.length - 1].split(':')[0] const lastHour = hoursInDay[hoursInDay.length - 1].split(':')[0]
let due let due
...@@ -168,9 +170,9 @@ function MonthCalendar() { ...@@ -168,9 +170,9 @@ function MonthCalendar() {
delete newTask.infoForCell delete newTask.infoForCell
await dispatch(editCalendarTask(newTask, currentTask.id, userId)) await dispatch(editCalendarTask(newTask, currentTask.id, userId))
setCurrentTask({}) setCurrentTask({})
} }, [currentTask, dateNow.month, dateNow.year, dispatch, hoursInDay, userId])
const sendNewTaskHandler = async () => { const sendNewTaskHandler = useCallback(async () => {
const timeEndHour = currentTask.infoForCell.endHour const timeEndHour = currentTask.infoForCell.endHour
const timeStartHour = currentTask.infoForCell.startHour const timeStartHour = currentTask.infoForCell.startHour
const day = currentTask.infoForCell.startDay const day = currentTask.infoForCell.startDay
...@@ -198,9 +200,9 @@ function MonthCalendar() { ...@@ -198,9 +200,9 @@ function MonthCalendar() {
delete newTask.id delete newTask.id
await dispatch(addCalendarTask(newTask, userId)) await dispatch(addCalendarTask(newTask, userId))
} }
} }, [currentTask, dateNow.month, dateNow.year, dispatch, user.id, userId])
const createCopyTask = async (dayNumber, hour) => { const createCopyTask = useCallback(async (dayNumber, hour) => {
const hourDiff = copyTask.infoForCell.endHour - copyTask.infoForCell.startHour const hourDiff = copyTask.infoForCell.endHour - copyTask.infoForCell.startHour
const lastHour = hoursInDay[hoursInDay.length - 1].split(':')[0] const lastHour = hoursInDay[hoursInDay.length - 1].split(':')[0]
let due let due
...@@ -220,35 +222,31 @@ function MonthCalendar() { ...@@ -220,35 +222,31 @@ function MonthCalendar() {
delete newTask.id delete newTask.id
await dispatch(addCopyCalendarTask(newTask, userId)) await dispatch(addCopyCalendarTask(newTask, userId))
setCopyTask(null) setCopyTask(null)
} }, [copyTask, dateNow.month, dateNow.year, dispatch, hoursInDay, userId])
const deleteTaskHandler = async (taskId) => { const deleteTaskHandler = useCallback(async (taskId) => {
dispatch(deleteCalendarTask(taskId, userId)) dispatch(deleteCalendarTask(taskId, userId))
} }, [dispatch, userId])
const handleClose = () => { const handleClose = useCallback(() => {
setModal(false) setModal(false)
setWorkerInfo({ project: '', worker: '' }) setWorkerInfo({ project: '', worker: '' })
} }, [])
const handleOpen = async () => {
const handleOpen = useCallback(async () => {
if (user.id === userId) { if (user.id === userId) {
await dispatch(fetchAllUserProjects()) await dispatch(fetchAllUserProjects())
setModal(true) setModal(true)
} else { } else {
navigate("/month") dispatch(setUserCalendarId(null))
setWorkerInfo({ project: '', worker: '' })
setUserId(user.id)
dispatch(fetchCalendarTasks(user.id))
dispatch(fetchCurrentCalendarDisplayName(user.id))
} }
} }, [dispatch, user.id, userId])
const onChangeCalendarUser = () => {
navigate(`/month/${workerInfo.worker.user.id}`) const onChangeCalendarUser = useCallback(() => {
setModal(false) setModal(false)
setUserId(workerInfo.worker.user.id) setUserCalendarId(workerInfo.worker.user.id)
dispatch(fetchCalendarTasks(workerInfo.worker.user.id)) setWorkerInfo({ project: '', worker: '' })
dispatch(fetchCurrentCalendarDisplayName(workerInfo.worker.user.id)) }, [workerInfo?.worker?.user?.id])
}
return ( return (
<> <>
......
...@@ -2,25 +2,29 @@ import moment from 'moment'; ...@@ -2,25 +2,29 @@ import moment from 'moment';
import { useEffect, useState, useMemo, useCallback } from 'react'; 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, addCopyCalendarTask, 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 [copyTask, setCopyTask] = useState(null)
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)
}, [dispatch, user.id])
const hoursInDay = useMemo(() => { const hoursInDay = useMemo(() => {
let arr let arr
...@@ -33,26 +37,132 @@ function WeekCalendar() { ...@@ -33,26 +37,132 @@ 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 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 weekInfo = useMemo(() => { const createTaskInCellHandler = useCallback((dayNumber, dayHour, month) => {
return getWeekInfoString(week, date) let hour
}, [date, week]) 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, month, dayNumber, hour, 0)),
dateTimeDue: dateToISOLikeButLocal(new Date(dateNow.year, month, dayNumber, hourDue, 59)),
infoForCell: {
startHour: hour,
endHour: hourDue,
startDay: dayNumber,
month: month
}
}
setCurrentTask((newTask))
}, [dateNow.month, dateNow.year, hourFormat])
const sendNewTaskHandler = useCallback(async () => {
const timeEndHour = currentTask.infoForCell.endHour
const timeStartHour = currentTask.infoForCell.startHour
const month = currentTask.infoForCell.month
const day = currentTask.infoForCell.startDay
const due = dateToISOLikeButLocal(new Date(dateNow.year, month, day, timeEndHour - 1, 59))
const start = dateToISOLikeButLocal(new Date(dateNow.year, 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))
}
}, [currentTask, dateNow.month, dateNow.year, dispatch, user.id, userId])
const createCopyTask = useCallback(async (dayNumber, hour, month) => {
const hourDiff = copyTask.infoForCell.endHour - copyTask.infoForCell.startHour
const lastHour = hoursInDay[hoursInDay.length - 1].split(':')[0]
let due
if (hour + hourDiff >= lastHour) {
due = dateToISOLikeButLocal(new Date(dateNow.year, month, dayNumber, lastHour, 59))
} else {
due = dateToISOLikeButLocal(new Date(dateNow.year, month, dayNumber, hour + hourDiff, 59))
}
const start = dateToISOLikeButLocal(new Date(dateNow.year, month, dayNumber, hour, 0))
const newTask = {
...copyTask,
dateTimeStart: start,
dateTimeDue: due,
taskId: copyTask.mainTaskId
}
delete newTask.infoForCell
delete newTask.id
await dispatch(addCopyCalendarTask(newTask, userId))
setCopyTask(null)
}, [copyTask, dateNow.month, dateNow.year, dispatch, hoursInDay, userId])
const deleteTaskHandler = useCallback(async (taskId) => {
dispatch(deleteCalendarTask(taskId, userId))
},[dispatch, userId])
return ( return (
<> <>
...@@ -62,12 +172,21 @@ function WeekCalendar() { ...@@ -62,12 +172,21 @@ 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}
createCopyTask={createCopyTask}
copyTask={copyTask}
setCopyTask={setCopyTask}
/> />
</> </>
); );
......
...@@ -183,4 +183,17 @@ export const getAvailableTasks = (tasks, year, month, dayNumber) => { ...@@ -183,4 +183,17 @@ export const getAvailableTasks = (tasks, year, month, dayNumber) => {
} else {return false} } else {return false}
}) })
return tasksInDay return tasksInDay
}
export const getColorTaskByPriority = (priority) => {
switch(priority) {
case 'A':
return 'rgb(32, 138, 250)';
case 'B':
return 'lightgreen';
case 'C':
return 'orange';
default:
return 'rgb(171, 157, 157)';
}
} }
\ No newline at end of file
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