From cf35ca5b676cff6a2aa65018589614ed128342f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=ED=98=84=EC=A1=B0?= Date: Wed, 18 Sep 2024 17:01:09 +0900 Subject: [PATCH] =?UTF-8?q?Refactor:=20workspace-browse=20page=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ProjectCreateModal/index.tsx | 9 +- .../WorkspaceBrowseLayout/index.tsx | 39 ++-- frontend/src/pages/WorkspaceBrowseDetail.tsx | 169 ++++++++++-------- 3 files changed, 105 insertions(+), 112 deletions(-) diff --git a/frontend/src/components/ProjectCreateModal/index.tsx b/frontend/src/components/ProjectCreateModal/index.tsx index 3ed7cf9..2824c16 100644 --- a/frontend/src/components/ProjectCreateModal/index.tsx +++ b/frontend/src/components/ProjectCreateModal/index.tsx @@ -3,9 +3,10 @@ import ProjectCreateForm, { ProjectCreateFormValues } from './ProjectCreateForm' import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../ui/dialogCustom'; import { Button } from '@/components/ui/button'; import { Plus } from 'lucide-react'; +import { ProjectRequest } from '@/types'; interface ProjectCreateModalProps { - onSubmit: (data: { title: string; labelType: 'classification' | 'detection' | 'segmentation' }) => void; + onSubmit: (data: ProjectRequest) => void; buttonClass?: string; } @@ -17,7 +18,7 @@ export default function ProjectCreateModal({ onSubmit, buttonClass = '' }: Proje const formatLabelType = ( labelType: 'Classification' | 'Detection' | 'Segmentation' - ): 'classification' | 'detection' | 'segmentation' => { + ): ProjectRequest['projectType'] => { switch (labelType) { case 'Classification': return 'classification'; @@ -47,9 +48,9 @@ export default function ProjectCreateModal({ onSubmit, buttonClass = '' }: Proje { - const formattedData = { + const formattedData: ProjectRequest = { title: data.projectName, - labelType: formatLabelType(data.labelType), + projectType: formatLabelType(data.labelType), }; onSubmit(formattedData); handleClose(); diff --git a/frontend/src/components/WorkspaceBrowseLayout/index.tsx b/frontend/src/components/WorkspaceBrowseLayout/index.tsx index dffbfb9..ed2c682 100644 --- a/frontend/src/components/WorkspaceBrowseLayout/index.tsx +++ b/frontend/src/components/WorkspaceBrowseLayout/index.tsx @@ -1,10 +1,11 @@ -import { Suspense, useEffect } from 'react'; +import { useEffect, Suspense } from 'react'; import { NavLink, Outlet, useNavigate } from 'react-router-dom'; import Header from '../Header'; import useAuthStore from '@/stores/useAuthStore'; import WorkSpaceCreateModal from '../WorkSpaceCreateModal'; import { WorkspaceRequest, WorkspaceResponse } from '@/types'; import useWorkspaceListQuery from '@/queries/useWorkspaceListQuery'; +import { useCreateWorkspace } from '@/hooks/useWorkspaceHooks'; export default function WorkspaceBrowseLayout() { const { profile, isLoggedIn } = useAuthStore(); @@ -12,42 +13,22 @@ export default function WorkspaceBrowseLayout() { const navigate = useNavigate(); useEffect(() => { - if (!isLoggedIn || !memberId) { - console.error('로그인되지 않았거나 유효한 멤버 ID가 없습니다.'); + if (!isLoggedIn || memberId == 0) { navigate('/'); } }, [isLoggedIn, memberId, navigate]); - const { data: workspacesResponse, isLoading, isError } = useWorkspaceListQuery(memberId ?? 0); - - const workspaces = workspacesResponse?.workspaceResponses ?? []; - - // const createWorkspace = useCreateWorkspace(); + const { data: workspacesResponse } = useWorkspaceListQuery(memberId ?? 0); + const createWorkspace = useCreateWorkspace(); const handleCreateWorkspace = (data: WorkspaceRequest) => { - if (!memberId) return; - console.log(data); - // createWorkspace.mutate( - // { memberId, data }, - // { - // onSuccess: () => { - // console.log('워크스페이스가 성공적으로 생성되었습니다.'); - // queryClient.invalidateQueries({ queryKey: ['workspaces'] }); - // }, - // onError: (error: AxiosError) => { - // console.error('워크스페이스 생성 실패:', error.message); - // }, - // } - // ); + createWorkspace.mutate({ + memberId, + data, + }); }; - if (isLoading) { - return

Loading workspaces...

; - } - - if (isError) { - return

Error loading workspaces. Please try again later.

; - } + const workspaces = workspacesResponse?.workspaceResponses ?? []; return ( <> diff --git a/frontend/src/pages/WorkspaceBrowseDetail.tsx b/frontend/src/pages/WorkspaceBrowseDetail.tsx index c15a0c6..60833e7 100644 --- a/frontend/src/pages/WorkspaceBrowseDetail.tsx +++ b/frontend/src/pages/WorkspaceBrowseDetail.tsx @@ -3,8 +3,10 @@ import ProjectCard from '@/components/ProjectCard'; import { Smile } from 'lucide-react'; import ProjectCreateModal from '../components/ProjectCreateModal'; import useAuthStore from '@/stores/useAuthStore'; -import { ProjectResponse } from '@/types'; +import { ProjectResponse, ProjectRequest } from '@/types'; import useProjectListQuery from '@/queries/useProjectListQuery'; +import useWorkspaceQuery from '@/queries/useWorkspaceQuery'; +import { useCreateProject } from '@/hooks/useProjectHooks'; import { webPath } from '@/router'; export default function WorkspaceBrowseDetail() { @@ -13,102 +15,111 @@ export default function WorkspaceBrowseDetail() { const { profile } = useAuthStore(); const memberId = profile?.id ?? 0; const navigate = useNavigate(); - // const createProject = useCreateProject(); + const { data: workspaceData } = useWorkspaceQuery(workspaceId, memberId); const { data: projectsResponse, isError } = useProjectListQuery(workspaceId, memberId); + const createProject = useCreateProject(); - const handleCreateProject = (data: { title: string; labelType: 'classification' | 'detection' | 'segmentation' }) => { - console.log(data); - // createProject.mutate( - // { - // workspaceId: workspaceId, - // memberId, - // data: { title: data.title, projectType: data.labelType }, - // }, - // { - // onSuccess: () => { - // console.log('프로젝트가 성공적으로 생성되었습니다.'); - // refetch(); - // }, - // onError: (error) => { - // console.error('프로젝트 생성 실패:', error); - // const errorMessage = error?.response?.data?.message || error.message || '알 수 없는 오류'; - // console.error('프로젝트 생성 실패:', errorMessage); - // }, - // } - // ); + const handleCreateProject = (data: ProjectRequest) => { + createProject.mutate({ + workspaceId, + memberId, + data, + }); }; - // TODO: 반환 형식 반영 projectsResponse?.workspaceResponses => projectResponse const projects: ProjectResponse[] = projectsResponse?.workspaceResponses ?? []; - if (isNaN(workspaceId)) { - return ( -
-
- + + {isNaN(workspaceId) || isError || !workspaceId ? ( + + ) : ( + + )} +
+ ); +} + +function HeaderSection({ + workspaceName, + onCreateProject, +}: { + workspaceName: string; + onCreateProject: (data: ProjectRequest) => void; +}) { + return ( +
+

{workspaceName}

+
+
+ -
작업할 워크스페이스를 선택하세요
- ); - } +
+ ); +} - if (isError || !workspaceId) { +function EmptyStateMessage({ workspaceId }: { workspaceId: number }) { + return ( +
+
+ +
+ {!workspaceId ? '작업할 워크스페이스를 선택하세요.' : '작업할 프로젝트가 없습니다.'} +
+
+
+ ); +} + +function ProjectList({ + projects, + workspaceId, + navigate, +}: { + projects: ProjectResponse[]; + workspaceId: number; + navigate: ReturnType; +}) { + if (projects.length === 0) { return (
-
- -
- {!workspaceId ? '작업할 워크스페이스를 선택하세요.' : '작업할 프로젝트가 없습니다.'} -
-
+ +
작업할 프로젝트가 없습니다.
); } return ( -
-
-

{`Workspace-${workspaceId}`}

-
-
- -
-
-
- {projects.length > 0 ? ( -
- {projects.map((project: ProjectResponse) => ( - { - navigate(`${webPath.workspace()}/${workspaceId}/project/${project.id}`); - }} - /> - ))} -
- ) : ( -
-
- -
작업할 프로젝트가 없습니다.
-
-
- )} +
+ {projects.map((project: ProjectResponse) => ( + { + navigate(`${webPath.workspace()}/${workspaceId}/project/${project.id}`); + }} + /> + ))}
); }