From aa5376031345a0660141e27475e727a089b3055d Mon Sep 17 00:00:00 2001 From: G-hoon Date: Wed, 18 Sep 2024 02:38:09 +0900 Subject: [PATCH] =?UTF-8?q?[feat/#58]=20=EB=82=98=EC=9D=98=20=ED=81=AC?= =?UTF-8?q?=EB=A3=A8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 나의 크루 관련 API 연동 구현 - 컴포넌트 분리 - 대시보드 레이아웃 개선 --- src/App.tsx | 2 +- src/api/group.ts | 45 ++++++++ src/assets/icons/crew-my-crew-leader-icon.svg | 15 +++ src/components/Crew/CrewList.tsx | 38 ++++--- .../Crew/{ => MyCrew}/CrewRanking.tsx | 0 src/components/Crew/MyCrew/MyCrewHeader.tsx | 21 ++++ .../{ => MyCrew}/MyCrewRankingContainer.tsx | 46 +++----- src/components/SideNav.tsx | 2 +- src/hooks/useMyGroup.ts | 76 +++++++++++++ src/layouts/AnalysisLayout.tsx | 2 +- src/pages/AnalysisDashboard.tsx | 4 + src/pages/MyCrew.tsx | 100 ++++++++++-------- src/store/MyGroup.ts | 12 +++ 13 files changed, 269 insertions(+), 94 deletions(-) create mode 100644 src/assets/icons/crew-my-crew-leader-icon.svg rename src/components/Crew/{ => MyCrew}/CrewRanking.tsx (100%) create mode 100644 src/components/Crew/MyCrew/MyCrewHeader.tsx rename src/components/Crew/{ => MyCrew}/MyCrewRankingContainer.tsx (55%) create mode 100644 src/hooks/useMyGroup.ts create mode 100644 src/store/MyGroup.ts diff --git a/src/App.tsx b/src/App.tsx index 5362fba..c7f0d58 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,7 +10,7 @@ const App = (): React.ReactElement => { return ( - + ) diff --git a/src/api/group.ts b/src/api/group.ts index eec5675..d06d0aa 100644 --- a/src/api/group.ts +++ b/src/api/group.ts @@ -28,6 +28,11 @@ export interface groupUserRank { score: number } +export interface GroupUserRankData { + groupId: number + ranks: groupUserRank[] +} + export interface groupsReq { page: number size: number @@ -54,6 +59,15 @@ export interface groupJoinRes { groupUserId: number } +export interface MyGroupData { + id: string + name: string + description: string + userCount: number + userCapacity: number + ownerNickname: string +} + export const getGroups = async (groupsReq: groupsReq): Promise => { try { const res = await axiosInstance.get(`/groups?${qs.stringify(groupsReq)}`) @@ -92,3 +106,34 @@ export const checkGroupName = async (name: string): Promise => { throw e } } + +export const getGroupScores = async (groupdId: string | number): Promise<{ data: GroupUserRankData }> => { + try { + const res = await axiosInstance.get(`/group-scores?groupId=${groupdId}`) + return res.data + } catch (e) { + throw e + } +} + +export const getMyGroup = async (): Promise<{ data: MyGroupData }> => { + try { + const res = await axiosInstance.get(`/groups/my-group`) + return res.data + } catch (e) { + throw e + } +} + +export const withdrawMyGroup = async (id: string | number | undefined): Promise => { + if (!id) { + throw new Error("잘못된 크루 id 입니다.") + } + try { + const res = await axiosInstance.delete(`/groups/${id}/withdraw`) + console.log("res: ", res) + return res + } catch (e) { + throw e + } +} diff --git a/src/assets/icons/crew-my-crew-leader-icon.svg b/src/assets/icons/crew-my-crew-leader-icon.svg new file mode 100644 index 0000000..a52a7f1 --- /dev/null +++ b/src/assets/icons/crew-my-crew-leader-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/components/Crew/CrewList.tsx b/src/components/Crew/CrewList.tsx index 7471844..c0a72a3 100644 --- a/src/components/Crew/CrewList.tsx +++ b/src/components/Crew/CrewList.tsx @@ -2,12 +2,13 @@ import { group, groupsReq, sort } from "@/api" import EmptyCrewImage from "@/assets/images/crew-empty.png" import CrewItem from "@/components/Crew/CrewItem" import { useGetGroups } from "@/hooks/useGroupMutation" +import { useModals } from "@/hooks/useModals" +import useMyGroup from "@/hooks/useMyGroup" import CreateCrewIcon from "@assets/icons/crew-create-button-icon.svg?react" import SortCrewIcon from "@assets/icons/crew-sort-icon.svg?react" import { ReactElement, useEffect, useRef, useState } from "react" -import { useModals } from "@/hooks/useModals" -import MyCrewRankingContainer from "./MyCrewRankingContainer" import { modals } from "../Modal/Modals" +import MyCrewRankingContainer from "./MyCrew/MyCrewRankingContainer" const SORT_LIST = [ { sort: "userCount,desc", label: "크루원 많은 순" }, @@ -15,9 +16,9 @@ const SORT_LIST = [ ] const CrewList = (): ReactElement => { - const [mode] = useState<"my" | "list">("my") + const { myGroupData, ranks, myRank } = useMyGroup() const [isDropdownOpen, setIsDropdownOpen] = useState(false) - + console.log("myGroupData: ", myGroupData) const [params, setParams] = useState({ page: 0, size: 10000, @@ -110,22 +111,31 @@ const CrewList = (): ReactElement => { return (
- {mode === "my" && } + {myGroupData && Object.keys(myGroupData).length > 0 && ( + + )} {/* header */}
전체크루 {isLoading ? "" : `(${data?.totalCount})`}
- {mode === "list" && ( -
- -
크루 만들기
-
- )} + {!myGroupData || + (myGroupData && Object.keys(myGroupData).length === 0 && ( +
+ +
크루 만들기
+
+ ))}
{/* sort */} diff --git a/src/components/Crew/CrewRanking.tsx b/src/components/Crew/MyCrew/CrewRanking.tsx similarity index 100% rename from src/components/Crew/CrewRanking.tsx rename to src/components/Crew/MyCrew/CrewRanking.tsx diff --git a/src/components/Crew/MyCrew/MyCrewHeader.tsx b/src/components/Crew/MyCrew/MyCrewHeader.tsx new file mode 100644 index 0000000..590bbe9 --- /dev/null +++ b/src/components/Crew/MyCrew/MyCrewHeader.tsx @@ -0,0 +1,21 @@ +import CreateCrewIcon from "@assets/icons/crew-create-button-icon.svg?react" + +interface MyCrewHeaderProps { + openCreateModal: () => void +} + +export default function MyCrewHeader(props: MyCrewHeaderProps) { + const { openCreateModal } = props + return ( +
+
나의 크루
+
+ +
크루 만들기
+
+
+ ) +} diff --git a/src/components/Crew/MyCrewRankingContainer.tsx b/src/components/Crew/MyCrew/MyCrewRankingContainer.tsx similarity index 55% rename from src/components/Crew/MyCrewRankingContainer.tsx rename to src/components/Crew/MyCrew/MyCrewRankingContainer.tsx index 7b37fdc..9a4eb0d 100644 --- a/src/components/Crew/MyCrewRankingContainer.tsx +++ b/src/components/Crew/MyCrew/MyCrewRankingContainer.tsx @@ -1,37 +1,35 @@ -import CreateCrewIcon from "@assets/icons/crew-create-button-icon.svg?react" import SendInvitationIcon from "@assets/icons/crew-send-invitation.svg?react" import CrewUserIcon from "@assets/icons/crew-user-icon.svg?react" import { Link } from "react-router-dom" import CrewRanking from "./CrewRanking" import RoutePath from "@/constants/routes.json" +import MyCrewHeader from "./MyCrewHeader" +import { groupUserRank, MyGroupData } from "@/api" +import dayjs from "dayjs" interface MyCrewRankingContainerProps { + myGroupData: MyGroupData + ranks: groupUserRank[] + myRank: groupUserRank | undefined openCreateModal: () => void openInviteModal: () => void } export default function MyCrewRankingContainer(props: MyCrewRankingContainerProps) { - const { openCreateModal, openInviteModal } = props + const { myGroupData, ranks, myRank, openCreateModal, openInviteModal } = props return (
-
-
나의 크루
-
- -
크루 만들기
-
-
+
-
주인공 다 모여랏
+
{myGroupData.name}
- 7/30명 + + {myGroupData.userCount}/{myGroupData.userCapacity}명 +
{/* 랭킹 표시 */}
- + {ranks.length > 0 && myRank && }
diff --git a/src/components/SideNav.tsx b/src/components/SideNav.tsx index d30c38c..451bb1f 100644 --- a/src/components/SideNav.tsx +++ b/src/components/SideNav.tsx @@ -81,7 +81,7 @@ export default function SideNav(): React.ReactElement {