Feat: 워크스페이스 api 연결 - S11P21S002-141
This commit is contained in:
parent
3267f24e11
commit
81187fb0f2
@ -1,71 +1,84 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import ProjectCard from '@/components/ProjectCard';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Workspace } from '@/types';
|
||||
import { Plus, Smile } from 'lucide-react';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../ui/dialogCustom';
|
||||
import WorkSpaceCreateForm from '../WorkSpaceCreateModal/WorkSpaceCreateForm';
|
||||
import { Smile } from 'lucide-react';
|
||||
import ProjectCreateModal from '../ProjectCreateModal';
|
||||
import { useGetAllProjects, useCreateProject } from '@/hooks/useProjectHooks';
|
||||
import useAuthStore from '@/stores/useAuthStore';
|
||||
import { Key } from 'react';
|
||||
|
||||
export default function WorkspaceBrowseDetail() {
|
||||
const { workspaceId } = useParams<{ workspaceId: string }>();
|
||||
const numericWorkspaceId: number = Number(workspaceId);
|
||||
const workspace: Workspace = !workspaceId
|
||||
? {
|
||||
id: 0,
|
||||
name: '',
|
||||
projects: [],
|
||||
const numericWorkspaceId = Number(workspaceId);
|
||||
const { profile } = useAuthStore();
|
||||
const memberId = profile.id ?? 0;
|
||||
|
||||
const { data: projectsResponse, isLoading, isError, refetch } = useGetAllProjects(numericWorkspaceId || 0, memberId);
|
||||
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 (
|
||||
<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">{workspaceId ? workspace.name : ''}</h1>
|
||||
<h1 className="small-title flex grow">{`Workspace-${workspaceId}`}</h1>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex gap-3">
|
||||
<Dialog>
|
||||
<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>
|
||||
<ProjectCreateModal onSubmit={handleCreateProject} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{workspaceId ? (
|
||||
{projects.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-6">
|
||||
{workspace.projects.map((project) => (
|
||||
{projects.map((project: { id: Key | null | undefined; title: string; projectType: string }) => (
|
||||
<ProjectCard
|
||||
key={project.id}
|
||||
title={project.name}
|
||||
description={project.type}
|
||||
title={project.title}
|
||||
description={project.projectType}
|
||||
onClick={() => {
|
||||
console.log('project id : ' + project.id);
|
||||
}}
|
||||
@ -73,13 +86,13 @@ export default function WorkspaceBrowseDetail() {
|
||||
))}
|
||||
</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">
|
||||
<Smile
|
||||
size={48}
|
||||
className="mb-2 text-gray-300"
|
||||
/>
|
||||
<div className="body text-gray-400">작업할 워크스페이스를 선택하세요.</div>
|
||||
<div className="body text-gray-400">작업할 프로젝트가 없습니다.</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
@ -1,39 +1,54 @@
|
||||
import { Suspense } from 'react';
|
||||
import { NavLink, Outlet } from 'react-router-dom';
|
||||
import { Suspense, useEffect } from 'react';
|
||||
import { NavLink, Outlet, useNavigate } from 'react-router-dom';
|
||||
import Header from '../Header';
|
||||
import { Workspace } from '@/types';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../ui/dialogCustom';
|
||||
import { Plus } from 'lucide-react';
|
||||
import WorkSpaceCreateForm from '../WorkSpaceCreateModal/WorkSpaceCreateForm';
|
||||
import { useGetAllWorkspaces, useCreateWorkspace } from '@/hooks/useWorkspaceHooks';
|
||||
import useAuthStore from '@/stores/useAuthStore';
|
||||
import WorkSpaceCreateModal from '../WorkSpaceCreateModal';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
export default function WorkspaceBrowseLayout() {
|
||||
const workspaces: Workspace[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'workspace-1',
|
||||
projects: [],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'workspace-2',
|
||||
projects: [],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'workspace-3',
|
||||
projects: [],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'workspace-4',
|
||||
projects: [],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'workspace-5',
|
||||
projects: [],
|
||||
},
|
||||
];
|
||||
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 },
|
||||
{
|
||||
onSuccess: () => {
|
||||
console.log('워크스페이스가 성공적으로 생성되었습니다.');
|
||||
queryClient.invalidateQueries({ queryKey: ['workspaces'] });
|
||||
},
|
||||
onError: (error: AxiosError) => {
|
||||
console.error('워크스페이스 생성 실패:', error.message);
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <p>Loading workspaces...</p>;
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
return <p>Error loading workspaces. Please try again later.</p>;
|
||||
}
|
||||
|
||||
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 items-center justify-center gap-5">
|
||||
<h1 className="heading mr-2.5 w-full">내 워크스페이스</h1>
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<button className="p-2">
|
||||
<Plus size={20} />
|
||||
</button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader title="새 워크스페이스" />
|
||||
<WorkSpaceCreateForm
|
||||
onSubmit={(data) => {
|
||||
console.log(data);
|
||||
}}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<WorkSpaceCreateModal onSubmit={handleCreateWorkspace} />
|
||||
</div>
|
||||
{workspaces.length > 0 ? (
|
||||
workspaces.map((workspace) => (
|
||||
@ -66,7 +67,7 @@ export default function WorkspaceBrowseLayout() {
|
||||
key={workspace.id}
|
||||
className={({ isActive }) => (isActive ? 'body-strong' : 'body') + ' cursor-pointer'}
|
||||
>
|
||||
{workspace.name}
|
||||
{workspace.title}
|
||||
</NavLink>
|
||||
))
|
||||
) : (
|
||||
|
Loading…
Reference in New Issue
Block a user