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.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", + }, +}; 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/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; diff --git a/src/pages/user/List.tsx b/src/pages/user/List.tsx index eb11aed..30c3c86 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,17 +65,26 @@ const UserListContent = () => { return ( - +
+ + +
- {data.users.map((user) => ( - - ))} + {!data.users || data.users.length === 0 ? ( + + ) : ( + data.users.map((user) => ) + )} queryOptions({ - queryKey: [ - "user", - "list", - params.pagination.page, - params.pagination.perPage, - params.filter?.keyword || "", - ], + queryKey: ["user", "list", params], queryFn: () => getUserList(params), }), getUserDetail: (params: DetailParams) =>