Feat: 워크스페이스 api 연결 - S11P21S002-141
This commit is contained in:
parent
3267f24e11
commit
81187fb0f2
@ -1,71 +1,84 @@
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import ProjectCard from '@/components/ProjectCard';
|
import ProjectCard from '@/components/ProjectCard';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Smile } from 'lucide-react';
|
||||||
import { Workspace } from '@/types';
|
import ProjectCreateModal from '../ProjectCreateModal';
|
||||||
import { Plus, Smile } from 'lucide-react';
|
import { useGetAllProjects, useCreateProject } from '@/hooks/useProjectHooks';
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../ui/dialogCustom';
|
import useAuthStore from '@/stores/useAuthStore';
|
||||||
import WorkSpaceCreateForm from '../WorkSpaceCreateModal/WorkSpaceCreateForm';
|
import { Key } from 'react';
|
||||||
|
|
||||||
export default function WorkspaceBrowseDetail() {
|
export default function WorkspaceBrowseDetail() {
|
||||||
const { workspaceId } = useParams<{ workspaceId: string }>();
|
const { workspaceId } = useParams<{ workspaceId: string }>();
|
||||||
const numericWorkspaceId: number = Number(workspaceId);
|
const numericWorkspaceId = Number(workspaceId);
|
||||||
const workspace: Workspace = !workspaceId
|
const { profile } = useAuthStore();
|
||||||
? {
|
const memberId = profile.id ?? 0;
|
||||||
id: 0,
|
|
||||||
name: '',
|
const { data: projectsResponse, isLoading, isError, refetch } = useGetAllProjects(numericWorkspaceId || 0, memberId);
|
||||||
projects: [],
|
const createProject = useCreateProject();
|
||||||
|
|
||||||
|
const handleCreateProject = (data: { title: string; labelType: 'Classification' | 'Detection' | 'Segmentation' }) => {
|
||||||
|
createProject.mutate(
|
||||||
|
{
|
||||||
|
workspaceId: numericWorkspaceId,
|
||||||
|
memberId,
|
||||||
|
data: { title: data.title, projectType: data.labelType.toLowerCase() },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
console.log('프로젝트가 성공적으로 생성되었습니다.');
|
||||||
|
refetch();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.error('프로젝트 생성 실패:', error);
|
||||||
|
console.log('Error details:', JSON.stringify(error, null, 2));
|
||||||
|
|
||||||
|
const errorMessage = error?.response?.data?.message || error.message || '알 수 없는 오류';
|
||||||
|
console.error('프로젝트 생성 실패:', errorMessage);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
: {
|
);
|
||||||
id: numericWorkspaceId,
|
|
||||||
name: `workspace-${workspaceId}`,
|
|
||||||
projects: [
|
|
||||||
{ id: 1, name: 'project1', type: 'Detection', children: [] },
|
|
||||||
{ id: 2, name: 'project2', type: 'Detection', children: [] },
|
|
||||||
{ id: 3, name: 'project3', type: 'Detection', children: [] },
|
|
||||||
{ id: 4, name: 'project4', type: 'Detection', children: [] },
|
|
||||||
{ id: 5, name: 'project5', type: 'Detection', children: [] },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const projects = Array.isArray(projectsResponse?.data?.workspaceResponses)
|
||||||
|
? projectsResponse.data.workspaceResponses
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <p>Loading projects...</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isError || !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"
|
||||||
|
/>
|
||||||
|
<div className="body text-gray-400">
|
||||||
|
{!workspaceId ? '작업할 워크스페이스를 선택하세요.' : '작업할 프로젝트가 없습니다.'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col gap-8 px-6 py-4">
|
<div className="flex h-full w-full flex-col gap-8 px-6 py-4">
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex items-center justify-center">
|
||||||
<h1 className="small-title flex grow">{workspaceId ? workspace.name : ''}</h1>
|
<h1 className="small-title flex grow">{`Workspace-${workspaceId}`}</h1>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<Dialog>
|
<ProjectCreateModal onSubmit={handleCreateProject} />
|
||||||
<DialogTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => {
|
|
||||||
console.log('새 프로젝트 생성 모달');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="body flex items-center gap-2">
|
|
||||||
<Plus size={16} />
|
|
||||||
<span>새 프로젝트</span>
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent>
|
|
||||||
<DialogHeader title="새 워크스페이스" />
|
|
||||||
<WorkSpaceCreateForm
|
|
||||||
onSubmit={(data) => {
|
|
||||||
console.log(data);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{workspaceId ? (
|
{projects.length > 0 ? (
|
||||||
<div className="flex flex-wrap gap-6">
|
<div className="flex flex-wrap gap-6">
|
||||||
{workspace.projects.map((project) => (
|
{projects.map((project: { id: Key | null | undefined; title: string; projectType: string }) => (
|
||||||
<ProjectCard
|
<ProjectCard
|
||||||
key={project.id}
|
key={project.id}
|
||||||
title={project.name}
|
title={project.title}
|
||||||
description={project.type}
|
description={project.projectType}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log('project id : ' + project.id);
|
console.log('project id : ' + project.id);
|
||||||
}}
|
}}
|
||||||
@ -73,13 +86,13 @@ export default function WorkspaceBrowseDetail() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex w-full grow items-center justify-center">
|
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<Smile
|
<Smile
|
||||||
size={48}
|
size={48}
|
||||||
className="mb-2 text-gray-300"
|
className="mb-2 text-gray-300"
|
||||||
/>
|
/>
|
||||||
<div className="body text-gray-400">작업할 워크스페이스를 선택하세요.</div>
|
<div className="body text-gray-400">작업할 프로젝트가 없습니다.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -1,39 +1,54 @@
|
|||||||
import { Suspense } from 'react';
|
import { Suspense, useEffect } from 'react';
|
||||||
import { NavLink, Outlet } from 'react-router-dom';
|
import { NavLink, Outlet, useNavigate } from 'react-router-dom';
|
||||||
import Header from '../Header';
|
import Header from '../Header';
|
||||||
import { Workspace } from '@/types';
|
import { useGetAllWorkspaces, useCreateWorkspace } from '@/hooks/useWorkspaceHooks';
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../ui/dialogCustom';
|
import useAuthStore from '@/stores/useAuthStore';
|
||||||
import { Plus } from 'lucide-react';
|
import WorkSpaceCreateModal from '../WorkSpaceCreateModal';
|
||||||
import WorkSpaceCreateForm from '../WorkSpaceCreateModal/WorkSpaceCreateForm';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
|
||||||
export default function WorkspaceBrowseLayout() {
|
export default function WorkspaceBrowseLayout() {
|
||||||
const workspaces: Workspace[] = [
|
const { profile, isLoggedIn } = useAuthStore();
|
||||||
|
const memberId = profile.id;
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isLoggedIn || !memberId) {
|
||||||
|
console.error('로그인되지 않았거나 유효한 멤버 ID가 없습니다.');
|
||||||
|
navigate('/');
|
||||||
|
}
|
||||||
|
}, [isLoggedIn, memberId, navigate]);
|
||||||
|
|
||||||
|
const { data: workspacesResponse, isLoading, isError } = useGetAllWorkspaces(memberId || 0);
|
||||||
|
|
||||||
|
const workspaces = workspacesResponse?.data?.workspaceResponses || [];
|
||||||
|
|
||||||
|
const createWorkspace = useCreateWorkspace();
|
||||||
|
|
||||||
|
const handleCreateWorkspace = (data: { title: string; content: string }) => {
|
||||||
|
if (!memberId) return;
|
||||||
|
createWorkspace.mutate(
|
||||||
|
{ memberId, data },
|
||||||
{
|
{
|
||||||
id: 1,
|
onSuccess: () => {
|
||||||
name: 'workspace-1',
|
console.log('워크스페이스가 성공적으로 생성되었습니다.');
|
||||||
projects: [],
|
queryClient.invalidateQueries({ queryKey: ['workspaces'] });
|
||||||
},
|
},
|
||||||
{
|
onError: (error: AxiosError) => {
|
||||||
id: 2,
|
console.error('워크스페이스 생성 실패:', error.message);
|
||||||
name: 'workspace-2',
|
|
||||||
projects: [],
|
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
id: 3,
|
);
|
||||||
name: 'workspace-3',
|
};
|
||||||
projects: [],
|
|
||||||
},
|
if (isLoading) {
|
||||||
{
|
return <p>Loading workspaces...</p>;
|
||||||
id: 4,
|
}
|
||||||
name: 'workspace-4',
|
|
||||||
projects: [],
|
if (isError) {
|
||||||
},
|
return <p>Error loading workspaces. Please try again later.</p>;
|
||||||
{
|
}
|
||||||
id: 5,
|
|
||||||
name: 'workspace-5',
|
|
||||||
projects: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -43,21 +58,7 @@ export default function WorkspaceBrowseLayout() {
|
|||||||
<div className="flex w-[280px] flex-col gap-4 border-r border-gray-200 bg-gray-100 px-6 py-4">
|
<div className="flex w-[280px] flex-col gap-4 border-r border-gray-200 bg-gray-100 px-6 py-4">
|
||||||
<div className="flex items-center justify-center gap-5">
|
<div className="flex items-center justify-center gap-5">
|
||||||
<h1 className="heading mr-2.5 w-full">내 워크스페이스</h1>
|
<h1 className="heading mr-2.5 w-full">내 워크스페이스</h1>
|
||||||
<Dialog>
|
<WorkSpaceCreateModal onSubmit={handleCreateWorkspace} />
|
||||||
<DialogTrigger asChild>
|
|
||||||
<button className="p-2">
|
|
||||||
<Plus size={20} />
|
|
||||||
</button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent>
|
|
||||||
<DialogHeader title="새 워크스페이스" />
|
|
||||||
<WorkSpaceCreateForm
|
|
||||||
onSubmit={(data) => {
|
|
||||||
console.log(data);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
</div>
|
||||||
{workspaces.length > 0 ? (
|
{workspaces.length > 0 ? (
|
||||||
workspaces.map((workspace) => (
|
workspaces.map((workspace) => (
|
||||||
@ -66,7 +67,7 @@ export default function WorkspaceBrowseLayout() {
|
|||||||
key={workspace.id}
|
key={workspace.id}
|
||||||
className={({ isActive }) => (isActive ? 'body-strong' : 'body') + ' cursor-pointer'}
|
className={({ isActive }) => (isActive ? 'body-strong' : 'body') + ' cursor-pointer'}
|
||||||
>
|
>
|
||||||
{workspace.name}
|
{workspace.title}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
|
Loading…
Reference in New Issue
Block a user