Refactor: workspace-browse page 리팩토링
This commit is contained in:
parent
331a110df1
commit
cf35ca5b67
@ -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
|
||||
<DialogHeader title="새 프로젝트" />
|
||||
<ProjectCreateForm
|
||||
onSubmit={(data: ProjectCreateFormValues) => {
|
||||
const formattedData = {
|
||||
const formattedData: ProjectRequest = {
|
||||
title: data.projectName,
|
||||
labelType: formatLabelType(data.labelType),
|
||||
projectType: formatLabelType(data.labelType),
|
||||
};
|
||||
onSubmit(formattedData);
|
||||
handleClose();
|
||||
|
@ -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<CustomError>) => {
|
||||
// console.error('워크스페이스 생성 실패:', error.message);
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
createWorkspace.mutate({
|
||||
memberId,
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <p>Loading workspaces...</p>;
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
return <p>Error loading workspaces. Please try again later.</p>;
|
||||
}
|
||||
const workspaces = workspacesResponse?.workspaceResponses ?? [];
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -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 (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<Smile
|
||||
size={48}
|
||||
className="mb-2 text-gray-300"
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col gap-8 px-6 py-4">
|
||||
<HeaderSection
|
||||
workspaceName={workspaceData?.title ?? `Workspace-${workspaceId}`}
|
||||
onCreateProject={handleCreateProject}
|
||||
/>
|
||||
{isNaN(workspaceId) || isError || !workspaceId ? (
|
||||
<EmptyStateMessage workspaceId={workspaceId} />
|
||||
) : (
|
||||
<ProjectList
|
||||
projects={projects}
|
||||
workspaceId={workspaceId}
|
||||
navigate={navigate}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function HeaderSection({
|
||||
workspaceName,
|
||||
onCreateProject,
|
||||
}: {
|
||||
workspaceName: string;
|
||||
onCreateProject: (data: ProjectRequest) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<h1 className="small-title flex grow">{workspaceName}</h1>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex gap-3">
|
||||
<ProjectCreateModal
|
||||
buttonClass="mt-4 flex items-center gap-2"
|
||||
onSubmit={onCreateProject}
|
||||
/>
|
||||
<div className="body text-gray-400">작업할 워크스페이스를 선택하세요</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isError || !workspaceId) {
|
||||
function EmptyStateMessage({ workspaceId }: { workspaceId: number }) {
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<Smile
|
||||
size={48}
|
||||
className="mb-2 text-gray-300"
|
||||
/>
|
||||
<div className="body text-gray-400">
|
||||
{!workspaceId ? '작업할 워크스페이스를 선택하세요.' : '작업할 프로젝트가 없습니다.'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ProjectList({
|
||||
projects,
|
||||
workspaceId,
|
||||
navigate,
|
||||
}: {
|
||||
projects: ProjectResponse[];
|
||||
workspaceId: number;
|
||||
navigate: ReturnType<typeof useNavigate>;
|
||||
}) {
|
||||
if (projects.length === 0) {
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<Smile
|
||||
size={48}
|
||||
className="mb-2 text-gray-300"
|
||||
/>
|
||||
<div className="body text-gray-400">
|
||||
{!workspaceId ? '작업할 워크스페이스를 선택하세요.' : '작업할 프로젝트가 없습니다.'}
|
||||
</div>
|
||||
</div>
|
||||
<Smile
|
||||
size={48}
|
||||
className="mb-2 text-gray-300"
|
||||
/>
|
||||
<div className="body text-gray-400">작업할 프로젝트가 없습니다.</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col gap-8 px-6 py-4">
|
||||
<div className="flex items-center justify-center">
|
||||
<h1 className="small-title flex grow">{`Workspace-${workspaceId}`}</h1>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex gap-3">
|
||||
<ProjectCreateModal
|
||||
buttonClass="mt-4 flex items-center gap-2"
|
||||
onSubmit={handleCreateProject}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{projects.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-6">
|
||||
{projects.map((project: ProjectResponse) => (
|
||||
<ProjectCard
|
||||
key={project.id}
|
||||
title={project.title}
|
||||
description={project.projectType}
|
||||
onClick={() => {
|
||||
navigate(`${webPath.workspace()}/${workspaceId}/project/${project.id}`);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<Smile
|
||||
size={48}
|
||||
className="mb-2 text-gray-300"
|
||||
/>
|
||||
<div className="body text-gray-400">작업할 프로젝트가 없습니다.</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-wrap gap-6">
|
||||
{projects.map((project: ProjectResponse) => (
|
||||
<ProjectCard
|
||||
key={project.id}
|
||||
title={project.title}
|
||||
description={project.projectType}
|
||||
onClick={() => {
|
||||
navigate(`${webPath.workspace()}/${workspaceId}/project/${project.id}`);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user