Merge branch 'fe/refactor/review-detail' into 'fe/develop'

Refactor: 리뷰 요청 zod 조건 추가

See merge request s11-s-project/S11P21S002!268
This commit is contained in:
조현수 2024-10-02 17:58:30 +09:00
commit f11e8d91d6
3 changed files with 22 additions and 63 deletions

View File

@ -18,7 +18,7 @@ const reviewFormSchema = z.object({
projectId: z.string().min(1, '프로젝트를 선택해주세요.'), projectId: z.string().min(1, '프로젝트를 선택해주세요.'),
title: z.string().min(1, '제목을 입력해주세요.'), title: z.string().min(1, '제목을 입력해주세요.'),
content: z.string().min(1, '내용을 입력해주세요.'), content: z.string().min(1, '내용을 입력해주세요.'),
imageIds: z.array(z.number()), imageIds: z.array(z.number()).min(1, '최소 한 개의 이미지를 선택해주세요.'),
}); });
type ReviewFormData = z.infer<typeof reviewFormSchema>; type ReviewFormData = z.infer<typeof reviewFormSchema>;

View File

@ -5,71 +5,37 @@ import { Project } from '@/types';
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from '../ui/select'; import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from '../ui/select';
import useCanvasStore from '@/stores/useCanvasStore'; import useCanvasStore from '@/stores/useCanvasStore';
import { webPath } from '@/router'; import { webPath } from '@/router';
import { useState } from 'react'; import { Suspense, useEffect } from 'react';
import useUploadImageFileQuery from '@/queries/projects/useUploadImageFileQuery';
import useAuthStore from '@/stores/useAuthStore';
export default function WorkspaceSidebar({ workspaceName, projects }: { workspaceName: string; projects: Project[] }) { export default function WorkspaceSidebar({ workspaceName, projects }: { workspaceName: string; projects: Project[] }) {
const { projectId: selectedProjectId } = useParams<{ projectId: string }>(); const { setImage } = useCanvasStore();
const selectedProject = projects.find((project) => project.id.toString() === selectedProjectId); const { projectId: selectedProjectId, workspaceId } = useParams<{ projectId: string; workspaceId: string }>();
const selectedProject = projects.find((project) => project.id.toString() === selectedProjectId) || null;
const setSidebarSize = useCanvasStore((state) => state.setSidebarSize); const setSidebarSize = useCanvasStore((state) => state.setSidebarSize);
const navigate = useNavigate(); const navigate = useNavigate();
const { workspaceId } = useParams<{ workspaceId: string }>();
const [isDragging, setIsDragging] = useState(false);
const uploadImageFileMutation = useUploadImageFileQuery();
const { profile } = useAuthStore();
const handleSelectProject = (projectId: string) => { const handleSelectProject = (projectId: string) => {
navigate(`${webPath.workspace()}/${workspaceId}/project/${projectId}`); setImage(null);
navigate(`${webPath.workspace()}/${workspaceId}/${projectId}`);
}; };
const handleDragOver = (e: React.DragEvent) => { useEffect(() => {
e.preventDefault(); if (!selectedProject) {
setIsDragging(true); setImage(null);
}; }
}, [selectedProject, setImage]);
const handleDragLeave = () => {
setIsDragging(false);
};
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
setIsDragging(false);
if (!selectedProjectId || !profile) return;
const files = Array.from(e.dataTransfer.files);
const memberId = profile.id;
const projectId = parseInt(selectedProjectId);
const folderId = 0;
uploadImageFileMutation.mutate({
memberId,
projectId,
folderId,
files,
progressCallback: (progress) => {
console.log(`업로드 진행률: ${progress}%`);
},
});
};
return ( return (
<> <>
<ResizablePanel <ResizablePanel
minSize={10} minSize={10}
maxSize={35} maxSize={35}
defaultSize={20} defaultSize={15}
className={`flex h-full flex-col bg-gray-50 ${isDragging ? 'bg-blue-100' : ''}`}
onResize={(size) => setSidebarSize(size)} onResize={(size) => setSidebarSize(size)}
onDragOver={(e) => handleDragOver(e as unknown as React.DragEvent<Element>)}
onDragLeave={handleDragLeave}
onDrop={(e) => handleDrop(e as unknown as React.DragEvent<Element>)}
> >
<header className="body flex w-full items-center gap-2 p-2"> <div className="box-border flex h-full flex-col gap-2 bg-gray-50 p-3">
<h1 className="w-full overflow-hidden text-ellipsis whitespace-nowrap">{workspaceName}</h1> <header className="body flex w-full items-center gap-2">
<h1 className="subheading w-full overflow-hidden text-ellipsis whitespace-nowrap">{workspaceName}</h1>
</header> </header>
<div className="p-2">
<Select <Select
onValueChange={handleSelectProject} onValueChange={handleSelectProject}
defaultValue={selectedProjectId} defaultValue={selectedProjectId}
@ -88,8 +54,10 @@ export default function WorkspaceSidebar({ workspaceName, projects }: { workspac
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
</div> <Suspense fallback={<div></div>}>
{selectedProject && <ProjectStructure project={selectedProject} />} {selectedProject && <ProjectStructure project={selectedProject} />}
</Suspense>
</div>
</ResizablePanel> </ResizablePanel>
<ResizableHandle className="bg-gray-300" /> <ResizableHandle className="bg-gray-300" />
</> </>

View File

@ -3,23 +3,14 @@ import * as ResizablePrimitive from 'react-resizable-panels';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
type PanelGroupProps = React.ComponentProps<typeof ResizablePrimitive.PanelGroup>; const ResizablePanelGroup = ({ className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
const ResizablePanelGroup = ({ className, ...props }: PanelGroupProps) => (
<ResizablePrimitive.PanelGroup <ResizablePrimitive.PanelGroup
className={cn('flex h-full w-full data-[panel-group-direction=vertical]:flex-col', className)} className={cn('flex h-full w-full data-[panel-group-direction=vertical]:flex-col', className)}
{...props} {...props}
/> />
); );
type PanelProps = React.ComponentProps<typeof ResizablePrimitive.Panel>; const ResizablePanel = ResizablePrimitive.Panel;
const ResizablePanel = ({ className, ...props }: PanelProps) => (
<ResizablePrimitive.Panel
className={cn('resizable-panel', className)}
{...props}
/>
);
const ResizableHandle = ({ const ResizableHandle = ({
withHandle, withHandle,