Feat: 이미지 폴더 업로드 컴포넌트 구현

This commit is contained in:
홍창기 2024-09-22 03:02:26 +09:00
parent 0557def88e
commit 5fde35a619
No known key found for this signature in database
GPG Key ID: 9FF142041B4A91B9
5 changed files with 136 additions and 50 deletions

View File

@ -51,11 +51,11 @@ export async function uploadImageList(projectId: number, folderId: number, membe
.then(({ data }) => data);
}
export async function uploadImageFolder(projectId: number, folderZip: File[], parentId: number, memberId: number) {
export async function uploadImageFolder(memberId: number, projectId: number, files: File[], parentId: number = 0) {
return api
.post(
`/projects/${projectId}/folders/0/images/upload`,
{ folderZip, parentId },
{ files, parentId },
{
params: { memberId },
}

View File

@ -1,59 +1,16 @@
import { uploadImageFolder, uploadImageList } from '@/api/imageApi';
import useAuthStore from '@/stores/useAuthStore';
import { useState } from 'react';
import { useParams } from 'react-router-dom';
import ImageFolderUploadModal from '../ImageFolderUploadModal';
export default function FolderUploadTest() {
const params = useParams<{ workspaceId: string; projectId: string }>();
const projectId = Number(params.projectId);
const profile = useAuthStore((state) => state.profile);
const memberId = profile?.id || 0;
const [files, setFiles] = useState<Array<File>>([]);
const [isUploading, setIsUploading] = useState<boolean>(false);
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedFiles = e.target.files;
if (selectedFiles) {
setFiles(Array.from(selectedFiles));
}
};
const handleUpload = async () => {
if (!files || files.length === 0) {
console.log('No selected files');
return;
}
setIsUploading(true);
// uploadImageFolder(projectId, files, 0, memberId);
uploadImageList(projectId, 0, memberId, files);
};
return (
<div className="min-h-screen w-full bg-blue-300">
<h1>hello infikei</h1>
<input
type="file"
id="folderInput"
// webkitdirectory=""
multiple
onChange={handleFileChange}
<div className="min-h-screen w-full">
<ImageFolderUploadModal
projectId={projectId}
parentId={0}
/>
<button
onClick={handleUpload}
disabled={isUploading}
>
{isUploading ? '업로드하는 중...' : '폴더 업로드'}
</button>
<div>
{files.length > 0 && (
<ul>
{files.map((file, index) => (
<li key={index}>{file.webkitRelativePath}</li>
))}
</ul>
)}
</div>
</div>
);
}

View File

@ -0,0 +1,88 @@
import { useState } from 'react';
import { Button } from '../ui/button';
import { cn } from '@/lib/utils';
import { uploadImageFolder } from '@/api/imageApi';
import useAuthStore from '@/stores/useAuthStore';
export default function ImageFolderUploadForm({ projectId, parentId }: { projectId: number; parentId: number }) {
const profile = useAuthStore((state) => state.profile);
const memberId = profile?.id || 0;
const [files, setFiles] = useState<File[]>([]);
const [isDragging, setIsDragging] = useState<boolean>(false);
const [isUploading, setIsUploading] = useState<boolean>(false);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const newFiles = event.target.files;
if (newFiles) {
setFiles((prevFiles) => [...prevFiles, ...Array.from(newFiles)]);
}
};
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
setIsDragging(true);
};
const handleDragLeave = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
setIsDragging(false);
};
const handleDrop = () => {
setIsDragging(false);
};
const handleClick = async () => {
setIsUploading(true);
await uploadImageFolder(memberId, projectId, files, parentId);
setFiles([]);
setIsUploading(false);
};
return (
<div className="flex flex-col gap-5">
<div
className={cn(
'relative flex h-[200px] w-full cursor-pointer items-center justify-center rounded-lg border-2 text-center',
isDragging ? 'border-solid border-primary bg-blue-200' : 'border-dashed border-gray-500 bg-gray-100'
)}
>
<input
type="file"
webkitdirectory=""
multiple
className="absolute inset-0 h-full w-full cursor-pointer opacity-0"
onChange={handleChange}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
/>
{isDragging ? (
<p className="text-primary"> </p>
) : (
<p className="text-gray-500">
<br />
</p>
)}
</div>
{files.length > 0 && (
<ul>
{files.map((file, index) => (
<li key={index}>{file.webkitRelativePath}</li>
))}
</ul>
)}
<Button
onClick={handleClick}
variant="outlinePrimary"
disabled={files.length === 0 || isDragging || isUploading}
>
{isUploading ? `업로드 중... 0%` : '업로드'}
</Button>
</div>
);
}

View File

@ -0,0 +1,34 @@
import React from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../ui/dialogCustom';
import { Plus } from 'lucide-react';
import ImageFolderUploadForm from './ImageFolderUploadForm';
export default function WorkSpaceCreateModal({ projectId, parentId = 0 }: { projectId: number; parentId: number }) {
const [isOpen, setIsOpen] = React.useState(false);
const handleOpen = () => setIsOpen(true);
// const handleClose = () => setIsOpen(false);
return (
<Dialog
open={isOpen}
onOpenChange={setIsOpen}
>
<DialogTrigger asChild>
<button
className="flex items-center justify-center p-2"
onClick={handleOpen}
>
<Plus size={20} />
</button>
</DialogTrigger>
<DialogContent className="max-w-2xl">
<DialogHeader title="폴더 업로드" />
<ImageFolderUploadForm
projectId={projectId}
parentId={parentId}
/>
</DialogContent>
</Dialog>
);
}

View File

@ -261,3 +261,10 @@ export interface ErrorResponse {
message: string;
isSuccess: boolean;
}
export interface ImageFolderRequest {
memberId: number;
projectId: number;
parentId: number;
files: File[];
}