From e9983ade3e45f810758537573f3b79142fffc9d3 Mon Sep 17 00:00:00 2001 From: a-honey Date: Tue, 14 Jan 2025 11:22:16 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20useQueryParams=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useQueryParams.ts | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/hooks/useQueryParams.ts diff --git a/src/hooks/useQueryParams.ts b/src/hooks/useQueryParams.ts new file mode 100644 index 0000000..7c9c499 --- /dev/null +++ b/src/hooks/useQueryParams.ts @@ -0,0 +1,59 @@ +import { useLocation } from "react-router-dom"; + +const useQueryParams = () => { + const location = useLocation(); + const searchParams = new URLSearchParams(location.search); + + const addKeyValue = (key: string, value: string) => { + searchParams.append(key, value); + return searchParams.toString(); + }; + const replaceValue = (key: string, value: string) => { + searchParams.set(key, value); + return searchParams.toString(); + }; + + const removeKeyValue = (key: string, value: string) => { + const values = searchParams.getAll(key); + searchParams.delete(key); + + values.forEach((val) => { + if (val !== value) { + searchParams.append(key, val); + } + }); + + return searchParams.toString(); + }; + + const removeAllValues = (key: string) => { + searchParams.delete(key); + + return searchParams.toString(); + }; + + const hasValue = (key: string) => { + return searchParams.has(key); + }; + + const getValue = (key: string) => searchParams.get(key); + const getAllValue = (key: string) => searchParams.getAll(key); + + const hasKeyValueSet = (key: string, value: string) => { + const values = getAllValue(key); + return values.includes(value); + }; + + return { + getValue, + getAllValue, + addKeyValue, + replaceValue, + removeKeyValue, + removeAllValues, + hasValue, + hasKeyValueSet, + }; +}; + +export default useQueryParams; From 02888536822ea6efb0b72be2d8b3e89c77f2088d Mon Sep 17 00:00:00 2001 From: a-honey Date: Tue, 14 Jan 2025 11:35:05 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20SortSelect=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/user/getUserList.ts | 2 +- src/components/SortSelect/index.tsx | 36 +++++++++++++++++++++++++++++ src/pages/user/List.tsx | 28 +++++++++++++++++----- src/queries/userQueryOptions.ts | 1 + 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/components/SortSelect/index.tsx diff --git a/src/api/user/getUserList.ts b/src/api/user/getUserList.ts index 31d21c1..f4c665e 100644 --- a/src/api/user/getUserList.ts +++ b/src/api/user/getUserList.ts @@ -14,7 +14,7 @@ export type UserListResponseType = { export default async function getUserList(params: ListParams) { const { page, perPage } = params.pagination; const keyword = params.filter?.keyword || ""; - const filter = "all"; + const filter = params.filter?.status; const url = keyword ? `/admin-management/users/search/${keyword}` diff --git a/src/components/SortSelect/index.tsx b/src/components/SortSelect/index.tsx new file mode 100644 index 0000000..aec9b92 --- /dev/null +++ b/src/components/SortSelect/index.tsx @@ -0,0 +1,36 @@ +interface SortOption { + value: string; + label: string; +} + +interface SortSelectProps { + options: SortOption[]; + onChange: (value: string) => void; + defaultValue?: string; +} + +export default function SortSelect({ + options, + onChange, + defaultValue, +}: SortSelectProps) { + const handleChange = (event: React.ChangeEvent) => { + onChange(event.target.value); + }; + + return ( +
+ +
+ ); +} diff --git a/src/pages/user/List.tsx b/src/pages/user/List.tsx index eb11aed..95cf804 100644 --- a/src/pages/user/List.tsx +++ b/src/pages/user/List.tsx @@ -5,6 +5,7 @@ import { Link } from "react-router-dom"; import List from "../../components/List"; import LoadingFallback from "../../components/fallback/LoadingFallback"; import Pagination from "../../components/Pagination"; +import SortSelect from "../../components/SortSelect"; import UIErrorBoundary from "../../components/fallback/UIErrorBoundary"; import { UserType } from "../../api/user"; import usePagination from "../../components/Pagination/usePagination"; @@ -27,17 +28,29 @@ const userListColumns = [ "사용자 상태", "가입날짜", ]; + +const USER_FILTER = [ + { value: "all", label: "전체보기" }, + { value: "monitored", label: "monitored" }, + { value: "activeSubscription", label: "구독자만 보기" }, +]; + const UserListContent = () => { const [userSearchKeyword, setUserSearchKeyword] = useState(""); + const [userFilter, setUserFilter] = useState(USER_FILTER[0].value); const { currentPage, handlePaginationEvent } = usePagination(); const { data, error, isLoading } = useQuery({ ...userQueryOptions.getUserList({ pagination: { page: currentPage, perPage: 10 }, - filter: { keyword: userSearchKeyword }, + filter: { keyword: userSearchKeyword, status: userFilter }, }), }); + const changeUserFilter = (filter: string) => { + setUserFilter(filter); + }; + if (isLoading) { return ; } @@ -52,11 +65,14 @@ const UserListContent = () => { return ( - +
+ + +
diff --git a/src/queries/userQueryOptions.ts b/src/queries/userQueryOptions.ts index e54cc25..c8640b1 100644 --- a/src/queries/userQueryOptions.ts +++ b/src/queries/userQueryOptions.ts @@ -13,6 +13,7 @@ const userQueryOptions = { params.pagination.page, params.pagination.perPage, params.filter?.keyword || "", + params.filter?.status, ], queryFn: () => getUserList(params), }), From 81990d8c3850a29b295c490a424bb0ca3a7d6948 Mon Sep 17 00:00:00 2001 From: a-honey Date: Tue, 14 Jan 2025 11:38:20 +0900 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=EC=BF=BC=EB=A6=AC=ED=82=A4=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/queries/userQueryOptions.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/queries/userQueryOptions.ts b/src/queries/userQueryOptions.ts index c8640b1..0055821 100644 --- a/src/queries/userQueryOptions.ts +++ b/src/queries/userQueryOptions.ts @@ -7,14 +7,7 @@ import { queryOptions } from "@tanstack/react-query"; const userQueryOptions = { getUserList: (params: ListParams) => queryOptions({ - queryKey: [ - "user", - "list", - params.pagination.page, - params.pagination.perPage, - params.filter?.keyword || "", - params.filter?.status, - ], + queryKey: ["user", "list", params], queryFn: () => getUserList(params), }), getUserDetail: (params: DetailParams) => From 156b9faa82fac8799c909586bd36780b03dfd011 Mon Sep 17 00:00:00 2001 From: a-honey Date: Tue, 14 Jan 2025 11:39:31 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20defaultValue=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/user/List.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pages/user/List.tsx b/src/pages/user/List.tsx index 95cf804..f5b52b9 100644 --- a/src/pages/user/List.tsx +++ b/src/pages/user/List.tsx @@ -66,7 +66,11 @@ const UserListContent = () => {
- + Date: Tue, 14 Jan 2025 11:52:01 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20SortSelect=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=EB=B6=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SortSelect/index.stories.tsx | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/components/SortSelect/index.stories.tsx diff --git a/src/components/SortSelect/index.stories.tsx b/src/components/SortSelect/index.stories.tsx new file mode 100644 index 0000000..9acfb8f --- /dev/null +++ b/src/components/SortSelect/index.stories.tsx @@ -0,0 +1,27 @@ +import { Meta, StoryObj } from "@storybook/react"; + +import SortSelect from "."; + +const meta: Meta = { + title: "components/sortSelect", + component: SortSelect, + tags: ["autodocs"], + argTypes: { + onChange: { action: "changed" }, + }, +}; + +export default meta; + +type SortSelectStory = StoryObj; + +export const Default: SortSelectStory = { + args: { + options: [ + { value: "name", label: "이름순" }, + { value: "date", label: "날짜순" }, + { value: "price", label: "가격순" }, + ], + defaultValue: "name", + }, +}; From 8e8dafffbe50875cc639936292005c54ce328c65 Mon Sep 17 00:00:00 2001 From: a-honey Date: Tue, 14 Jan 2025 11:59:36 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20Blank=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/user/List.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/user/List.tsx b/src/pages/user/List.tsx index f5b52b9..30c3c86 100644 --- a/src/pages/user/List.tsx +++ b/src/pages/user/List.tsx @@ -80,9 +80,11 @@ const UserListContent = () => { - {data.users.map((user) => ( - - ))} + {!data.users || data.users.length === 0 ? ( + + ) : ( + data.users.map((user) => ) + )}