From e8429e7d986b9a74021b8f7e48e5657eebade70b Mon Sep 17 00:00:00 2001 From: TaeSeung Yoo <59465914+gudusol@users.noreply.github.com> Date: Wed, 15 Jan 2025 00:49:09 +0900 Subject: [PATCH] =?UTF-8?q?[Feat/#73]=20=EA=B4=80=EB=A6=AC=EC=9E=90=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=88=98=EC=A0=95(=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80=20&=20?= =?UTF-8?q?=EC=83=81=ED=92=88=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5)=20(#74)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 관리자 상품 조회 순서 변경 기능 추가 * feat: 관리자 상품 추가 모달에 카테고리 반영 * feat: 관리자 페이지 주문 조회 staleTime 추가 * feat: 관리자 주문 조회 필터 조건 추가(주문 번호, 보내는 분, 받는 분) * design: 관리자 상품 조회 페이지 행 cursor 변경 --- package.json | 2 + src/apis/domains/admin/useFetchOrders.ts | 1 + src/apis/domains/admin/usePatchSequence.ts | 42 +++++ .../Admin/components/Filter/Filter.style.ts | 6 +- src/pages/Admin/components/Filter/Filter.tsx | 80 +++++++-- .../ProductAddModal/ProductAddModal.tsx | 6 +- .../components/ProductTable/ProductTable.tsx | 152 +++++++++++------- .../components/SortableRow/SortableRow.tsx | 65 ++++++++ .../Admin/page/AdminPage/AdminPage.style.ts | 1 + .../page/AdminPage/OrderCheck/OrderCheck.tsx | 28 +++- .../AdminPage/ProductCheck/ProductCheck.tsx | 2 + yarn.lock | 36 +++++ 12 files changed, 345 insertions(+), 76 deletions(-) create mode 100644 src/apis/domains/admin/usePatchSequence.ts create mode 100644 src/pages/Admin/components/SortableRow/SortableRow.tsx diff --git a/package.json b/package.json index d3be8c6..1045ad8 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ "svgr": "npx @svgr/cli -d src/assets/svg --ignore-existing --typescript --no-dimensions public/svg" }, "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", "@emotion/react": "^11.13.3", "@tanstack/react-query": "^5.56.2", "@tanstack/react-query-devtools": "^5.62.16", diff --git a/src/apis/domains/admin/useFetchOrders.ts b/src/apis/domains/admin/useFetchOrders.ts index 1c98a8c..1399125 100644 --- a/src/apis/domains/admin/useFetchOrders.ts +++ b/src/apis/domains/admin/useFetchOrders.ts @@ -49,5 +49,6 @@ export const useFetchOrders = (query: queryType) => { }, initialPageParam: -1, // 초기 페이지 파라미터 설정 select: (data) => (data.pages ?? []).flatMap((page) => page?.orders), + staleTime: 1000 * 60, }); }; diff --git a/src/apis/domains/admin/usePatchSequence.ts b/src/apis/domains/admin/usePatchSequence.ts new file mode 100644 index 0000000..7bb3d39 --- /dev/null +++ b/src/apis/domains/admin/usePatchSequence.ts @@ -0,0 +1,42 @@ +import { adminPatch } from "@apis/api"; +import { QUERY_KEY } from "@apis/queryKeys/queryKeys"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { ErrorResponse, MutateResponseType } from "@types"; + +interface PatchProductSequence { + productId: number; + currentSequence: number; + newSequence: number; +} + +const patchProductSequence = async ({ + productId, + currentSequence, + newSequence, +}: PatchProductSequence): Promise => { + try { + const response = await adminPatch( + `api/v1/product/sequence/${productId.toString()}?currentSequence=${currentSequence}&newSequence=${newSequence}` + ); + return response.data; + } catch (error) { + const errorResponse = error as ErrorResponse; + const errorData = errorResponse.response.data; + throw errorData; + } +}; + +export const usePatchSequence = () => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: ({ + productId, + currentSequence, + newSequence, + }: PatchProductSequence) => + patchProductSequence({ productId, currentSequence, newSequence }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: [QUERY_KEY.PRODUCT_LIST_ALL] }); + }, + }); +}; diff --git a/src/pages/Admin/components/Filter/Filter.style.ts b/src/pages/Admin/components/Filter/Filter.style.ts index e32f0ea..72e7609 100644 --- a/src/pages/Admin/components/Filter/Filter.style.ts +++ b/src/pages/Admin/components/Filter/Filter.style.ts @@ -25,8 +25,12 @@ export const rowStyle = (theme: Theme) => css` background-color: ${theme.color.white}; `; +export const inputWrapper = css` + width: 20rem; +`; + export const productSelectStyle = (theme: Theme) => css` - width: 40rem; + width: 30rem; ${theme.font["subhead-m-14"]} & #react-select-3-listbox { diff --git a/src/pages/Admin/components/Filter/Filter.tsx b/src/pages/Admin/components/Filter/Filter.tsx index 95bb63e..1f7ff44 100644 --- a/src/pages/Admin/components/Filter/Filter.tsx +++ b/src/pages/Admin/components/Filter/Filter.tsx @@ -1,10 +1,11 @@ import { useEffect, useState } from "react"; -import { Button, DateSelect } from "@components"; +import { Button, DateSelect, Input } from "@components"; import FilterAttribute from "../FilterAttribute/FilterAttribute"; import { buttonContainer, filterContainer, filterTable, + inputWrapper, productSelectStyle, rowStyle, statusSelectStyle, @@ -28,10 +29,15 @@ const statusOptions: Option[] = [ ]; interface FilterProps { - orderReceivedDateRef: React.MutableRefObject; - deliveryDateRef: React.MutableRefObject; - productRef: React.MutableRefObject