From c317e7bcf095425cbc861f70e1497fc88d3be277 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 8 Nov 2024 19:57:36 +0900 Subject: [PATCH 1/5] =?UTF-8?q?Feat(group-member):=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EB=82=98=EA=B0=80=EA=B8=B0=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/services/group/member.api.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/api/services/group/member.api.ts b/src/api/services/group/member.api.ts index 4a95285..e860882 100644 --- a/src/api/services/group/member.api.ts +++ b/src/api/services/group/member.api.ts @@ -57,3 +57,9 @@ export const membersQuries = { export const joinGroupMember = async (inviteCode: string) => { await authorizationInstance.post('/api/group/join', { inviteCode }) } + +export const exitGroupMember = async (groupId: number) => { + await authorizationInstance.post('/api/group/exit', { + groupId, + }) +} From 78519ea4b7d08e91ec109f18799e10e90fc3cce0 Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 8 Nov 2024 19:57:55 +0900 Subject: [PATCH 2/5] =?UTF-8?q?Feat(group-member):=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EB=82=98=EA=B0=80=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/GroupPage/ExitGroupButton/index.tsx | 58 +++++++++++++++++++ src/pages/GroupPage/index.tsx | 21 +++++-- 2 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 src/pages/GroupPage/ExitGroupButton/index.tsx diff --git a/src/pages/GroupPage/ExitGroupButton/index.tsx b/src/pages/GroupPage/ExitGroupButton/index.tsx new file mode 100644 index 0000000..66a6294 --- /dev/null +++ b/src/pages/GroupPage/ExitGroupButton/index.tsx @@ -0,0 +1,58 @@ +import { BiSolidError } from 'react-icons/bi' +import { useNavigate } from 'react-router-dom' + +import { Button, Flex, useDisclosure } from '@chakra-ui/react' +import { useMutation } from '@tanstack/react-query' + +import { queryClient } from '@/api/instance' +import { exitGroupMember } from '@/api/services/group/member.api' +import { + ConfirmModal, + ConfirmModalButton, +} from '@/components/Modal/ConfirmModal' + +interface ExitGroupButtonProps { + groupId: number + groupName: string +} + +export const ExitGroupButton = ({ + groupId, + groupName, +}: ExitGroupButtonProps) => { + const { isOpen, onOpen, onClose } = useDisclosure() + const navigate = useNavigate() + + const { mutate: exitGroup } = useMutation({ + mutationFn: () => exitGroupMember(groupId), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['groups'] }) + navigate('/') + }, + }) + + return ( + + + } + title={`정말로 ${groupName} 그룹에서 나가시겠습니까?`} + description="그룹에서의 모든 활동은 삭제됩니다." + confirmButton={ + { + onClose() + exitGroup() + }} + > + 확인 + + } + /> + + ) +} diff --git a/src/pages/GroupPage/index.tsx b/src/pages/GroupPage/index.tsx index 8c1863b..570a0e9 100644 --- a/src/pages/GroupPage/index.tsx +++ b/src/pages/GroupPage/index.tsx @@ -1,12 +1,13 @@ import { useParams } from 'react-router-dom' -import { Box } from '@chakra-ui/react' +import { Box, Flex } from '@chakra-ui/react' import { useGroupInfo } from '@/api/services/group/group.api' import { Loading } from '@/components/Loading' import { RankingGraph } from '@/components/RankingGraph' import ErrorPage from '@/pages/ErrorPage' +import { ExitGroupButton } from './ExitGroupButton' import Management from './Management' import Navigate from './Navigate' import Profile from './Profile' @@ -47,10 +48,6 @@ export default function GroupPage() {
- - - - {groupId && }
) } @@ -66,5 +63,17 @@ const GroupSection = ({ groupId }: GroupSectionProps) => { if (error) return if (!groupData) return - return + return ( + + + + + + {groupId && } + + + ) } From 9a533ba98923f266bec0de694a6826bf95ebaa9e Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 8 Nov 2024 20:19:04 +0900 Subject: [PATCH 3/5] =?UTF-8?q?Feat(group-member):=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=97=AD=ED=95=A0=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/services/group/member.api.ts | 23 +++++++++++++++++-- src/pages/GroupPage/ExitGroupButton/index.tsx | 9 +++++++- src/pages/GroupPage/Management/index.tsx | 5 ++-- src/pages/GroupPage/Profile/index.tsx | 8 +++---- src/pages/GroupPage/index.tsx | 13 +++++++---- src/types/index.ts | 4 +++- 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/api/services/group/member.api.ts b/src/api/services/group/member.api.ts index e860882..4ea6bc2 100644 --- a/src/api/services/group/member.api.ts +++ b/src/api/services/group/member.api.ts @@ -1,8 +1,8 @@ -import { useSuspenseInfiniteQuery } from '@tanstack/react-query' +import { useQuery, useSuspenseInfiniteQuery } from '@tanstack/react-query' import { authorizationInstance } from '@/api/instance' import { appendParamsToUrl } from '@/api/utils/common/appendParamsToUrl' -import { Member, PagingRequestParams, PagingResponse } from '@/types' +import { GroupRole, Member, PagingRequestParams, PagingResponse } from '@/types' type GroupMembersRequestParams = { groupId: number @@ -63,3 +63,22 @@ export const exitGroupMember = async (groupId: number) => { groupId, }) } + +type GruopRoleResponse = { + role: GroupRole +} + +const getGroupRole = async (groupId: number) => { + const response = await authorizationInstance.get( + `/api/group/${groupId}/role` + ) + + return response.data.role +} + +export const useGroupRole = (groupId: number) => { + return useQuery({ + queryKey: ['group', 'role', groupId], + queryFn: () => getGroupRole(groupId), + }) +} diff --git a/src/pages/GroupPage/ExitGroupButton/index.tsx b/src/pages/GroupPage/ExitGroupButton/index.tsx index 66a6294..28d022e 100644 --- a/src/pages/GroupPage/ExitGroupButton/index.tsx +++ b/src/pages/GroupPage/ExitGroupButton/index.tsx @@ -10,15 +10,18 @@ import { ConfirmModal, ConfirmModalButton, } from '@/components/Modal/ConfirmModal' +import { GroupRole } from '@/types' interface ExitGroupButtonProps { groupId: number groupName: string + role: GroupRole } export const ExitGroupButton = ({ groupId, groupName, + role, }: ExitGroupButtonProps) => { const { isOpen, onOpen, onClose } = useDisclosure() const navigate = useNavigate() @@ -41,7 +44,11 @@ export const ExitGroupButton = ({ onClose={onClose} icon={} title={`정말로 ${groupName} 그룹에서 나가시겠습니까?`} - description="그룹에서의 모든 활동은 삭제됩니다." + description={ + role === 'LEADER' + ? '그룹장이 그룹을 나가면 그룹이 삭제됩니다.' + : '그룹에서의 모든 활동은 삭제됩니다.' + } confirmButton={ { diff --git a/src/pages/GroupPage/Management/index.tsx b/src/pages/GroupPage/Management/index.tsx index 6cd807e..a99df90 100644 --- a/src/pages/GroupPage/Management/index.tsx +++ b/src/pages/GroupPage/Management/index.tsx @@ -4,11 +4,12 @@ import { Link } from 'react-router-dom' import { Box, Flex, Text } from '@chakra-ui/react' import { CardButton } from '@/components/CardButton' +import { GroupRole } from '@/types' import { InviteMemberModal } from './InviteMemberModal' interface ManagementProps { - role: 'leader' | 'member' + role: GroupRole groupId: number } @@ -25,7 +26,7 @@ export default function Management({ role, groupId }: ManagementProps) { Icon={BiPlus} /> - {role === 'leader' && ( + {role === 'LEADER' && ( - {role === 'leader' ? '그룹장' : '그룹원'} + {role === 'LEADER' ? '그룹장' : '그룹원'} @@ -95,7 +95,7 @@ export default function Profile({ role, gprofile }: GroupProps) { {gprofile.groupDescription} )} - {role === 'leader' && ( + {role === 'LEADER' && ( setIsEditing(isEdit)} diff --git a/src/pages/GroupPage/index.tsx b/src/pages/GroupPage/index.tsx index 570a0e9..325f60d 100644 --- a/src/pages/GroupPage/index.tsx +++ b/src/pages/GroupPage/index.tsx @@ -3,6 +3,7 @@ import { useParams } from 'react-router-dom' import { Box, Flex } from '@chakra-ui/react' import { useGroupInfo } from '@/api/services/group/group.api' +import { useGroupRole } from '@/api/services/group/member.api' import { Loading } from '@/components/Loading' import { RankingGraph } from '@/components/RankingGraph' import ErrorPage from '@/pages/ErrorPage' @@ -39,11 +40,11 @@ const dummyRankData = [ }, ] -const userRole = 'leader' // "leader" or "member" - export default function GroupPage() { const { groupId } = useParams<{ groupId: string }>() + if (!groupId) return + return (
@@ -58,21 +59,23 @@ interface GroupSectionProps { const GroupSection = ({ groupId }: GroupSectionProps) => { const { data: groupData, error, status } = useGroupInfo(groupId) + const { data: role } = useGroupRole(groupId) if (status === 'pending') return if (error) return - if (!groupData) return + if (!groupData || !role) return return ( - + - {groupId && } + {groupId && } ) diff --git a/src/types/index.ts b/src/types/index.ts index e031077..19cf50a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -98,7 +98,7 @@ export type Modal = { export type Member = { groupMemberId: number userId: number - role: 'LEADER' | 'MEMBER' + role: GroupRole userName: string memberImageUrl: string joinedAt: string @@ -128,3 +128,5 @@ export type UserRankingItem = { count: number groupName: string } + +export type GroupRole = 'MEMBER' | 'LEADER' From 511126e51da583c62c3175c09a37753e7160ea5e Mon Sep 17 00:00:00 2001 From: ajin Date: Fri, 8 Nov 2024 20:37:01 +0900 Subject: [PATCH 4/5] =?UTF-8?q?Design(group-member):=20=EA=B7=B8=EB=A3=B9?= =?UTF-8?q?=20=ED=83=88=ED=87=B4=20=EB=B2=84=ED=8A=BC=20=EC=83=89=EC=83=81?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/GroupPage/ExitGroupButton/index.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pages/GroupPage/ExitGroupButton/index.tsx b/src/pages/GroupPage/ExitGroupButton/index.tsx index 28d022e..ed55824 100644 --- a/src/pages/GroupPage/ExitGroupButton/index.tsx +++ b/src/pages/GroupPage/ExitGroupButton/index.tsx @@ -36,7 +36,13 @@ export const ExitGroupButton = ({ return ( - Date: Fri, 8 Nov 2024 21:06:45 +0900 Subject: [PATCH 5/5] =?UTF-8?q?Fix:=20=EC=B9=9C=EA=B5=AC=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=9B=84=20=EC=83=88=EB=A1=9C=EA=B3=A0=EC=B9=A8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SelectFriendSection/SelectFriendHeader/index.tsx | 3 +++ src/pages/MainPage/UseProfilehook/index.ts | 1 + 2 files changed, 4 insertions(+) diff --git a/src/pages/Layout/MainLayout/MemberSection/SelectFriendSection/SelectFriendHeader/index.tsx b/src/pages/Layout/MainLayout/MemberSection/SelectFriendSection/SelectFriendHeader/index.tsx index 6819a21..cf48020 100644 --- a/src/pages/Layout/MainLayout/MemberSection/SelectFriendSection/SelectFriendHeader/index.tsx +++ b/src/pages/Layout/MainLayout/MemberSection/SelectFriendSection/SelectFriendHeader/index.tsx @@ -1,4 +1,5 @@ import { BiCheckCircle, BiUserCheck } from 'react-icons/bi' +import { useNavigate } from 'react-router-dom' import { Box, Text, useDisclosure } from '@chakra-ui/react' import { useMutation, useQueryClient } from '@tanstack/react-query' @@ -20,6 +21,7 @@ export const SelectFreindHeader = ({ }: SelectFreindHeaderProps) => { const queryClient = useQueryClient() const { isOpen, onOpen, onClose } = useDisclosure() + const navigate = useNavigate() const setMemberType = useMemberTypeStore((state) => state.setMemberType) const friendList = useFriendStore((state) => state.friendList()) @@ -62,6 +64,7 @@ export const SelectFreindHeader = ({ onClose={() => { onClose() setMemberType('FRIEND') + navigate(0) }} icon={} title="친구 설정이 완료되었습니다." diff --git a/src/pages/MainPage/UseProfilehook/index.ts b/src/pages/MainPage/UseProfilehook/index.ts index 7d27e63..ede3802 100644 --- a/src/pages/MainPage/UseProfilehook/index.ts +++ b/src/pages/MainPage/UseProfilehook/index.ts @@ -7,6 +7,7 @@ import { Friend } from '@/types' const useProfile = () => { const { data: all } = useSuspenseQuery(friendsQueries.myFriends()) + const [remain, setRemain] = useState([]) const [picked, setPicked] = useState([])