From 3b753f38afdee0724d2d8b9997548db388a3c384 Mon Sep 17 00:00:00 2001 From: Suk Woo Date: Thu, 29 Aug 2024 13:19:49 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20React=20Query=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20=EC=84=A4=EC=A0=95=20&=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EB=B3=84=20=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API=20=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80=20(#93)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Config: #89 React Query Devtools 추가 * Feat: #89 React Query 기본 설정 추가 * Feat: #89 Mutation 기본 Error handler 추가 * Refactor: #89 Axios 에러 처리와 React Query 에러 처리 통합 * Feat: #89 Task 목록 useQuery 작성 * Chore: #89 Mock 데이터 수정 & Task, Status 타입 수정 * Chore: #89 Mock & Type 변경 * Feat: 할일 전체 목록 API MSW Handler 추가 * Chore: MSW Handler 추가로 할일 목록 Dummy 참조 삭제 --- package.json | 1 + src/components/modal/task/ModalTaskForm.tsx | 4 +- src/hooks/errorHandler.ts | 15 ++ src/hooks/query/queryClient.ts | 32 ++++ src/hooks/query/useTaskQuery.ts | 40 ++-- src/hooks/useAxios.ts | 13 +- src/main.tsx | 10 +- src/mocks/handlers.ts | 3 +- src/mocks/mockData.ts | 198 +++++++++++++++++--- src/mocks/services/taskServiceHandler.ts | 23 +++ src/pages/project/CalendarPage.tsx | 7 +- src/pages/project/KanbanPage.tsx | 5 +- src/services/taskService.ts | 18 ++ src/types/ProjectStatusType.tsx | 11 +- src/types/TaskType.tsx | 5 +- yarn.lock | 12 ++ 16 files changed, 333 insertions(+), 64 deletions(-) create mode 100644 src/hooks/errorHandler.ts create mode 100644 src/hooks/query/queryClient.ts create mode 100644 src/mocks/services/taskServiceHandler.ts create mode 100644 src/services/taskService.ts diff --git a/package.json b/package.json index 4231414a..476792f6 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "dependencies": { "@hello-pangea/dnd": "^16.6.0", "@tanstack/react-query": "^5.36.2", + "@tanstack/react-query-devtools": "^5.52.2", "axios": "^1.6.8", "luxon": "^3.4.4", "react": "^18.2.0", diff --git a/src/components/modal/task/ModalTaskForm.tsx b/src/components/modal/task/ModalTaskForm.tsx index 83309bf2..214a5a73 100644 --- a/src/components/modal/task/ModalTaskForm.tsx +++ b/src/components/modal/task/ModalTaskForm.tsx @@ -13,7 +13,7 @@ import CustomMarkdown from '@components/common/CustomMarkdown'; import DuplicationCheckInput from '@components/common/DuplicationCheckInput'; import useToast from '@hooks/useToast'; import useAxios from '@hooks/useAxios'; -import useTaskQuery from '@hooks/query/useTaskQuery'; +import { useTasksQuery } from '@hooks/query/useTaskQuery'; import useStatusQuery from '@hooks/query/useStatusQuery'; import { convertBytesToString } from '@utils/converter'; import { findUserByProject } from '@services/projectService'; @@ -43,7 +43,7 @@ export default function ModalTaskForm({ formId, project, taskId, onSubmit }: Mod const [files, setFiles] = useState([]); const { statusList } = useStatusQuery(projectId, taskId); - const { taskNameList } = useTaskQuery(projectId); + const { taskNameList } = useTasksQuery(projectId); const { data, loading, clearData, fetchData } = useAxios(findUserByProject); const { toastInfo, toastWarn } = useToast(); diff --git a/src/hooks/errorHandler.ts b/src/hooks/errorHandler.ts new file mode 100644 index 00000000..5f792a15 --- /dev/null +++ b/src/hooks/errorHandler.ts @@ -0,0 +1,15 @@ +import axios from 'axios'; + +// ToDo: useAxios의 에러 처리와 react query의 에러 처리를 담당하도록 만들 것 +export default function errorHandler(error: T) { + // ToDo: AxiosError가 아닌 경우 에러 처리 + if (!axios.isAxiosError(error)) return; + + if (error.request) { + // ToDo: 네트워크 요청을 보냈지만 응답이 없는 경우 에러 처리 + } else if (error.response) { + // ToDo: 요청후 응답을 받았지만 200 이외의 응답 코드인 경우 예외 처리 + } else { + // ToDo: request 설정 오류 + } +} diff --git a/src/hooks/query/queryClient.ts b/src/hooks/query/queryClient.ts new file mode 100644 index 00000000..bd8ccb67 --- /dev/null +++ b/src/hooks/query/queryClient.ts @@ -0,0 +1,32 @@ +import { MutationCache, QueryCache, QueryClient } from '@tanstack/react-query'; +import { MINUTE } from '@constants/units'; +import errorHandler from '@hooks/errorHandler'; +import type { QueryClientConfig } from '@tanstack/react-query'; + +// ToDo: 기본 옵션 설정 대화하고 확정하기 +const queryClientOptions: QueryClientConfig = { + defaultOptions: { + queries: { + staleTime: 5 * MINUTE, + gcTime: 10 * MINUTE, + refetchOnMount: true, + refetchOnReconnect: true, + refetchOnWindowFocus: true, + retry: 3, + }, + }, + queryCache: new QueryCache({ + onError: (error) => { + console.error(`Query: ${error.name}:${error.message}:${error.stack}`); + errorHandler(error); + }, + }), + mutationCache: new MutationCache({ + onError: (error) => { + console.error(`Mutation: ${error.name}:${error.message}:${error.stack}`); + errorHandler(error); + }, + }), +}; + +export const queryClient = new QueryClient(queryClientOptions); diff --git a/src/hooks/query/useTaskQuery.ts b/src/hooks/query/useTaskQuery.ts index 6d15bf3c..eb06ca03 100644 --- a/src/hooks/query/useTaskQuery.ts +++ b/src/hooks/query/useTaskQuery.ts @@ -1,20 +1,34 @@ -import { TASK_DUMMY } from '@mocks/mockData'; -import { TaskListWithStatus } from '@/types/TaskType'; -import { Project } from '@/types/ProjectType'; +import { useQuery } from '@tanstack/react-query'; +import { findTaskList } from '@services/taskService'; + +import type { TaskListWithStatus } from '@/types/TaskType'; +import type { Project } from '@/types/ProjectType'; function getTaskNameList(taskList: TaskListWithStatus[]) { - return taskList - .map((statusTask) => statusTask.tasks) - .flat() - .map((task) => task.name); + return taskList.length > 0 + ? taskList + .map((statusTask) => statusTask.tasks) + .flat() + .map((task) => task.name) + : []; } -// Todo: Task Query CRUD로직 작성하기 -// QueryKey: project, projectId, tasks -export default function useTaskQuery(projectId: Project['projectId']) { - const taskList = TASK_DUMMY; +// Todo: Task Query CUD로직 작성하기 +export function useTasksQuery(projectId: Project['projectId']) { + const { + data: taskList = [], + isLoading: isTaskLoading, + isError: isTaskError, + error: taskError, + } = useQuery({ + queryKey: ['projects', projectId, 'tasks'], + queryFn: async () => { + const { data } = await findTaskList(projectId); + return data; + }, + }); - const taskNameList = taskList ? getTaskNameList(taskList) : []; + const taskNameList = getTaskNameList(taskList); - return { taskList, taskNameList }; + return { taskList, taskNameList, isTaskLoading, isTaskError, taskError }; } diff --git a/src/hooks/useAxios.ts b/src/hooks/useAxios.ts index dca534a6..bd2d1762 100644 --- a/src/hooks/useAxios.ts +++ b/src/hooks/useAxios.ts @@ -1,5 +1,5 @@ -import axios from 'axios'; import { useState, useCallback } from 'react'; +import errorHandler from '@hooks/errorHandler'; import type { AxiosResponse } from 'axios'; type PromiseCallback = (...args: P) => Promise>; @@ -40,16 +40,7 @@ export default function useAxios(fetchCallback: PromiseC setData(response.data); } catch (error: unknown) { setError(error as Error); - - if (!axios.isAxiosError(error)) return; - - if (error.request) { - // ToDo: 네트워크 요청을 보냈지만 응답이 없는 경우 에러 처리 - } else if (error.response) { - // ToDo: 요청후 응답을 받았지만 200 이외의 응답 코드인 경우 예외 처리 - } else { - // ToDo: request 설정 오류 - } + errorHandler(error as Error); } finally { setLoading(false); } diff --git a/src/main.tsx b/src/main.tsx index ef2936b2..18f99bbf 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,7 +1,10 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import '@/globals.css'; +import { QueryClientProvider } from '@tanstack/react-query'; +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import MainRouter from '@routes/MainRouter.tsx'; +import { queryClient } from '@hooks/query/queryClient'; +import '@/globals.css'; async function enableMocking() { if (!import.meta.env.DEV) return; @@ -13,7 +16,10 @@ async function enableMocking() { enableMocking().then(() => { ReactDOM.createRoot(document.getElementById('root')!).render( - + + + + , ); }); diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 478ec85a..6a54a7ce 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -1,7 +1,8 @@ import userServiceHandler from '@mocks/services/userServiceHandler'; import teamServiceHandler from '@mocks/services/teamServiceHandler'; import projectServiceHandler from '@mocks/services/projectServiceHandler'; +import taskServiceHandler from '@mocks/services/taskServiceHandler'; -const handlers = [...userServiceHandler, ...teamServiceHandler, ...projectServiceHandler]; +const handlers = [...userServiceHandler, ...teamServiceHandler, ...projectServiceHandler, ...taskServiceHandler]; export default handlers; diff --git a/src/mocks/mockData.ts b/src/mocks/mockData.ts index 23760fd3..036077aa 100644 --- a/src/mocks/mockData.ts +++ b/src/mocks/mockData.ts @@ -1,8 +1,10 @@ +import { PROJECT_STATUS_COLORS } from '@constants/projectStatus'; + import type { User } from '@/types/UserType'; import type { Team } from '@/types/TeamType'; import type { Project } from '@/types/ProjectType'; import type { ProjectStatus } from '@/types/ProjectStatusType'; -import type { TaskListWithStatus } from '@/types/TaskType'; +import type { Task, TaskListWithStatus } from '@/types/TaskType'; import type { Role } from '@/types/RoleType'; type TeamUser = { @@ -282,6 +284,12 @@ export const TEAM_USER_DUMMY: TeamUser[] = [ isPendingApproval: true, }, // 팀2 소속 유저 정보 + { + teamId: 2, + userId: 1, + roleId: 2, + isPendingApproval: true, + }, { teamId: 2, userId: 3, @@ -463,7 +471,7 @@ export const PROJECT_DUMMY: Project[] = [ startDate: new Date('2024-05-15 00:00:00'), endDate: new Date('2024-09-01 00:00:00'), createAt: new Date('2024-05-15'), - updateAt: new Date('2025-05-15'), + updateAt: new Date('2024-05-15'), }, { projectId: 3, @@ -478,30 +486,178 @@ export const PROJECT_DUMMY: Project[] = [ ] as const; // 프로젝트 상태 테이블 Mock -// ToDo: 프로젝트 상태 테이블용 더미 데이터 변경 필요 export const STATUS_DUMMY: ProjectStatus[] = [ + // 프로젝트1 상태 { statusId: 1, - name: 'To Do', - color: '#c83c00', + projectId: 1, + name: '할일', + color: PROJECT_STATUS_COLORS.RED, order: 1, }, { statusId: 2, - name: 'In Progress', - color: '#dab700', + projectId: 1, + name: '진행중', + color: PROJECT_STATUS_COLORS.YELLOW, order: 2, }, { statusId: 3, - name: 'Done', - color: '#237700', + projectId: 1, + name: '완료', + color: PROJECT_STATUS_COLORS.GREEN, + order: 3, + }, + // 프로젝트2 상태 + { + statusId: 4, + projectId: 2, + name: '할일', + color: PROJECT_STATUS_COLORS.RED, + order: 1, + }, + { + statusId: 5, + projectId: 2, + name: '진행중', + color: PROJECT_STATUS_COLORS.YELLOW, + order: 2, + }, + { + statusId: 6, + projectId: 2, + name: '완료', + color: PROJECT_STATUS_COLORS.GREEN, + order: 3, + }, + // 프로젝트3 상태 + { + statusId: 7, + projectId: 3, + name: 'To Do', + color: PROJECT_STATUS_COLORS.YELLOW, + order: 1, + }, + { + statusId: 8, + projectId: 3, + name: 'In Progress', + color: PROJECT_STATUS_COLORS.ORANGE, + order: 2, + }, + { + statusId: 9, + projectId: 3, + name: 'In Review', + color: PROJECT_STATUS_COLORS.RED, order: 3, }, + { + statusId: 10, + projectId: 3, + name: 'Done', + color: PROJECT_STATUS_COLORS.BLUE, + order: 4, + }, ] as const; +export const TASK_DUMMY: Task[] = [ + // 프로젝트2 완료 상태 + { + taskId: 1, + name: 'task 상태 추가 모달 작업하기', + order: 1, + statusId: 6, + userId: 1, + content: '', + files: [], + startDate: '2024-06-22', + endDate: '2024-06-26', + }, + { + taskId: 2, + name: 'project layout 작성하기', + order: 2, + statusId: 6, + userId: 3, + content: '', + files: [], + startDate: '2024-06-18', + endDate: '2024-06-21', + }, + { + taskId: 3, + name: 'tailwindcss 설정하기', + order: 3, + statusId: 6, + userId: 9, + content: '', + files: [], + startDate: '2024-06-14', + endDate: '2024-06-18', + }, + // 프로젝트2 진행중 상태 + { + taskId: 4, + name: 'API 명세서 작성하기', + order: 2, + statusId: 5, + userId: 1, + content: '', + files: [], + startDate: '2024-06-27', + endDate: '2024-06-29', + }, + { + taskId: 5, + name: 'DnD 기술 조사하기', + order: 1, + statusId: 5, + userId: 3, + content: `# AITalk\n## 주제\nDnD 기술 조사하기\n\n※\`DnD\`란 Drag and Drop의 약자다\n\n## 라이브러리 선정\n[react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd) 등과 같이 다양한 라이브러리 중 어느 것을 선정할 것인가?`, + files: [], + startDate: '2024-06-27', + endDate: '2024-06-29', + }, + // 프로젝트2 할일 상태 + { + taskId: 6, + name: '할일 추가 모달 구현하기', + order: 1, + statusId: 4, + userId: 1, + content: '', + files: [], + startDate: '2024-06-26', + endDate: '2024-07-02', + }, + { + taskId: 7, + name: 'ID 찾기 페이지 작성하기', + order: 2, + statusId: 4, + userId: 3, + content: '', + files: [], + startDate: '2024-07-03', + endDate: '2024-07-05', + }, + { + taskId: 8, + name: 'DnD 구현하기', + order: 3, + statusId: 4, + userId: 9, + content: '', + files: [], + startDate: '2024-06-30', + endDate: '2024-07-02', + }, +]; + // 특수 케이스: 할일 목록을 프로젝트 상태별로 정리하여 내려준 Mock -export const TASK_DUMMY: TaskListWithStatus[] = [ +export const TASK_SPECIAL_DUMMY: TaskListWithStatus[] = [ { statusId: 1, name: 'To Do', @@ -509,17 +665,17 @@ export const TASK_DUMMY: TaskListWithStatus[] = [ order: 1, tasks: [ { - taskId: 7, + taskId: 6, name: '할일 추가 모달 구현하기', order: 1, - userId: 3, + userId: 1, content: '', files: [], startDate: '2024-06-26', endDate: '2024-07-02', }, { - taskId: 8, + taskId: 7, name: 'ID 찾기 페이지 작성하기', order: 2, userId: 3, @@ -529,10 +685,10 @@ export const TASK_DUMMY: TaskListWithStatus[] = [ endDate: '2024-07-05', }, { - taskId: 9, + taskId: 8, name: 'DnD 구현하기', order: 3, - userId: 1, + userId: 9, content: '', files: [], startDate: '2024-06-30', @@ -550,8 +706,8 @@ export const TASK_DUMMY: TaskListWithStatus[] = [ taskId: 5, name: 'DnD 기술 조사하기', order: 1, - userId: 1, - content: '', + userId: 3, + content: `# AITalk\n## 주제\nDnD 기술 조사하기\n\n※\`DnD\`란 Drag and Drop의 약자다\n\n## 라이브러리 선정\n[react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd) 등과 같이 다양한 라이브러리 중 어느 것을 선정할 것인가?`, files: [], startDate: '2024-06-27', endDate: '2024-06-29', @@ -560,7 +716,7 @@ export const TASK_DUMMY: TaskListWithStatus[] = [ taskId: 4, name: 'API 명세서 작성하기', order: 2, - userId: 2, + userId: 1, content: '', files: [], startDate: '2024-06-27', @@ -578,7 +734,7 @@ export const TASK_DUMMY: TaskListWithStatus[] = [ taskId: 1, name: 'task 상태 추가 모달 작업하기', order: 1, - userId: 2, + userId: 1, content: '', files: [], startDate: '2024-06-22', @@ -588,7 +744,7 @@ export const TASK_DUMMY: TaskListWithStatus[] = [ taskId: 2, name: 'project layout 작성하기', order: 2, - userId: 1, + userId: 3, content: '', files: [], startDate: '2024-06-18', @@ -598,7 +754,7 @@ export const TASK_DUMMY: TaskListWithStatus[] = [ taskId: 3, name: 'tailwindcss 설정하기', order: 3, - userId: 3, + userId: 9, content: '', files: [], startDate: '2024-06-14', diff --git a/src/mocks/services/taskServiceHandler.ts b/src/mocks/services/taskServiceHandler.ts new file mode 100644 index 00000000..27bfe9f4 --- /dev/null +++ b/src/mocks/services/taskServiceHandler.ts @@ -0,0 +1,23 @@ +import { http, HttpResponse } from 'msw'; +import { STATUS_DUMMY, TASK_DUMMY } from '@mocks/mockData'; + +const BASE_URL = import.meta.env.VITE_BASE_URL; + +const taskServiceHandler = [ + http.get(`${BASE_URL}/project/:projectId/task`, ({ request, params }) => { + const accessToken = request.headers.get('Authorization'); + const { projectId } = params; + + if (!accessToken) return new HttpResponse(null, { status: 401 }); + + const statusList = STATUS_DUMMY.filter((status) => status.projectId === Number(projectId)); + const statusTaskList = statusList.map((status) => { + const tasks = TASK_DUMMY.filter((task) => task.statusId === status.statusId); + return { ...status, tasks }; + }); + + return HttpResponse.json(statusTaskList); + }), +]; + +export default taskServiceHandler; diff --git a/src/pages/project/CalendarPage.tsx b/src/pages/project/CalendarPage.tsx index 661c3f08..765c8b7c 100644 --- a/src/pages/project/CalendarPage.tsx +++ b/src/pages/project/CalendarPage.tsx @@ -8,11 +8,11 @@ import UpdateModalTask from '@components/modal/task/UpdateModalTask'; import useModal from '@hooks/useModal'; import useProjectContext from '@hooks/useProjectContext'; import Validator from '@utils/Validator'; -import { TASK_DUMMY } from '@mocks/mockData'; import { TaskListWithStatus, TaskWithStatus } from '@/types/TaskType'; import { CustomEvent } from '@/types/CustomEventType'; import 'react-big-calendar/lib/css/react-big-calendar.css'; import '@/customReactBigCalendar.css'; +import { useTasksQuery } from '@/hooks/query/useTaskQuery'; function getCalendarTask(statusTasks: TaskListWithStatus[]) { const calendarTasks: TaskWithStatus[] = []; @@ -31,11 +31,14 @@ const dt = DateTime.local(); Settings.defaultZone = dt.zoneName; const localizer = luxonLocalizer(DateTime, { firstDayOfWeek: 7 }); +// ToDo: Loading시 infinite spinner UI 보이도록 변경할 것 +// ToDo: Error 발생시 처리 추가할 것 export default function CalendarPage() { const { project } = useProjectContext(); const { showModal, openModal, closeModal } = useModal(); const [selectedTask, setSelectedTask] = useState(); const [date, setDate] = useState(() => DateTime.now().toJSDate()); + const { taskList, isTaskLoading, isTaskError, taskError } = useTasksQuery(project.projectId); const handleNavigate = useCallback((newDate: Date) => setDate(newDate), [setDate]); @@ -74,7 +77,7 @@ export default function CalendarPage() { ); const state = { - events: getCalendarTask(TASK_DUMMY) + events: getCalendarTask(taskList) .map((task) => ({ title: task.name, start: new Date(task.startDate), diff --git a/src/pages/project/KanbanPage.tsx b/src/pages/project/KanbanPage.tsx index e3c66e03..eab324d0 100644 --- a/src/pages/project/KanbanPage.tsx +++ b/src/pages/project/KanbanPage.tsx @@ -4,7 +4,7 @@ import ProjectStatusContainer from '@components/task/kanban/ProjectStatusContain import { DND_DROPPABLE_PREFIX, DND_TYPE } from '@constants/dnd'; import deepClone from '@utils/deepClone'; import { parsePrefixId } from '@utils/converter'; -import { TASK_DUMMY } from '@mocks/mockData'; +import { TASK_SPECIAL_DUMMY } from '@mocks/mockData'; import type { Task, TaskListWithStatus } from '@/types/TaskType'; function createChangedStatus(statusTasks: TaskListWithStatus[], dropResult: DropResult) { @@ -48,9 +48,10 @@ function createChangedTasks(statusTasks: TaskListWithStatus[], dropResult: DropR return newStatusTasks; } +// ToDo: TASK_SPECIAL_DUMMY 부분을 react query로 변경할 것, mutation 작업이 같이 들어가야함 // ToDo: DnD시 가시성을 위한 애니메이션 처리 추가할 것 export default function KanbanPage() { - const [statusTasks, setStatusTasks] = useState(TASK_DUMMY); + const [statusTasks, setStatusTasks] = useState(TASK_SPECIAL_DUMMY); const handleDragEnd = (dropResult: DropResult) => { const { source, destination, type } = dropResult; diff --git a/src/services/taskService.ts b/src/services/taskService.ts new file mode 100644 index 00000000..d9730eed --- /dev/null +++ b/src/services/taskService.ts @@ -0,0 +1,18 @@ +import { authAxios } from '@services/axiosProvider'; + +import type { AxiosRequestConfig } from 'axios'; +import type { Project } from '@/types/ProjectType'; +import type { TaskListWithStatus } from '@/types/TaskType'; + +/** + * 프로젝트에 속한 모든 할일 목록 조회 API + * + * @export + * @async + * @param {Project['projectId']} projectId - 대상 프로젝트 ID + * @param {AxiosRequestConfig} [axiosConfig={}] - axios 요청 옵션 설정 객체 + * @returns {Promise>} + */ +export async function findTaskList(projectId: Project['projectId'], axiosConfig: AxiosRequestConfig = {}) { + return authAxios.get(`project/${projectId}/task`, axiosConfig); +} diff --git a/src/types/ProjectStatusType.tsx b/src/types/ProjectStatusType.tsx index 783532d9..dff8579a 100644 --- a/src/types/ProjectStatusType.tsx +++ b/src/types/ProjectStatusType.tsx @@ -1,17 +1,12 @@ // ToDo: API 설계 완료시 데이터 타입 변경할 것 export type ProjectStatus = { statusId: number; + projectId: number; name: string; color: string; order: number; }; -export type ProjectStatusForm = { - name: string; - color: string; -}; +export type ProjectStatusForm = Pick; -export type UsableColor = { - color: string; - isUsable: boolean; -}; +export type UsableColor = Pick & { isUsable: boolean }; diff --git a/src/types/TaskType.tsx b/src/types/TaskType.tsx index e67d0090..4279643a 100644 --- a/src/types/TaskType.tsx +++ b/src/types/TaskType.tsx @@ -14,6 +14,7 @@ export type Task = { taskId: number; name: string; userId: number; + statusId: number; content: string; startDate: string; endDate: string; @@ -31,5 +32,5 @@ export type TaskForm = { statusId: number; }; -export type TaskWithStatus = RenameKeys & Task; -export type TaskListWithStatus = ProjectStatus & { tasks: Task[] }; +export type TaskWithStatus = RenameKeys, StatusKeyMapping> & Task; +export type TaskListWithStatus = Omit & { tasks: Omit[] }; diff --git a/yarn.lock b/yarn.lock index 81c2b3fc..43d64155 100644 --- a/yarn.lock +++ b/yarn.lock @@ -598,6 +598,18 @@ resolved "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.36.1.tgz" integrity sha512-BteWYEPUcucEu3NBcDAgKuI4U25R9aPrHSP6YSf2NvaD2pSlIQTdqOfLRsxH9WdRYg7k0Uom35Uacb6nvbIMJg== +"@tanstack/query-devtools@5.51.16": + version "5.51.16" + resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.51.16.tgz#d855d00e7939c1a442c2e8ae3ad1a5bd603d003b" + integrity sha512-ajwuq4WnkNCMj/Hy3KR8d3RtZ6PSKc1dD2vs2T408MdjgKzQ3klVoL6zDgVO7X+5jlb5zfgcO3thh4ojPhfIaw== + +"@tanstack/react-query-devtools@^5.52.2": + version "5.52.2" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-5.52.2.tgz#cb0f0617e023141bb0f8a530f8c6e3e99fcae1bf" + integrity sha512-QI3jsi8sVA805F9NRdL/sVGgCUzVD8lr6/ts9v3ZtECG864YDW3GJwEWH030U+4aPvxMtxaJz7ctbtE7Wkxh1g== + dependencies: + "@tanstack/query-devtools" "5.51.16" + "@tanstack/react-query@^5.36.2": version "5.36.2" resolved "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.36.2.tgz"