From 62cb3677279b8a4486d1fc634642001586e08b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=ED=98=84=EC=A1=B0?= Date: Fri, 20 Sep 2024 08:21:56 +0900 Subject: [PATCH] =?UTF-8?q?Feat=20:=20admin=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=20=EB=B6=80=EB=B6=84=20=EA=B0=80=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectMemberManageForm.tsx | 17 ++- .../WorkspaceMemberManageForm.tsx | 129 +++--------------- .../components/AdminMemberManage/index.tsx | 28 ++-- .../MemberAddModal/MemberAddForm.tsx | 56 ++++---- 4 files changed, 63 insertions(+), 167 deletions(-) diff --git a/frontend/src/components/AdminMemberManage/ProjectMemberManageForm.tsx b/frontend/src/components/AdminMemberManage/ProjectMemberManageForm.tsx index 66f46cd..226e296 100644 --- a/frontend/src/components/AdminMemberManage/ProjectMemberManageForm.tsx +++ b/frontend/src/components/AdminMemberManage/ProjectMemberManageForm.tsx @@ -1,12 +1,13 @@ -import { useParams } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; import { Form, FormControl, FormField, FormItem, FormMessage } from '../ui/form'; import { Input } from '../ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select'; -import { ProjectMemberResponse } from '@/types'; import useUpdateProjectMemberPrivilegeQuery from '@/queries/projects/useUpdateProjectMemberPrivilegeQuery'; +import useProjectMembersQuery from '@/queries/projects/useProjectMembersQuery'; +import useAuthStore from '@/stores/useAuthStore'; type Role = 'ADMIN' | 'MANAGER' | 'EDITOR' | 'VIEWER'; @@ -31,12 +32,14 @@ const formSchema = z.object({ export type ProjectMemberManageFormValues = z.infer; -interface ProjectMemberManageFormProps { - members: ProjectMemberResponse[]; -} +export default function ProjectMemberManageForm() { + const location = useLocation(); + const searchParams = new URLSearchParams(location.search); + const projectId = searchParams.get('projectId'); + const profile = useAuthStore((state) => state.profile); + const memberId = profile?.id || 0; -export default function ProjectMemberManageForm({ members }: ProjectMemberManageFormProps) { - const { projectId } = useParams<{ projectId: string }>(); + const { data: members = [] } = useProjectMembersQuery(Number(projectId), memberId); const { mutate: updatePrivilege } = useUpdateProjectMemberPrivilegeQuery(); const form = useForm({ diff --git a/frontend/src/components/AdminMemberManage/WorkspaceMemberManageForm.tsx b/frontend/src/components/AdminMemberManage/WorkspaceMemberManageForm.tsx index 5df5b95..22d1779 100644 --- a/frontend/src/components/AdminMemberManage/WorkspaceMemberManageForm.tsx +++ b/frontend/src/components/AdminMemberManage/WorkspaceMemberManageForm.tsx @@ -1,125 +1,30 @@ import { useParams } from 'react-router-dom'; -import { useForm } from 'react-hook-form'; -import { z } from 'zod'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { Form, FormControl, FormField, FormItem, FormMessage } from '../ui/form'; -import { Input } from '../ui/input'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select'; -import { WorkspaceMemberResponse } from '@/types'; -import useUpdateProjectMemberPrivilegeQuery from '@/queries/projects/useUpdateProjectMemberPrivilegeQuery'; +import useWorkspaceMembersQuery from '@/queries/workspaces/useWorkspaceMembersQuery'; -type Role = 'ADMIN' | 'MANAGER' | 'EDITOR' | 'VIEWER'; - -const roles: Role[] = ['ADMIN', 'MANAGER', 'EDITOR', 'VIEWER']; - -const roleToStr: { [key in Role]: string } = { - ADMIN: '관리자', - MANAGER: '매니저', - EDITOR: '에디터', - VIEWER: '뷰어', -}; - -const formSchema = z.object({ - members: z.array( - z.object({ - memberId: z.number(), - nickname: z.string().nonempty('닉네임을 입력하세요.'), - role: z.enum(roles as [Role, ...Role[]], { errorMap: () => ({ message: '역할을 선택해주세요.' }) }), - }) - ), -}); - -export type WorkspaceMemberManageFormValues = z.infer; - -interface WorkspaceMemberManageFormProps { - members: WorkspaceMemberResponse[]; -} - -export default function WorkspaceMemberManageForm({ members }: WorkspaceMemberManageFormProps) { +export default function WorkspaceMemberManageForm() { const { workspaceId } = useParams<{ workspaceId: string }>(); - const { mutate: updatePrivilege } = useUpdateProjectMemberPrivilegeQuery(); - const form = useForm({ - resolver: zodResolver(formSchema), - defaultValues: { - members: members.map((m) => ({ - memberId: m.memberId, - nickname: m.nickname, - role: m.privilegeType as Role, - })), - }, - }); - - const handleRoleChange = (memberId: number, role: Role) => { - updatePrivilege({ - workspaceId: Number(workspaceId), - memberId, - privilegeData: { - memberId, - privilegeType: role, - }, - }); - }; + const { data: members = [] } = useWorkspaceMembersQuery(Number(workspaceId)); return ( -
-
- {members.map((member, index) => ( +
+ {members.length === 0 ? ( +
워크스페이스에 멤버가 없습니다.
+ ) : ( + members.map((member) => (
- ( - - - - - - - )} - /> - - ( - - - - - - - )} + {member.nickname} + {member.nickname}
- ))} -
- + )) + )} +
); } diff --git a/frontend/src/components/AdminMemberManage/index.tsx b/frontend/src/components/AdminMemberManage/index.tsx index ef1abb3..d493c54 100644 --- a/frontend/src/components/AdminMemberManage/index.tsx +++ b/frontend/src/components/AdminMemberManage/index.tsx @@ -1,35 +1,35 @@ import { useState } from 'react'; -import { useParams } from 'react-router-dom'; +import { useParams, useLocation } from 'react-router-dom'; import useAuthStore from '@/stores/useAuthStore'; import useAddWorkspaceMemberQuery from '@/queries/workspaces/useAddWorkspaceMemberQuery'; import useAddProjectMemberQuery from '@/queries/projects/useAddProjectMemberQuery'; -import useWorkspaceMembersQuery from '@/queries/workspaces/useWorkspaceMembersQuery'; -import useProjectMembersQuery from '@/queries/projects/useProjectMembersQuery'; import MemberAddModal from '../MemberAddModal'; import { MemberAddFormValues } from '../MemberAddModal/MemberAddForm'; import WorkspaceMemberManageForm from './WorkspaceMemberManageForm'; import ProjectMemberManageForm from './ProjectMemberManageForm'; export default function AdminMemberManage() { - const { workspaceId, projectId } = useParams<{ workspaceId?: string; projectId?: string }>(); + const { workspaceId } = useParams<{ workspaceId: string }>(); + const location = useLocation(); + const searchParams = new URLSearchParams(location.search); + const projectId = searchParams.get('projectId'); + const profile = useAuthStore((state) => state.profile); const memberId = profile?.id || 0; + const addWorkspaceMember = useAddWorkspaceMemberQuery(); + const addProjectMember = useAddProjectMemberQuery(); + const [, setInviteModalOpen] = useState(false); const handleMemberInvite = (data: MemberAddFormValues) => { if (workspaceId) { - const addWorkspaceMember = useAddWorkspaceMemberQuery(); addWorkspaceMember.mutate({ workspaceId: Number(workspaceId), memberId: memberId, - newMember: { - memberId: 0, - privilegeType: data.role, - }, + newMemberId: data.memberId, }); - } else if (projectId) { - const addProjectMember = useAddProjectMemberQuery(); + } else if (projectId && Number(projectId) > 0) { addProjectMember.mutate({ projectId: Number(projectId), memberId: memberId, @@ -49,10 +49,8 @@ export default function AdminMemberManage() { - {workspaceId && } - {projectId && ( - - )} + {workspaceId && } + {projectId && } ); } diff --git a/frontend/src/components/MemberAddModal/MemberAddForm.tsx b/frontend/src/components/MemberAddModal/MemberAddForm.tsx index 3031f08..a2b329a 100644 --- a/frontend/src/components/MemberAddModal/MemberAddForm.tsx +++ b/frontend/src/components/MemberAddModal/MemberAddForm.tsx @@ -20,22 +20,14 @@ const privilegeTypeToStr: { [key in PrivilegeType]: string } = { }; const formSchema = z.object({ - email: z - .string() - .email({ - message: '올바른 이메일 형식을 입력해주세요.', - }) - .max(40) - .min(1, { - message: '초대할 멤버의 이메일 주소를 입력해주세요.', - }), + memberId: z.number().nonnegative({ message: '멤버를 선택하세요.' }), role: z.enum(privilegeTypes), }); export type MemberAddFormValues = z.infer; const defaultValues: Partial = { - email: '', + memberId: 0, role: undefined, }; @@ -48,43 +40,40 @@ export default function MemberAddForm({ onSubmit }: { onSubmit: (data: MemberAdd const [keyword, setKeyword] = useState(''); const { data: members } = useSearchMembersByEmailQuery(keyword); + const handleMemberSelect = (memberId: number) => { + form.setValue('memberId', memberId); + }; + return (
- ( - - 이메일 - - { - field.onChange(e); - setKeyword(e.target.value); - }} - /> - - - - )} - /> + + 이메일 + + setKeyword(e.target.value)} + /> + + + + {members && (
    {members.map((member) => (
  • handleMemberSelect(member.id)} > {member.nickname} {member.nickname} ({member.email}) @@ -124,10 +113,11 @@ export default function MemberAddForm({ onSubmit }: { onSubmit: (data: MemberAdd )} /> +