Feat: 워크스페이스 api 연결 - S11P21S002-141

This commit is contained in:
정현조 2024-09-11 13:46:08 +09:00
parent 3267f24e11
commit 81187fb0f2
2 changed files with 115 additions and 101 deletions

View File

@ -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>
)} )}

View File

@ -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>
)) ))
) : ( ) : (