Feat: 이미지 업로드 시 진행도 표시 추가
This commit is contained in:
parent
04e30230c6
commit
c945f0029d
@ -31,7 +31,13 @@ export async function changeImageStatus(
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function uploadImageFile(memberId: number, projectId: number, folderId: number, files: File[]) {
|
||||
export async function uploadImageFile(
|
||||
memberId: number,
|
||||
projectId: number,
|
||||
folderId: number,
|
||||
files: File[],
|
||||
processCallback: (progress: number) => void
|
||||
) {
|
||||
const formData = new FormData();
|
||||
files.forEach((file) => {
|
||||
formData.append('imageList', file);
|
||||
@ -40,30 +46,60 @@ export async function uploadImageFile(memberId: number, projectId: number, folde
|
||||
return api
|
||||
.post(`/projects/${projectId}/folders/${folderId}/images/file`, formData, {
|
||||
params: { memberId },
|
||||
onUploadProgress: (progressEvent) => {
|
||||
if (progressEvent.total) {
|
||||
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
processCallback(progress);
|
||||
}
|
||||
},
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function uploadImageFolder(memberId: number, projectId: number, files: File[]) {
|
||||
export async function uploadImageFolder(
|
||||
memberId: number,
|
||||
projectId: number,
|
||||
folderId: number,
|
||||
files: File[],
|
||||
processCallback: (progress: number) => void
|
||||
) {
|
||||
const formData = new FormData();
|
||||
files.forEach((file) => {
|
||||
formData.append('imageList', file);
|
||||
});
|
||||
|
||||
return api
|
||||
.post(`/projects/${projectId}/folders/${0}/images/file`, formData, {
|
||||
.post(`/projects/${projectId}/folders/${folderId}/images/file`, formData, {
|
||||
params: { memberId },
|
||||
onUploadProgress: (progressEvent) => {
|
||||
if (progressEvent.total) {
|
||||
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
processCallback(progress);
|
||||
}
|
||||
},
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function uploadImageZip(memberId: number, projectId: number, file: File) {
|
||||
export async function uploadImageZip(
|
||||
memberId: number,
|
||||
projectId: number,
|
||||
folderId: number,
|
||||
file: File,
|
||||
processCallback: (progress: number) => void
|
||||
) {
|
||||
const formData = new FormData();
|
||||
formData.append('folderZip', file);
|
||||
|
||||
return api
|
||||
.post(`/projects/${projectId}/folders/${0}/images/zip`, formData, {
|
||||
.post(`/projects/${projectId}/folders/${folderId}/images/zip`, formData, {
|
||||
params: { memberId },
|
||||
onUploadProgress: (progressEvent) => {
|
||||
if (progressEvent.total) {
|
||||
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
processCallback(progress);
|
||||
}
|
||||
},
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ export default function ImageUploadFileForm({
|
||||
const [isUploading, setIsUploading] = useState<boolean>(false);
|
||||
const [isUploaded, setIsUploaded] = useState<boolean>(false);
|
||||
const [isFailed, setIsFailed] = useState<boolean>(false);
|
||||
const [progress, setProgress] = useState<number>(0);
|
||||
|
||||
const uploadImageFile = useUploadImageFileQuery();
|
||||
|
||||
@ -71,6 +72,9 @@ export default function ImageUploadFileForm({
|
||||
projectId,
|
||||
folderId,
|
||||
files,
|
||||
progressCallback: (progress: number) => {
|
||||
setProgress(progress);
|
||||
},
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
@ -115,11 +119,11 @@ export default function ImageUploadFileForm({
|
||||
</div>
|
||||
)}
|
||||
{files.length > 0 && (
|
||||
<ul className="m-0 max-h-[200px] list-none overflow-y-auto p-0">
|
||||
<ul className="m-0 max-h-[260px] list-none overflow-y-auto p-0">
|
||||
{files.map((file, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={cn('flex items-center justify-between p-1')}
|
||||
className="flex items-center justify-between p-1"
|
||||
>
|
||||
<span className="truncate">{file.webkitRelativePath || file.name}</span>
|
||||
{isUploading ? (
|
||||
@ -127,19 +131,19 @@ export default function ImageUploadFileForm({
|
||||
{isUploaded ? (
|
||||
<CircleCheckBig
|
||||
className="stroke-green-500"
|
||||
size={20}
|
||||
size={16}
|
||||
strokeWidth="2"
|
||||
/>
|
||||
) : isFailed ? (
|
||||
<CircleX
|
||||
className="stroke-red-500"
|
||||
size={20}
|
||||
size={16}
|
||||
strokeWidth="2"
|
||||
/>
|
||||
) : (
|
||||
<CircleDashed
|
||||
className="stroke-gray-500"
|
||||
size={20}
|
||||
size={16}
|
||||
strokeWidth="2"
|
||||
/>
|
||||
)}
|
||||
@ -171,7 +175,7 @@ export default function ImageUploadFileForm({
|
||||
}
|
||||
disabled={!isUploaded && !isFailed}
|
||||
>
|
||||
{isFailed ? '업로드 실패 (닫기)' : isUploaded ? '업로드 완료 (닫기)' : '업로드 중...'}
|
||||
{isFailed ? '업로드 실패 (닫기)' : isUploaded ? '업로드 완료 (닫기)' : `업로드 중... ${progress}%`}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
|
@ -5,7 +5,15 @@ import useAuthStore from '@/stores/useAuthStore';
|
||||
import { CircleCheckBig, CircleDashed, CircleX, X } from 'lucide-react';
|
||||
import useUploadImageFolderQuery from '@/queries/projects/useUploadImageFolderQuery';
|
||||
|
||||
export default function ImageUploadFolderForm({ onClose, projectId }: { onClose: () => void; projectId: number }) {
|
||||
export default function ImageUploadFolderForm({
|
||||
onClose,
|
||||
projectId,
|
||||
folderId,
|
||||
}: {
|
||||
onClose: () => void;
|
||||
projectId: number;
|
||||
folderId: number;
|
||||
}) {
|
||||
const profile = useAuthStore((state) => state.profile);
|
||||
const memberId = profile?.id || 0;
|
||||
|
||||
@ -14,6 +22,7 @@ export default function ImageUploadFolderForm({ onClose, projectId }: { onClose:
|
||||
const [isUploading, setIsUploading] = useState<boolean>(false);
|
||||
const [isUploaded, setIsUploaded] = useState<boolean>(false);
|
||||
const [isFailed, setIsFailed] = useState<boolean>(false);
|
||||
const [progress, setProgress] = useState<number>(0);
|
||||
|
||||
const uploadImageFolder = useUploadImageFolderQuery();
|
||||
|
||||
@ -56,7 +65,11 @@ export default function ImageUploadFolderForm({ onClose, projectId }: { onClose:
|
||||
{
|
||||
memberId,
|
||||
projectId,
|
||||
folderId,
|
||||
files,
|
||||
progressCallback: (progress: number) => {
|
||||
setProgress(progress);
|
||||
},
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
@ -156,7 +169,7 @@ export default function ImageUploadFolderForm({ onClose, projectId }: { onClose:
|
||||
}
|
||||
disabled={!isUploaded && !isFailed}
|
||||
>
|
||||
{isFailed ? '업로드 실패 (닫기)' : isUploaded ? '업로드 완료 (닫기)' : '업로드 중...'}
|
||||
{isFailed ? '업로드 실패 (닫기)' : isUploaded ? '업로드 완료 (닫기)' : `업로드 중... ${progress}%`}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
|
@ -3,7 +3,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../ui/dialog
|
||||
import { Plus } from 'lucide-react';
|
||||
import ImageUploadFolderForm from './ImageUploadFolderForm';
|
||||
|
||||
export default function ImageUploadFolderModal({ projectId }: { projectId: number }) {
|
||||
export default function ImageUploadFolderModal({ projectId, folderId }: { projectId: number; folderId: number }) {
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
|
||||
const handleOpen = () => setIsOpen(true);
|
||||
@ -27,6 +27,7 @@ export default function ImageUploadFolderModal({ projectId }: { projectId: numbe
|
||||
<ImageUploadFolderForm
|
||||
onClose={handleClose}
|
||||
projectId={projectId}
|
||||
folderId={folderId}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
@ -5,7 +5,15 @@ import useAuthStore from '@/stores/useAuthStore';
|
||||
import { CircleCheckBig, CircleDashed, CircleX, X } from 'lucide-react';
|
||||
import useUploadImageZipQuery from '@/queries/projects/useUploadImageZipQuery';
|
||||
|
||||
export default function ImageUploadZipForm({ onClose, projectId }: { onClose: () => void; projectId: number }) {
|
||||
export default function ImageUploadZipForm({
|
||||
onClose,
|
||||
projectId,
|
||||
folderId,
|
||||
}: {
|
||||
onClose: () => void;
|
||||
projectId: number;
|
||||
folderId: number;
|
||||
}) {
|
||||
const profile = useAuthStore((state) => state.profile);
|
||||
const memberId = profile?.id || 0;
|
||||
|
||||
@ -14,6 +22,7 @@ export default function ImageUploadZipForm({ onClose, projectId }: { onClose: ()
|
||||
const [isUploading, setIsUploading] = useState<boolean>(false);
|
||||
const [isUploaded, setIsUploaded] = useState<boolean>(false);
|
||||
const [isFailed, setIsFailed] = useState<boolean>(false);
|
||||
const [progress, setProgress] = useState<number>(0);
|
||||
|
||||
const uploadImageZip = useUploadImageZipQuery();
|
||||
|
||||
@ -57,7 +66,11 @@ export default function ImageUploadZipForm({ onClose, projectId }: { onClose: ()
|
||||
{
|
||||
memberId,
|
||||
projectId,
|
||||
folderId,
|
||||
file,
|
||||
progressCallback: (progress: number) => {
|
||||
setProgress(progress);
|
||||
},
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
@ -152,7 +165,7 @@ export default function ImageUploadZipForm({ onClose, projectId }: { onClose: ()
|
||||
}
|
||||
disabled={!isUploaded && !isFailed}
|
||||
>
|
||||
{isFailed ? '업로드 실패 (닫기)' : isUploaded ? '업로드 완료 (닫기)' : '업로드 중...'}
|
||||
{isFailed ? '업로드 실패 (닫기)' : isUploaded ? '업로드 완료 (닫기)' : `업로드 중... ${progress}%`}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
|
@ -3,7 +3,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../ui/dialog
|
||||
import { Plus } from 'lucide-react';
|
||||
import ImageUploadZipForm from './ImageUploadZipForm';
|
||||
|
||||
export default function ImageUploadZipModal({ projectId }: { projectId: number }) {
|
||||
export default function ImageUploadZipModal({ projectId, folderId }: { projectId: number; folderId: number }) {
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
|
||||
const handleOpen = () => setIsOpen(true);
|
||||
@ -27,6 +27,7 @@ export default function ImageUploadZipModal({ projectId }: { projectId: number }
|
||||
<ImageUploadZipForm
|
||||
onClose={handleClose}
|
||||
projectId={projectId}
|
||||
folderId={folderId}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
@ -90,6 +90,7 @@ export default function WorkspaceDropdownMenu({
|
||||
<ImageUploadFolderForm
|
||||
onClose={handleCloseUploadFolder}
|
||||
projectId={projectId}
|
||||
folderId={folderId}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@ -104,6 +105,7 @@ export default function WorkspaceDropdownMenu({
|
||||
<ImageUploadZipForm
|
||||
onClose={handleCloseUploadZip}
|
||||
projectId={projectId}
|
||||
folderId={folderId}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
@ -8,11 +8,13 @@ export default function useUploadImageFileQuery() {
|
||||
projectId,
|
||||
folderId,
|
||||
files,
|
||||
progressCallback,
|
||||
}: {
|
||||
memberId: number;
|
||||
projectId: number;
|
||||
folderId: number;
|
||||
files: File[];
|
||||
}) => uploadImageFile(memberId, projectId, folderId, files),
|
||||
progressCallback: (progress: number) => void;
|
||||
}) => uploadImageFile(memberId, projectId, folderId, files, progressCallback),
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,18 @@ import { useMutation } from '@tanstack/react-query';
|
||||
|
||||
export default function useUploadImageFolderQuery() {
|
||||
return useMutation({
|
||||
mutationFn: ({ memberId, projectId, files }: { memberId: number; projectId: number; files: File[] }) =>
|
||||
uploadImageFolder(memberId, projectId, files),
|
||||
mutationFn: ({
|
||||
memberId,
|
||||
projectId,
|
||||
folderId,
|
||||
files,
|
||||
progressCallback,
|
||||
}: {
|
||||
memberId: number;
|
||||
projectId: number;
|
||||
folderId: number;
|
||||
files: File[];
|
||||
progressCallback: (progress: number) => void;
|
||||
}) => uploadImageFolder(memberId, projectId, folderId, files, progressCallback),
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,18 @@ import { useMutation } from '@tanstack/react-query';
|
||||
|
||||
export default function useUploadImageZipQuery() {
|
||||
return useMutation({
|
||||
mutationFn: ({ memberId, projectId, file }: { memberId: number; projectId: number; file: File }) =>
|
||||
uploadImageZip(memberId, projectId, file),
|
||||
mutationFn: ({
|
||||
memberId,
|
||||
projectId,
|
||||
folderId,
|
||||
file,
|
||||
progressCallback,
|
||||
}: {
|
||||
memberId: number;
|
||||
projectId: number;
|
||||
folderId: number;
|
||||
file: File;
|
||||
progressCallback: (progress: number) => void;
|
||||
}) => uploadImageZip(memberId, projectId, folderId, file, progressCallback),
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user