From 009850c744b34c31ec804a15266df94b7c947cde Mon Sep 17 00:00:00 2001 From: surinkwon Date: Wed, 7 Aug 2024 21:44:57 +0900 Subject: [PATCH 1/7] =?UTF-8?q?fix:=20=EC=97=90=ED=94=BD=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=EA=B0=80=20=EC=9E=88=EC=96=B4=EB=8F=84=20=ED=99=94?= =?UTF-8?q?=EC=82=B4=ED=91=9C=EA=B0=80=20=ED=9A=8C=EC=83=89=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=82=98=ED=83=80=EB=82=98=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/backlog/EpicPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/backlog/EpicPage.tsx b/frontend/src/pages/backlog/EpicPage.tsx index bef7450..17f1258 100644 --- a/frontend/src/pages/backlog/EpicPage.tsx +++ b/frontend/src/pages/backlog/EpicPage.tsx @@ -27,7 +27,7 @@ const EpicPage = () => { {...backlog.epicList.map( ({ id: epicId, name, color, rankValue, storyList }) => ( 1} + storyExist={storyList.length > 0} epic={{ id: epicId, name, color, rankValue }} > {...storyList.map(({ id, title, point, status, taskList }) => { From 6b05d821c0a164d8bb3f9cabb995c73e3c7a6890 Mon Sep 17 00:00:00 2001 From: surinkwon Date: Thu, 8 Aug 2024 21:38:55 +0900 Subject: [PATCH 2/7] =?UTF-8?q?refactor:=20DragContainer=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20=EB=93=9C=EB=9E=98?= =?UTF-8?q?=EA=B7=B8=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/backlog/DragContainer.tsx | 36 +++++++++++++++++++ .../src/components/backlog/StoryBlock.tsx | 13 ++++--- .../src/pages/backlog/UnfinishedStoryPage.tsx | 31 ++++++---------- 3 files changed, 56 insertions(+), 24 deletions(-) create mode 100644 frontend/src/components/backlog/DragContainer.tsx diff --git a/frontend/src/components/backlog/DragContainer.tsx b/frontend/src/components/backlog/DragContainer.tsx new file mode 100644 index 0000000..b91ec46 --- /dev/null +++ b/frontend/src/components/backlog/DragContainer.tsx @@ -0,0 +1,36 @@ +import React, { DragEvent } from "react"; + +interface DragContainerProps { + index: number; + setRef: (index: number) => (element: HTMLDivElement) => void; + onDragStart: () => void; + onDragEnd: (event: DragEvent) => void; + currentlyDraggedOver: boolean; + children: React.ReactNode; +} + +const DragContainer = ({ + index, + setRef, + onDragStart, + onDragEnd, + currentlyDraggedOver, + children, +}: DragContainerProps) => ( +
+
+ {children} +
+); + +export default DragContainer; diff --git a/frontend/src/components/backlog/StoryBlock.tsx b/frontend/src/components/backlog/StoryBlock.tsx index 6bc9e0d..23ff2ad 100644 --- a/frontend/src/components/backlog/StoryBlock.tsx +++ b/frontend/src/components/backlog/StoryBlock.tsx @@ -1,7 +1,11 @@ import { Socket } from "socket.io-client"; import { useOutletContext } from "react-router-dom"; import useShowDetail from "../../hooks/pages/backlog/useShowDetail"; -import { BacklogStatusType, EpicCategoryDTO } from "../../types/DTO/backlogDTO"; +import { + BacklogStatusType, + EpicCategoryDTO, + TaskDTO, +} from "../../types/DTO/backlogDTO"; import BacklogStatusChip from "./BacklogStatusChip"; import CategoryChip from "./CategoryChip"; import ChevronDown from "../../assets/icons/chevron-down.svg?react"; @@ -19,6 +23,7 @@ import { useModal } from "../../hooks/common/modal/useModal"; import ConfirmModal from "../common/ConfirmModal"; import EpicDropdown from "./EpicDropdown"; import TaskCreateBlock from "./TaskCreateBlock"; +import TaskBlock from "./TaskBlock"; interface StoryBlockProps { id: number; @@ -27,11 +32,11 @@ interface StoryBlockProps { point: number | null; progress: number; status: BacklogStatusType; - children: React.ReactNode; taskExist: boolean; epicList?: EpicCategoryDTO[]; finished?: boolean; lastTaskRankValue?: string; + taskList: TaskDTO[]; } const StoryBlock = ({ @@ -45,7 +50,7 @@ const StoryBlock = ({ epicList, finished = false, lastTaskRankValue, - children, + taskList, }: StoryBlockProps) => { const { socket }: { socket: Socket } = useOutletContext(); const { showDetail, handleShowDetail } = useShowDetail(); @@ -283,7 +288,7 @@ const StoryBlock = ({ {showDetail && ( - {children} + {...taskList.map((task) => )} {!finished && ( )} diff --git a/frontend/src/pages/backlog/UnfinishedStoryPage.tsx b/frontend/src/pages/backlog/UnfinishedStoryPage.tsx index 4847143..9b0a83f 100644 --- a/frontend/src/pages/backlog/UnfinishedStoryPage.tsx +++ b/frontend/src/pages/backlog/UnfinishedStoryPage.tsx @@ -1,17 +1,17 @@ +import { DragEvent, useEffect, useMemo, useRef, useState } from "react"; import { useOutletContext } from "react-router-dom"; import { Socket } from "socket.io-client"; import { LexoRank } from "lexorank"; -import { BacklogDTO } from "../../types/DTO/backlogDTO"; import StoryCreateButton from "../../components/backlog/StoryCreateButton"; import StoryCreateForm from "../../components/backlog/StoryCreateForm"; -import { DragEvent, useEffect, useMemo, useRef, useState } from "react"; -import changeEpicListToStoryList from "../../utils/changeEpicListToStoryList"; import StoryBlock from "../../components/backlog/StoryBlock"; -import TaskBlock from "../../components/backlog/TaskBlock"; import useShowDetail from "../../hooks/pages/backlog/useShowDetail"; import useStoryEmitEvent from "../../hooks/pages/backlog/useStoryEmitEvent"; +import changeEpicListToStoryList from "../../utils/changeEpicListToStoryList"; import getDragElementIndex from "../../utils/getDragElementIndex"; import { BacklogSocketData } from "../../types/common/backlog"; +import { BacklogDTO } from "../../types/DTO/backlogDTO"; +import DragContainer from "../../components/backlog/DragContainer"; const UnfinishedStoryPage = () => { const { socket, backlog }: { socket: Socket; backlog: BacklogDTO } = @@ -140,22 +140,15 @@ const UnfinishedStoryPage = () => { : 0; return ( -
handleDragStart(id)} onDragEnd={handleDragEnd} + currentlyDraggedOver={index === storyElementIndex} > -
0} epicList={epicCategoryList} lastTaskRankValue={ @@ -163,10 +156,8 @@ const UnfinishedStoryPage = () => { ? taskList[taskList.length - 1].rankValue : undefined } - > - {...taskList.map((task) => )} - -
+ /> + ); } )} From 1ddcf277915cfc4200a1baed70e2ce7249d49562 Mon Sep 17 00:00:00 2001 From: surinkwon Date: Sat, 10 Aug 2024 17:13:02 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=ED=83=9C=EC=8A=A4=ED=81=AC=20?= =?UTF-8?q?=EB=93=9C=EB=9E=98=EA=B7=B8=20=EC=95=A4=20=EB=93=9C=EB=A1=AD=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/backlog/StoryBlock.tsx | 43 ++--- ...agContainer.tsx => StoryDragContainer.tsx} | 8 +- .../components/backlog/TaskDragContainer.tsx | 41 +++++ .../src/pages/backlog/UnfinishedStoryPage.tsx | 152 ++++++++++++++---- 4 files changed, 179 insertions(+), 65 deletions(-) rename frontend/src/components/backlog/{DragContainer.tsx => StoryDragContainer.tsx} (82%) create mode 100644 frontend/src/components/backlog/TaskDragContainer.tsx diff --git a/frontend/src/components/backlog/StoryBlock.tsx b/frontend/src/components/backlog/StoryBlock.tsx index 23ff2ad..fab109e 100644 --- a/frontend/src/components/backlog/StoryBlock.tsx +++ b/frontend/src/components/backlog/StoryBlock.tsx @@ -1,29 +1,21 @@ +import { MouseEvent } from "react"; import { Socket } from "socket.io-client"; import { useOutletContext } from "react-router-dom"; -import useShowDetail from "../../hooks/pages/backlog/useShowDetail"; -import { - BacklogStatusType, - EpicCategoryDTO, - TaskDTO, -} from "../../types/DTO/backlogDTO"; +import EpicDropdown from "./EpicDropdown"; import BacklogStatusChip from "./BacklogStatusChip"; import CategoryChip from "./CategoryChip"; -import ChevronDown from "../../assets/icons/chevron-down.svg?react"; -import ChevronRight from "../../assets/icons/chevron-right.svg?react"; -import TaskContainer from "./TaskContainer"; -import TaskHeader from "./TaskHeader"; import BacklogStatusDropdown from "./BacklogStatusDropdown"; -import useStoryEmitEvent from "../../hooks/pages/backlog/useStoryEmitEvent"; +import ConfirmModal from "../common/ConfirmModal"; +import useShowDetail from "../../hooks/pages/backlog/useShowDetail"; import useBacklogInputChange from "../../hooks/pages/backlog/useBacklogInputChange"; -import { MouseEvent } from "react"; -import { MOUSE_KEY } from "../../constants/event"; +import useStoryEmitEvent from "../../hooks/pages/backlog/useStoryEmitEvent"; import useDropdownState from "../../hooks/common/dropdown/useDropdownState"; -import TrashCan from "../../assets/icons/trash-can.svg?react"; import { useModal } from "../../hooks/common/modal/useModal"; -import ConfirmModal from "../common/ConfirmModal"; -import EpicDropdown from "./EpicDropdown"; -import TaskCreateBlock from "./TaskCreateBlock"; -import TaskBlock from "./TaskBlock"; +import ChevronRight from "../../assets/icons/chevron-right.svg?react"; +import ChevronDown from "../../assets/icons/chevron-down.svg?react"; +import TrashCan from "../../assets/icons/trash-can.svg?react"; +import { MOUSE_KEY } from "../../constants/event"; +import { BacklogStatusType, EpicCategoryDTO } from "../../types/DTO/backlogDTO"; interface StoryBlockProps { id: number; @@ -34,9 +26,6 @@ interface StoryBlockProps { status: BacklogStatusType; taskExist: boolean; epicList?: EpicCategoryDTO[]; - finished?: boolean; - lastTaskRankValue?: string; - taskList: TaskDTO[]; } const StoryBlock = ({ @@ -48,9 +37,6 @@ const StoryBlock = ({ status, taskExist, epicList, - finished = false, - lastTaskRankValue, - taskList, }: StoryBlockProps) => { const { socket }: { socket: Socket } = useOutletContext(); const { showDetail, handleShowDetail } = useShowDetail(); @@ -285,15 +271,6 @@ const StoryBlock = ({
)} - {showDetail && ( - - - {...taskList.map((task) => )} - {!finished && ( - - )} - - )} ); }; diff --git a/frontend/src/components/backlog/DragContainer.tsx b/frontend/src/components/backlog/StoryDragContainer.tsx similarity index 82% rename from frontend/src/components/backlog/DragContainer.tsx rename to frontend/src/components/backlog/StoryDragContainer.tsx index b91ec46..8964258 100644 --- a/frontend/src/components/backlog/DragContainer.tsx +++ b/frontend/src/components/backlog/StoryDragContainer.tsx @@ -1,6 +1,6 @@ import React, { DragEvent } from "react"; -interface DragContainerProps { +interface StoryDragContainerProps { index: number; setRef: (index: number) => (element: HTMLDivElement) => void; onDragStart: () => void; @@ -9,14 +9,14 @@ interface DragContainerProps { children: React.ReactNode; } -const DragContainer = ({ +const StoryDragContainer = ({ index, setRef, onDragStart, onDragEnd, currentlyDraggedOver, children, -}: DragContainerProps) => ( +}: StoryDragContainerProps) => (
); -export default DragContainer; +export default StoryDragContainer; diff --git a/frontend/src/components/backlog/TaskDragContainer.tsx b/frontend/src/components/backlog/TaskDragContainer.tsx new file mode 100644 index 0000000..3c532d1 --- /dev/null +++ b/frontend/src/components/backlog/TaskDragContainer.tsx @@ -0,0 +1,41 @@ +import { DragEvent } from "react"; + +interface TaskDragContainerProps { + storyIndex: number; + taskIndex: number; + setRef: ( + storyIndex: number, + taskIndex: number + ) => (element: HTMLDivElement) => void; + onDragStart: () => void; + onDragEnd: (event: DragEvent) => void; + currentlyDraggedOver: boolean; + children: React.ReactNode; +} + +const TaskDragContainer = ({ + storyIndex, + taskIndex, + setRef, + onDragStart, + onDragEnd, + currentlyDraggedOver, + children, +}: TaskDragContainerProps) => ( +
+
+ {children} +
+); + +export default TaskDragContainer; diff --git a/frontend/src/pages/backlog/UnfinishedStoryPage.tsx b/frontend/src/pages/backlog/UnfinishedStoryPage.tsx index 9b0a83f..c157674 100644 --- a/frontend/src/pages/backlog/UnfinishedStoryPage.tsx +++ b/frontend/src/pages/backlog/UnfinishedStoryPage.tsx @@ -11,15 +11,29 @@ import changeEpicListToStoryList from "../../utils/changeEpicListToStoryList"; import getDragElementIndex from "../../utils/getDragElementIndex"; import { BacklogSocketData } from "../../types/common/backlog"; import { BacklogDTO } from "../../types/DTO/backlogDTO"; -import DragContainer from "../../components/backlog/DragContainer"; +import StoryDragContainer from "../../components/backlog/StoryDragContainer"; +import TaskBlock from "../../components/backlog/TaskBlock"; +import TaskDragContainer from "../../components/backlog/TaskDragContainer"; +import TaskContainer from "../../components/backlog/TaskContainer"; +import TaskHeader from "../../components/backlog/TaskHeader"; +import TaskCreateBlock from "../../components/backlog/TaskCreateBlock"; const UnfinishedStoryPage = () => { const { socket, backlog }: { socket: Socket; backlog: BacklogDTO } = useOutletContext(); const { showDetail, handleShowDetail } = useShowDetail(); const [storyElementIndex, setStoryElementIndex] = useState(); + const [taskElementIndex, setTaskElementIndex] = useState<{ + storyId?: number; + taskIndex?: number; + }>({ + storyId: undefined, + taskIndex: undefined, + }); + const [draggingStoryId, setDraggingStoryId] = useState(); + const [draggingTaskId, setDraggingTaskId] = useState(); const storyComponentRefList = useRef([]); - const draggingComponentIdRef = useRef(); + const taskComponentRefList = useRef([]); const storyList = useMemo( () => changeEpicListToStoryList(backlog.epicList) @@ -51,11 +65,20 @@ const UnfinishedStoryPage = () => { storyComponentRefList.current[index] = element; }; + const setTaskComponentRef = + (storyIndex: number, taskIndex: number) => (element: HTMLDivElement) => { + taskComponentRefList.current[storyIndex][taskIndex] = element; + }; + const handleDragOver = (event: DragEvent) => { + if (draggingTaskId) { + return; + } + event.preventDefault(); const index = getDragElementIndex( storyComponentRefList.current, - draggingComponentIdRef.current, + storyList.findIndex(({ id }) => id === draggingStoryId), event.clientY ); @@ -63,18 +86,23 @@ const UnfinishedStoryPage = () => { }; const handleDragStart = (id: number) => { - draggingComponentIdRef.current = id; + if (draggingTaskId) { + return; + } + setDraggingStoryId(id); }; const handleDragEnd = (event: DragEvent) => { + if (draggingTaskId) { + return; + } + event.stopPropagation(); - const targetIndex = storyList.findIndex( - ({ id }) => id === draggingComponentIdRef.current - ); + const targetIndex = storyList.findIndex(({ id }) => id === draggingStoryId); let rankValue; if (storyElementIndex === targetIndex) { - draggingComponentIdRef.current = undefined; + setDraggingStoryId(undefined); setStoryElementIndex(undefined); return; } @@ -96,11 +124,11 @@ const UnfinishedStoryPage = () => { } emitStoryUpdateEvent({ - id: draggingComponentIdRef.current as number, + id: draggingStoryId as number, rankValue, }); - draggingComponentIdRef.current = undefined; + setDraggingStoryId(undefined); setStoryElementIndex(undefined); }; @@ -113,7 +141,7 @@ const UnfinishedStoryPage = () => { if ( domain === "story" && action === "delete" && - content.id === draggingComponentIdRef.current + content.id === draggingStoryId ) { setStoryElementIndex(undefined); } @@ -126,6 +154,37 @@ const UnfinishedStoryPage = () => { }; }, []); + const handleTaskDragOver = (event: DragEvent, storyIndex: number) => { + if (draggingStoryId) { + return; + } + + event.preventDefault(); + const mouseIndex = storyList[storyIndex].taskList.findIndex( + ({ id }) => id === draggingTaskId + ); + + const index = getDragElementIndex( + taskComponentRefList.current[storyIndex], + mouseIndex, + event.clientY + ); + + setTaskElementIndex({ + storyId: storyList[storyIndex].id, + taskIndex: index, + }); + }; + + const handleTaskDragStart = (taskId: number) => { + setDraggingTaskId(taskId); + }; + + const handleTaskDragEnd = () => { + setDraggingTaskId(undefined); + setTaskElementIndex({ storyId: undefined, taskIndex: undefined }); + }; + return (
@@ -138,26 +197,63 @@ const UnfinishedStoryPage = () => { 100 ) : 0; + taskComponentRefList.current[index] = []; return ( - handleDragStart(id)} - onDragEnd={handleDragEnd} - currentlyDraggedOver={index === storyElementIndex} +
handleTaskDragOver(event, index)} > - 0} - epicList={epicCategoryList} - lastTaskRankValue={ - taskList.length - ? taskList[taskList.length - 1].rankValue - : undefined - } - /> - + handleDragStart(id)} + onDragEnd={handleDragEnd} + currentlyDraggedOver={index === storyElementIndex} + > + 0} + epicList={epicCategoryList} + /> + + + + {...taskList.map((task, taskIndex) => ( + handleTaskDragStart(task.id)} + currentlyDraggedOver={ + id === taskElementIndex.storyId && + taskIndex === taskElementIndex.taskIndex + } + > + + + ))} +
+ + +
); } )} From 9c202510e16de8881d4f1fd44c41566c7b8cabec Mon Sep 17 00:00:00 2001 From: surinkwon Date: Mon, 12 Aug 2024 17:24:31 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=ED=83=9C=EC=8A=A4=ED=81=AC=20?= =?UTF-8?q?=EC=9A=B0=EC=84=A0=EC=88=9C=EC=9C=84=20=EB=B3=80=EA=B2=BD=20API?= =?UTF-8?q?=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hooks/pages/backlog/useBacklogSocket.ts | 52 +++++++++++++++- .../src/pages/backlog/UnfinishedStoryPage.tsx | 60 ++++++++++++++++++- 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/frontend/src/hooks/pages/backlog/useBacklogSocket.ts b/frontend/src/hooks/pages/backlog/useBacklogSocket.ts index b18d3c9..30838fc 100644 --- a/frontend/src/hooks/pages/backlog/useBacklogSocket.ts +++ b/frontend/src/hooks/pages/backlog/useBacklogSocket.ts @@ -78,7 +78,7 @@ const useBacklogSocket = (socket: Socket) => { if (content.epicId) { setBacklog((prevBacklog) => { let targetStory: StoryDTO | null = null; - backlog.epicList.some((epic) => { + prevBacklog.epicList.some((epic) => { const foundStory = epic.storyList.find( (story) => story.id === content.id ); @@ -168,6 +168,56 @@ const useBacklogSocket = (socket: Socket) => { }); break; case BacklogSocketTaskAction.UPDATE: + if (content.storyId) { + setBacklog((prevBacklog) => { + let targetTask: TaskDTO | null = null; + prevBacklog.epicList.some((epic) => { + epic.storyList.some((story) => { + const foundTask = story.taskList.find( + (task) => task.id === content.id + ); + + if (foundTask) { + targetTask = { ...foundTask }; + return true; + } + + return false; + }); + + if (targetTask) { + return true; + } + + return false; + }); + + if (!targetTask) { + return prevBacklog; + } + + const newEpicList = prevBacklog.epicList.map((epic) => { + const newStoryList = epic.storyList.map((story) => { + const newTaskList = story.taskList.filter( + (task) => task.id !== content.id + ); + + if (story.id === content.storyId) { + newTaskList.push({ + ...targetTask, + ...content, + } as TaskDTO); + } + return { ...story, taskList: newTaskList }; + }); + + return { ...epic, storyList: newStoryList }; + }); + return { epicList: newEpicList }; + }); + break; + } + setBacklog((prevBacklog) => { const newEpicList = prevBacklog.epicList.map((epic) => { const newStoryList = epic.storyList.map((story) => { diff --git a/frontend/src/pages/backlog/UnfinishedStoryPage.tsx b/frontend/src/pages/backlog/UnfinishedStoryPage.tsx index c157674..b7e73d9 100644 --- a/frontend/src/pages/backlog/UnfinishedStoryPage.tsx +++ b/frontend/src/pages/backlog/UnfinishedStoryPage.tsx @@ -10,13 +10,14 @@ import useStoryEmitEvent from "../../hooks/pages/backlog/useStoryEmitEvent"; import changeEpicListToStoryList from "../../utils/changeEpicListToStoryList"; import getDragElementIndex from "../../utils/getDragElementIndex"; import { BacklogSocketData } from "../../types/common/backlog"; -import { BacklogDTO } from "../../types/DTO/backlogDTO"; +import { BacklogDTO, TaskDTO } from "../../types/DTO/backlogDTO"; import StoryDragContainer from "../../components/backlog/StoryDragContainer"; import TaskBlock from "../../components/backlog/TaskBlock"; import TaskDragContainer from "../../components/backlog/TaskDragContainer"; import TaskContainer from "../../components/backlog/TaskContainer"; import TaskHeader from "../../components/backlog/TaskHeader"; import TaskCreateBlock from "../../components/backlog/TaskCreateBlock"; +import useTaskEmitEvent from "../../hooks/pages/backlog/useTaskEmitEvent"; const UnfinishedStoryPage = () => { const { socket, backlog }: { socket: Socket; backlog: BacklogDTO } = @@ -37,6 +38,20 @@ const UnfinishedStoryPage = () => { const storyList = useMemo( () => changeEpicListToStoryList(backlog.epicList) + .filter(({ status }) => status !== "완료") + .map((story) => { + const newTaskList = story.taskList.slice(); + newTaskList.sort((taskA, taskB) => { + if (taskA.rankValue < taskB.rankValue) { + return -1; + } + if (taskA.rankValue > taskB.rankValue) { + return 1; + } + return 0; + }); + return { ...story, taskList: newTaskList }; + }) .sort((storyA, storyB) => { if (storyA.rankValue < storyB.rankValue) { return -1; @@ -45,8 +60,7 @@ const UnfinishedStoryPage = () => { return 1; } return 0; - }) - .filter(({ status }) => status !== "완료"), + }), [backlog.epicList] ); const epicCategoryList = useMemo( @@ -60,6 +74,7 @@ const UnfinishedStoryPage = () => { [backlog.epicList] ); const { emitStoryUpdateEvent } = useStoryEmitEvent(socket); + const { emitTaskUpdateEvent } = useTaskEmitEvent(socket); const setStoryComponentRef = (index: number) => (element: HTMLDivElement) => { storyComponentRefList.current[index] = element; @@ -181,6 +196,45 @@ const UnfinishedStoryPage = () => { }; const handleTaskDragEnd = () => { + const { storyId, taskIndex } = taskElementIndex; + const taskList = storyList.find(({ id }) => id === storyId) + ?.taskList as TaskDTO[]; + const targetIndex = taskList?.findIndex(({ id }) => id === draggingTaskId); + + let rankValue; + + if (taskIndex === targetIndex) { + setDraggingTaskId(undefined); + setTaskElementIndex({ storyId: undefined, taskIndex: undefined }); + return; + } + + if (taskIndex === 0 && !taskList.length) { + console.log("아무 것도 없을 때"); + + rankValue = LexoRank.middle().toString(); + } else if (taskIndex === 0) { + const firstTaskRank = taskList[0].rankValue; + rankValue = LexoRank.parse(firstTaskRank).genPrev().toString(); + } else if (taskIndex === taskList.length) { + const lastTaskRank = taskList[taskList.length - 1].rankValue; + rankValue = LexoRank.parse(lastTaskRank).genNext().toString(); + } else { + const prevTaskRank = LexoRank.parse( + taskList[(taskIndex as number) - 1].rankValue + ); + const nextTaskRank = LexoRank.parse( + taskList[taskIndex as number].rankValue + ); + rankValue = prevTaskRank.between(nextTaskRank).toString(); + } + + emitTaskUpdateEvent({ + id: draggingTaskId as number, + storyId, + rankValue, + }); + setDraggingTaskId(undefined); setTaskElementIndex({ storyId: undefined, taskIndex: undefined }); }; From 9b0ba24f36d581fae8051fb09f9b54cd9806e43f Mon Sep 17 00:00:00 2001 From: surinkwon Date: Tue, 13 Aug 2024 23:30:28 +0900 Subject: [PATCH 5/7] =?UTF-8?q?fix:=20=EB=B3=80=EA=B2=BD=EB=90=9C=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=97=90?= =?UTF-8?q?=ED=94=BD=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/backlog/EpicPage.tsx | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/frontend/src/pages/backlog/EpicPage.tsx b/frontend/src/pages/backlog/EpicPage.tsx index 17f1258..5f73559 100644 --- a/frontend/src/pages/backlog/EpicPage.tsx +++ b/frontend/src/pages/backlog/EpicPage.tsx @@ -40,19 +40,15 @@ const EpicPage = () => { : 0; return ( - 0} - lastTaskRankValue={ - taskList.length - ? taskList[taskList.length - 1].rankValue - : undefined - } - > + <> + 0} + /> {...taskList.map((task) => )} - + ); })} {showDetail ? ( From d9cfd6ba52464a54b3f2986864a9f034b7913448 Mon Sep 17 00:00:00 2001 From: surinkwon Date: Tue, 13 Aug 2024 23:37:27 +0900 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=EB=B3=80=EA=B2=BD=20=EC=82=AC?= =?UTF-8?q?=ED=95=AD=EC=97=90=20=EB=A7=9E=EC=B6=B0=20=EC=99=84=EB=A3=8C?= =?UTF-8?q?=EB=90=9C=20=EC=8A=A4=ED=86=A0=EB=A6=AC=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/backlog/FinishedStoryPage.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/frontend/src/pages/backlog/FinishedStoryPage.tsx b/frontend/src/pages/backlog/FinishedStoryPage.tsx index ec0b765..37dbcb8 100644 --- a/frontend/src/pages/backlog/FinishedStoryPage.tsx +++ b/frontend/src/pages/backlog/FinishedStoryPage.tsx @@ -38,16 +38,16 @@ const FinishedStoryPage = () => { : 0; return ( - 0} - epicList={epicCategoryList} - finished={true} - > + <> + 0} + epicList={epicCategoryList} + /> {...taskList.map((task) => )} - + ); })}
From 2df27066007a650cbc0e341c23af03b6b067702c Mon Sep 17 00:00:00 2001 From: surinkwon Date: Tue, 13 Aug 2024 23:51:21 +0900 Subject: [PATCH 7/7] =?UTF-8?q?design:=20=EB=A7=88=EC=A7=80=EB=A7=89=20?= =?UTF-8?q?=EC=A4=84=EC=97=90=20=ED=83=9C=EC=8A=A4=ED=81=AC=20=EB=93=9C?= =?UTF-8?q?=EB=9E=98=EA=B7=B8=20=EC=8B=9C=20=EB=82=98=ED=83=80=EB=82=98?= =?UTF-8?q?=EB=8A=94=20=ED=91=9C=EC=8B=9C=EC=9D=98=20=EA=B8=B8=EC=9D=B4=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/backlog/UnfinishedStoryPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/backlog/UnfinishedStoryPage.tsx b/frontend/src/pages/backlog/UnfinishedStoryPage.tsx index b7e73d9..0cfabff 100644 --- a/frontend/src/pages/backlog/UnfinishedStoryPage.tsx +++ b/frontend/src/pages/backlog/UnfinishedStoryPage.tsx @@ -294,7 +294,7 @@ const UnfinishedStoryPage = () => { className={`${ id === taskElementIndex.storyId && taskElementIndex.taskIndex === taskList.length - ? "w-[67.9rem] h-1 bg-blue-400" + ? "w-[60.13rem] h-1 bg-blue-400" : "" } absolute`} />