From 178671c6e658899b98000d057127e519a4e84ef9 Mon Sep 17 00:00:00 2001 From: Lin Date: Fri, 24 Jan 2025 17:36:47 +0900 Subject: [PATCH 01/28] =?UTF-8?q?Refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B3=84?= =?UTF-8?q?=EC=B8=B5(MembersContent.tsx)=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../members/_components/MembersContent.tsx | 78 ------------------- .../_components/ResponsiveMembersPage.tsx | 74 +++++++++++++++++- .../modals/MembersSettingModal.tsx | 4 +- 3 files changed, 73 insertions(+), 83 deletions(-) delete mode 100644 apps/web/app/(admin)/members/_components/MembersContent.tsx diff --git a/apps/web/app/(admin)/members/_components/MembersContent.tsx b/apps/web/app/(admin)/members/_components/MembersContent.tsx deleted file mode 100644 index 75fdf2cb..00000000 --- a/apps/web/app/(admin)/members/_components/MembersContent.tsx +++ /dev/null @@ -1,78 +0,0 @@ -"use client"; - -import { Suspense, useState } from "react"; -import { Button } from "@ui/index"; -import { type MemberWithStaticImage, type SortOption } from "@repo/types/src/membersType"; -import { useLockBodyScroll } from "@ui/src/hooks/useLockBodyScroll"; -import { MEMBER_FORM_MESSAGES } from "@repo/constants/messages"; -import { PlusIcon } from "@ui/public"; -import cn from "@ui/src/utils/cn"; -import Header from "./Header"; -import Navbar from "./Navbar"; -import MemberList from "./MemberList"; -import SidePanel from "./sidepanel"; -import MemberListSkeleton from "./skeleton/MemberListSkeleton"; - -export default function MembersContent(): JSX.Element { - const [activeTab, setActiveTab] = useState("전체"); - const [isSidePanelOpen, setIsSidePanelOpen] = useState(false); - const [selectedMember, setSelectedMember] = useState(null); - const [selectedSort, setSelectedSort] = useState("newest"); - const [keyword, setKeyword] = useState(""); - - useLockBodyScroll(isSidePanelOpen); - - const handleMemberClick = (member: MemberWithStaticImage): void => { - setSelectedMember(member); - setIsSidePanelOpen(true); - }; - - const handleOpenSidePanel = (): void => { - setIsSidePanelOpen(true); - }; - - const handleCloseSidePanel = (): void => { - setIsSidePanelOpen(false); - setSelectedMember(null); - }; - - return ( -
-
-
- -
- -
- }> - - -
- -
- -
- - -
- ); -} diff --git a/apps/web/app/(admin)/members/_components/ResponsiveMembersPage.tsx b/apps/web/app/(admin)/members/_components/ResponsiveMembersPage.tsx index dd5a93a2..cbce3f39 100644 --- a/apps/web/app/(admin)/members/_components/ResponsiveMembersPage.tsx +++ b/apps/web/app/(admin)/members/_components/ResponsiveMembersPage.tsx @@ -1,17 +1,85 @@ "use client"; +import { Suspense, useState } from "react"; import { PAGE_NAME } from "@ui/src/utils/constants/pageNames"; -import ErrorResetBoundary from "@/components/common/ErrorResetBoundary"; +import { Button } from "@ui/index"; +import { type MemberWithStaticImage, type SortOption } from "@repo/types/src/membersType"; +import { useLockBodyScroll } from "@ui/src/hooks/useLockBodyScroll"; +import { MEMBER_FORM_MESSAGES } from "@repo/constants/messages"; +import { PlusIcon } from "@ui/public"; +import cn from "@ui/src/utils/cn"; import ErrorFallback from "@/components/common/Fallback"; import { useRedirectOnMobile } from "@/app/_hooks/useRediectOnMobile"; -import MembersContent from "./MembersContent"; +import ErrorResetBoundary from "@/components/common/ErrorResetBoundary"; +import Header from "./Header"; +import Navbar from "./Navbar"; +import MemberList from "./MemberList"; +import SidePanel from "./sidepanel"; +import MemberListSkeleton from "./skeleton/MemberListSkeleton"; export default function ResponsiveMembersPage(): JSX.Element { + const [activeTab, setActiveTab] = useState("전체"); + const [isSidePanelOpen, setIsSidePanelOpen] = useState(false); + const [selectedMember, setSelectedMember] = useState(null); + const [selectedSort, setSelectedSort] = useState("newest"); + const [keyword, setKeyword] = useState(""); + useRedirectOnMobile(PAGE_NAME.SETTINGS); + useLockBodyScroll(isSidePanelOpen); + + const handleMemberClick = (member: MemberWithStaticImage): void => { + setSelectedMember(member); + setIsSidePanelOpen(true); + }; + + const handleOpenSidePanel = (): void => { + setIsSidePanelOpen(true); + }; + + const handleCloseSidePanel = (): void => { + setIsSidePanelOpen(false); + setSelectedMember(null); + }; return ( - +
+
+
+ +
+ +
+ }> + + +
+ +
+ +
+ + +
); } diff --git a/apps/web/app/settings/_components/modals/MembersSettingModal.tsx b/apps/web/app/settings/_components/modals/MembersSettingModal.tsx index 771906ca..ed2c8a62 100644 --- a/apps/web/app/settings/_components/modals/MembersSettingModal.tsx +++ b/apps/web/app/settings/_components/modals/MembersSettingModal.tsx @@ -1,4 +1,4 @@ -import MembersContent from "@/app/(admin)/members/_components/MembersContent"; +import ResponsiveMembersPage from "@/app/(admin)/members/_components/ResponsiveMembersPage"; import { SettingsModal, SettingsModalContent, SettingsModalHeader } from "@/components/SettingsModal"; interface MembersSettingModalProps { @@ -11,7 +11,7 @@ export default function MembersSettingModal({ isOpen, onClose }: MembersSettingM - + ); From 4568bf6675c7ff1553c04d8b8120ed66bfa81f38 Mon Sep 17 00:00:00 2001 From: Lin Date: Sat, 25 Jan 2025 11:27:18 +0900 Subject: [PATCH 02/28] =?UTF-8?q?Refactor:=20MemberQueryParams=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=9E=AC=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/api/members.ts | 13 +++++++------ .../app/(admin)/members/_components/MemberList.tsx | 9 +++++---- .../_hooks/useMembersSuspenseInfiniteQuery.ts | 11 ++--------- apps/web/lib/queryKey.ts | 4 ++-- packages/types/src/membersType.ts | 7 +++++++ 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/apps/web/api/members.ts b/apps/web/api/members.ts index d0734a80..d496002d 100644 --- a/apps/web/api/members.ts +++ b/apps/web/api/members.ts @@ -1,12 +1,13 @@ import { API_ENDPOINTS } from "@repo/constants"; -import type { MemberResponse, ResponseWithMessage, SortOption, MembersResponse } from "@repo/types/src/membersType"; +import type { + MemberResponse, + ResponseWithMessage, + MembersResponse, + MembersQueryParams, +} from "@repo/types/src/membersType"; import { axiosRequester } from "@/lib/axios"; -interface GetMembersProps { - selectedSort: SortOption; - role?: string; - team?: string; - keyword?: string; +interface GetMembersProps extends MembersQueryParams { cursor?: string | null; } diff --git a/apps/web/app/(admin)/members/_components/MemberList.tsx b/apps/web/app/(admin)/members/_components/MemberList.tsx index b2806e99..009d3a21 100644 --- a/apps/web/app/(admin)/members/_components/MemberList.tsx +++ b/apps/web/app/(admin)/members/_components/MemberList.tsx @@ -1,5 +1,4 @@ -import { useMemo } from "react"; -import { type MemberWithStaticImage, type SortOption } from "@repo/types/src/membersType"; +import { type MembersQueryParams, type MemberWithStaticImage, type SortOption } from "@repo/types/src/membersType"; import { SpinnerIcon } from "@ui/public"; import { useIntersectionObserver } from "@repo/ui/src/hooks/useIntersectionObserver"; import { getEmptyMessage } from "@repo/ui/src/utils/getEmptyMessage"; @@ -15,7 +14,7 @@ interface MemberListProps { } export default function MemberList({ selectedSort, activeTab, onMemberClick, keyword }: MemberListProps): JSX.Element { - const queryParams = useMemo(() => { + const getQueryParams = (): MembersQueryParams => { const baseParams = { selectedSort, keyword, @@ -32,7 +31,9 @@ export default function MemberList({ selectedSort, activeTab, onMemberClick, key } return { ...baseParams, team: activeTab }; - }, [activeTab, selectedSort, keyword]); + }; + + const queryParams = getQueryParams(); const { data: members, diff --git a/apps/web/app/(admin)/members/_hooks/useMembersSuspenseInfiniteQuery.ts b/apps/web/app/(admin)/members/_hooks/useMembersSuspenseInfiniteQuery.ts index 4e0405b7..0a471e24 100644 --- a/apps/web/app/(admin)/members/_hooks/useMembersSuspenseInfiniteQuery.ts +++ b/apps/web/app/(admin)/members/_hooks/useMembersSuspenseInfiniteQuery.ts @@ -4,18 +4,11 @@ import { useSuspenseInfiniteQuery, type UseSuspenseInfiniteQueryResult, } from "@tanstack/react-query"; -import type { MembersResponse, SortOption } from "@repo/types/src/membersType"; +import type { MembersResponse, MembersQueryParams } from "@repo/types/src/membersType"; import { type IUser } from "@repo/types"; import { getMembers } from "@/api/members"; import { QUERY_KEYS } from "@/lib/queryKey"; -export interface UseMembersSuspenseInfiniteQueryParams { - selectedSort: SortOption; - role?: string; - team?: string; - keyword?: string; -} - interface PageParam { pageParam: string | null; } @@ -25,7 +18,7 @@ export function useMembersSuspenseInfiniteQuery({ role, team, keyword, -}: UseMembersSuspenseInfiniteQueryParams): UseSuspenseInfiniteQueryResult { +}: MembersQueryParams): UseSuspenseInfiniteQueryResult { const options = infiniteQueryOptions({ queryKey: QUERY_KEYS.MEMBERS.list({ selectedSort, role, team, keyword }), queryFn: ({ pageParam }: PageParam): Promise => diff --git a/apps/web/lib/queryKey.ts b/apps/web/lib/queryKey.ts index fa093d38..764e7737 100644 --- a/apps/web/lib/queryKey.ts +++ b/apps/web/lib/queryKey.ts @@ -1,9 +1,9 @@ -import { type UseMembersSuspenseInfiniteQueryParams } from "@/app/(admin)/members/_hooks/useMembersSuspenseInfiniteQuery"; +import { type MembersQueryParams } from "@repo/types/src/membersType"; export const QUERY_KEYS = { MEMBERS: { ALL: ["members"], - list: (params: UseMembersSuspenseInfiniteQueryParams) => [...QUERY_KEYS.MEMBERS.ALL, params], + list: (params: MembersQueryParams) => [...QUERY_KEYS.MEMBERS.ALL, params], }, TEAMS: { ALL: ["teams"], diff --git a/packages/types/src/membersType.ts b/packages/types/src/membersType.ts index 2eda2be1..06c55219 100644 --- a/packages/types/src/membersType.ts +++ b/packages/types/src/membersType.ts @@ -64,3 +64,10 @@ export interface MembersResponse extends ResponseWithMessage { members: IUser[]; nextCursor: string | null; } + +export interface MembersQueryParams { + selectedSort: SortOption; + role?: string; + team?: string; + keyword?: string; +} From ba05bd98bf31253edf820e926ae7e0647fe177fa Mon Sep 17 00:00:00 2001 From: Lin Date: Sat, 25 Jan 2025 11:54:38 +0900 Subject: [PATCH 03/28] =?UTF-8?q?Chore:=20=EC=9E=90=EC=9E=98=ED=95=9C=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 - 오탈자 수정 - 불필요한 import 제거 - 주석 수정 --- apps/web/app/(admin)/members/_components/Navbar.tsx | 4 ++-- apps/web/app/(admin)/members/_components/sidepanel/Header.tsx | 3 ++- apps/web/app/(admin)/members/_components/sidepanel/index.tsx | 4 ++-- .../members/_components/skeleton/MemberListSkeleton.tsx | 2 +- .../app/(admin)/members/_components/skeleton/TabSkeleton.tsx | 2 +- packages/constants/index.ts | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/web/app/(admin)/members/_components/Navbar.tsx b/apps/web/app/(admin)/members/_components/Navbar.tsx index 795eb444..2ab73e6d 100644 --- a/apps/web/app/(admin)/members/_components/Navbar.tsx +++ b/apps/web/app/(admin)/members/_components/Navbar.tsx @@ -3,7 +3,7 @@ import { Suspense } from "react"; import useIsMobileStore from "@/app/store/useIsMobileStore"; import { Tab } from "./Tab"; import SortDropdown from "./SortDropdown"; -import TabsSkeleton from "./skeleton/TabSkeleton"; +import TabSkeleton from "./skeleton/TabSkeleton"; interface NavbarProps { activeTab: string; @@ -18,7 +18,7 @@ export default function Navbar({ activeTab, onTabChange, selectedSort, onSortCha return (