diff --git a/src/components/SideBar/SideBar.tsx b/src/components/SideBar/SideBar.tsx
index 036954e..54a5229 100644
--- a/src/components/SideBar/SideBar.tsx
+++ b/src/components/SideBar/SideBar.tsx
@@ -12,8 +12,9 @@ import { lid } from 'assets/images'; // Initial image
import SideBarUser from 'components/SideBarUser/SideBarUser';
import SideBarUserMenu from 'components/SideBarUserMenu/SideBarUserMenu';
import NewEmployeePopup from 'components/Popup/NewEmployee/NewEmployee';
-import React, { useState } from 'react';
-import { useSelector } from 'services/hooks';
+import React, { KeyboardEvent, useState } from 'react';
+import { useDispatch, useSelector } from 'services/hooks';
+import { getAllTeamTasks } from 'store/tasksOfUserSlice';
import { TTask } from 'types/types';
import { v4 as uuidv4 } from 'uuid';
import styles from './SideBar.module.scss';
@@ -22,7 +23,7 @@ const SideBar: React.FC = () => {
const currentUser = useSelector((state) => state.user);
const tasks: TTask = useSelector((state) => state.task);
const currentUsers = useSelector((state) => state.users);
-
+ const dispatch = useDispatch();
const [isSidebarMenuOpen, setisSidebarMenuOpen] = useState(false);
const [isNewEmployeePopupOpen, setIsNewEmployeePopupOpen] = useState(false);
@@ -36,6 +37,13 @@ const SideBar: React.FC = () => {
const handleCancel = () => {
setIsNewEmployeePopupOpen(false);
+
+ const showAllTasks = () => dispatch(getAllTeamTasks());
+ const handleKeyDown = (evt: KeyboardEvent) => {
+ if (evt.key === 'Enter' || evt.key === ' ') {
+ evt.preventDefault();
+ showAllTasks();
+ }
};
return (
@@ -91,10 +99,16 @@ const SideBar: React.FC = () => {
- Вся команда
+
+ Вся команда
+
{currentUsers.results.map((user) => {
- return ;
+ return ;
})}
{isNewEmployeePopupOpen && }
diff --git a/src/components/SideBarUser/SideBarUser.tsx b/src/components/SideBarUser/SideBarUser.tsx
index 48d18d6..f2e80dc 100644
--- a/src/components/SideBarUser/SideBarUser.tsx
+++ b/src/components/SideBarUser/SideBarUser.tsx
@@ -1,16 +1,29 @@
import { lid } from 'assets/images'; // Initial image
-import React from 'react';
+import React, { KeyboardEvent } from 'react';
+import { useDispatch } from 'services/hooks';
+import { getUserTasks } from 'store/tasksOfUserSlice';
import styles from './SidebarUser.module.scss';
type Tprops = {
fullName: string;
+ id: number;
};
-const SideBarUser: React.FC = ({ fullName }) => {
+const SideBarUser: React.FC = ({ fullName, id }) => {
+ const dispatch = useDispatch();
+ const getTasks = () => dispatch(getUserTasks({ id }));
+ const handleKeyDown = (evt: KeyboardEvent) => {
+ if (evt.key === 'Enter' || evt.key === ' ') {
+ evt.preventDefault();
+ getTasks();
+ }
+ };
return (
- {fullName}
+
+ {fullName}
+
);
};
diff --git a/src/components/Task/Task.tsx b/src/components/Task/Task.tsx
index 6a9f8aa..7f34ac9 100644
--- a/src/components/Task/Task.tsx
+++ b/src/components/Task/Task.tsx
@@ -5,7 +5,6 @@ import { useSelector } from 'services/hooks';
import { resetActiveMenu, setActiveMenu } from 'store/taskMenuActiveSlice';
import EditButton from 'ui-lib/Buttons/editTaskButton/editTaskButton';
import { ClockIcon, CommentsIcon, FlagIcon } from 'ui-lib/Icons';
-import { TPerformers } from '../../types/types';
import styles from './Task.module.scss';
// содержимое карточки
@@ -13,24 +12,26 @@ export interface TaskProps {
text: string;
date: string;
headerText: string;
- isLead: boolean | null;
ownTask: boolean;
status: string;
taskID: number;
- performers: TPerformers[];
completedTime: string;
+ taskCreatorId: number;
+ isCurrentUserLead: boolean;
+ currentUserId: number;
}
export const Task: React.FC = ({
text,
date,
headerText,
- isLead,
ownTask,
status,
taskID,
- performers,
completedTime,
+ taskCreatorId,
+ isCurrentUserLead,
+ currentUserId,
}) => {
const [isMenuOpened, setIsMenuOpened] = React.useState(false);
const dispatch = useDispatch();
@@ -67,7 +68,7 @@ export const Task: React.FC = ({
return (
{/* Шапка отображается только для лида для не своей задачи */}
- {isLead && !ownTask && (
+ {isCurrentUserLead && currentUserId !== taskCreatorId && (
{headerText}
@@ -77,15 +78,16 @@ export const Task: React.FC
= ({
{/* Открытие меню редактирования */}
{isMenuOpened && (
)}
diff --git a/src/components/TaskEditMenu/TaskEditMenu.tsx b/src/components/TaskEditMenu/TaskEditMenu.tsx
index 959f122..420c613 100644
--- a/src/components/TaskEditMenu/TaskEditMenu.tsx
+++ b/src/components/TaskEditMenu/TaskEditMenu.tsx
@@ -1,42 +1,54 @@
/* eslint-disable jsx-a11y/label-has-associated-control */
import React from 'react';
+import { TaskStatus } from 'types/types';
import { UniversalButton } from 'ui-lib/Buttons';
import { BallpenIcon, TrashIcon } from 'ui-lib/Icons';
import { useClose, useDispatch } from '../../services/hooks';
import updateTaskThunk from '../../thunks/update-task-thunk';
-import { TPerformers } from '../../types/types';
import styles from './TaskEditMenu.module.scss';
// import { changeTaskStatus } from '../../store/taskSlice';
export interface TaskEditMenuProps {
- isLead: boolean | null;
ownTask: boolean;
handleToggleEditMenu: () => void;
handleCloseEditMenu: () => void;
status: string;
taskID: number;
- performers: TPerformers[];
deadlineDate: string;
description: string;
+ taskCreatorId: number;
+ isCurrentUserLead: boolean;
+ currentUserId: number;
}
export const TaskEditMenu: React.FC = ({
- isLead,
ownTask,
handleToggleEditMenu,
handleCloseEditMenu,
status,
- performers,
deadlineDate,
description,
taskID,
+ taskCreatorId,
+ isCurrentUserLead,
+ currentUserId,
}) => {
+ const [currentStatus, setStatus] = React.useState(status);
const dispatch = useDispatch();
useClose(styles.container, handleCloseEditMenu);
- const notOwnLeadTask = isLead && !ownTask;
- const notOwnPerformerTask = !isLead && !ownTask;
- const [currentStatus, setStatus] = React.useState(status);
+ const isTaskEditable = currentUserId === taskCreatorId;
+ const isStatusEditable = isTaskEditable || ownTask;
+
+ const isArchivedVisible =
+ status === TaskStatus.ARCHIVED || (status === TaskStatus.DONE && isCurrentUserLead);
+ const isHoldVisible = status === TaskStatus.HOLD || status === TaskStatus.IN_PROGRESS;
+ const isDoneVisible = status === TaskStatus.DONE || status === TaskStatus.IN_PROGRESS;
+ const isInProgressVisible =
+ status === TaskStatus.IN_PROGRESS || status === TaskStatus.TO_DO;
+ const isToDoVisible =
+ status === TaskStatus.TO_DO || (status === TaskStatus.ARCHIVED && isCurrentUserLead);
+
const onChange = (evt: React.ChangeEvent) => {
setStatus(evt.target.value);
};
@@ -66,8 +78,7 @@ export const TaskEditMenu: React.FC = ({
{/* Кнопки отображаются у лида для задачи сотруднику, */}
{/* а также у лида и сотрудника для своей задачи */}
- {/* как применить условие ИЛИ? */}
- {(notOwnLeadTask || ownTask) && (
+ {isTaskEditable && (
= ({
Редактировать
-
-
- Удалить
-
+ {(status === TaskStatus.DONE || status === TaskStatus.ARCHIVED) && (
+
+
+ Удалить
+
+ )}
)}
{/* Смена статуса отображаются для своих задач */}
{/* и задачи у сотрудника от лида */}
- {(notOwnPerformerTask || ownTask) && (
+ {isStatusEditable && (
)}
@@ -75,12 +79,19 @@ interface ITaskCard {
allTasks: TTask;
}
-const Lead: FC = (props) => {
- const { allTasks } = props;
+const Lead: FC = ({ allTasks }) => {
const { count, results } = allTasks;
const dispatch = useDispatch();
const currentUser = useSelector((state) => state.user);
-
+ const tasksOfUserId = useSelector((state) => state.tasksOfUser).id;
+ const resultsToRender = useMemo(
+ () =>
+ tasksOfUserId !== -1
+ ? results.filter((task) => handleCheckIfTaskForMe(tasksOfUserId, task.performers))
+ : results,
+ [results, tasksOfUserId]
+ );
+ console.log(resultsToRender);
const openCreateTask = () => {
dispatch(openCreateTaskModal());
};
@@ -97,17 +108,17 @@ const Lead: FC = (props) => {
const done: TResults[] = [];
const hold: TResults[] = [];
// eslint-disable-next-line no-plusplus
- for (let i = 0; i < results.length; i++) {
- if (results[i].status === 'to do') {
- todo.push(results[i]);
+ for (let i = 0; i < resultsToRender.length; i++) {
+ if (resultsToRender[i].status === TaskStatus.TO_DO) {
+ todo.push(resultsToRender[i]);
}
- if (results[i].status === 'in progress') {
- inProgress.push(results[i]);
+ if (resultsToRender[i].status === TaskStatus.IN_PROGRESS) {
+ inProgress.push(resultsToRender[i]);
}
- if (results[i].status === 'done') {
- done.push(results[i]);
+ if (resultsToRender[i].status === TaskStatus.DONE) {
+ done.push(resultsToRender[i]);
}
- if (results[i].status === 'hold') {
+ if (resultsToRender[i].status === TaskStatus.HOLD) {
hold.push(results[i]);
}
}
@@ -116,18 +127,13 @@ const Lead: FC = (props) => {
setDoneTasks(done);
setHoldTasks(hold);
};
- // Проверка есть ли текущий пользователь в списке
- const handleCheckTaskOwner = (performers: TPerformers[]) => {
- const res = performers.filter((user) => user.full_name === currentUser.full_name);
- return res.length > 0;
- };
useEffect(() => {
- if (results.length >= 1) {
- parseTasks();
- }
+ parseTasks();
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [results]);
+ }, [resultsToRender]);
+
+ const onDragStart = () => dispatch(resetActiveMenu());
const onDragEnd = (result: any) => {
const { source, destination, draggableId } = result;
@@ -143,6 +149,28 @@ const Lead: FC = (props) => {
);
const item = allTasks.results[itemIndex];
+ const { status } = item;
+ const isCurrentUserLead = currentUser.is_team_lead;
+
+ const canDragToInProgress =
+ status === TaskStatus.TO_DO && dInd === TaskStatus.IN_PROGRESS;
+ const canDragToToDo =
+ status === TaskStatus.ARCHIVED && isCurrentUserLead && dInd === TaskStatus.TO_DO;
+ const canDragToDone = status === TaskStatus.IN_PROGRESS && dInd === TaskStatus.DONE;
+ const canDragToHold = status === TaskStatus.IN_PROGRESS && dInd === TaskStatus.HOLD;
+ const canDragToArchived =
+ status === TaskStatus.DONE && isCurrentUserLead && dInd === TaskStatus.ARCHIVED;
+
+ if (
+ !canDragToToDo &&
+ !canDragToInProgress &&
+ !canDragToDone &&
+ !canDragToHold &&
+ !canDragToArchived
+ ) {
+ return;
+ }
+
const updateTaskStatus = () => {
dispatch(
updateTaskThunk({
@@ -175,27 +203,11 @@ const Lead: FC = (props) => {
-
-
-
-
-
+
+
+
+
+
diff --git a/src/pages/Main/Main.tsx b/src/pages/Main/Main.tsx
index 5f9bc41..5d2cfaa 100644
--- a/src/pages/Main/Main.tsx
+++ b/src/pages/Main/Main.tsx
@@ -12,7 +12,7 @@ const Main = () => {
const [isUpdated, setIsUpdated] = useState(false);
const dispatch = useDispatch();
const { isLoggedIn } = useSelector((state) => state.system);
- const isLead = useSelector((state) => state.user);
+ const isLead = useSelector((state) => state.user).is_team_lead;
const tasks: TTask = useSelector((state) => state.task);
useEffect(() => {
diff --git a/src/pages/Tasks/Tasks.tsx b/src/pages/Tasks/Tasks.tsx
index 36413a7..c2b7426 100644
--- a/src/pages/Tasks/Tasks.tsx
+++ b/src/pages/Tasks/Tasks.tsx
@@ -1,9 +1,7 @@
import { FC } from 'react';
-import { v4 as uuidv4 } from 'uuid';
-import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
import styles from './Tasks.module.scss';
-import { TaskProps, Task } from '../../components/Task/Task';
+import { Task, TaskProps } from '../../components/Task/Task';
import { TaskStateProps } from '../../components/TaskState/TaskState';
const Tasks: FC = (props) => {
diff --git a/src/services/functions.ts b/src/services/functions.ts
new file mode 100644
index 0000000..3adc7e5
--- /dev/null
+++ b/src/services/functions.ts
@@ -0,0 +1,7 @@
+import { TPerformers } from 'types/types';
+
+// Проверка есть ли текущий пользователь в списке
+export const handleCheckIfTaskForMe = (id: number, performers: TPerformers[]) => {
+ const res = performers.filter((user) => user.id === id);
+ return res.length > 0;
+};
diff --git a/src/store/store.ts b/src/store/store.ts
index fa2e5b0..0fccff4 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -5,6 +5,7 @@ import modalReducer from './modalSlice';
import systemReducer from './systemSlice';
import { taskMenuActiveReducer } from './taskMenuActiveSlice';
import taskReducer from './taskSlice';
+import { tasksOfUserSliceReducer } from './tasksOfUserSlice';
import userReducer from './userSlice';
import usersReducer from './usersSlice';
@@ -17,6 +18,7 @@ const store = configureStore({
modals: modalReducer,
createTask: createTaskReducer,
taskMenuActive: taskMenuActiveReducer,
+ tasksOfUser: tasksOfUserSliceReducer,
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(thunk),
// eslint-disable-next-line no-undef
diff --git a/src/store/tasksOfUserSlice.ts b/src/store/tasksOfUserSlice.ts
new file mode 100644
index 0000000..7859cf9
--- /dev/null
+++ b/src/store/tasksOfUserSlice.ts
@@ -0,0 +1,19 @@
+import { createSlice } from '@reduxjs/toolkit';
+
+const initialState = { id: -1 };
+
+const tasksOfUserSlice = createSlice({
+ name: 'tasksOfUser',
+ initialState,
+ reducers: {
+ getUserTasks: (state, { payload: { id } }: { payload: { id: number } }) => {
+ state.id = id;
+ },
+ getAllTeamTasks: (state) => {
+ state.id = initialState.id;
+ },
+ },
+});
+
+export const tasksOfUserSliceReducer = tasksOfUserSlice.reducer;
+export const { getUserTasks, getAllTeamTasks } = tasksOfUserSlice.actions;
diff --git a/src/types/types.ts b/src/types/types.ts
index f56b7bf..a8058ce 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -21,7 +21,7 @@ export type TUser2 = {
last_name: string;
telegram_nickname: string;
username: string | null;
- id: string;
+ id: number;
};
export type Tusers = {
@@ -80,3 +80,11 @@ export type TCreateTask = {
link: string;
performers: number[];
};
+
+export enum TaskStatus {
+ TO_DO = 'to do',
+ IN_PROGRESS = 'in progress',
+ HOLD = 'hold',
+ DONE = 'done',
+ ARCHIVED = 'archived',
+}