-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
대표이미지 수정버그, 아이템 이미지 등록삭제시 생기는 버그 수정 (#715)
* refactor:여러이미지업로드 로직 함수분리, 변수명변경 * fix: 대표사진 업로드 버그 수정(맥시멈 사진갯수지정) * fix: 배열 멱등성 지켜서 버그 방지 * refactor:이미지url 변수명 변경 * refactor: 모바일 모달창 문구보이게 margin추가
- Loading branch information
Showing
15 changed files
with
123 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,130 +1,141 @@ | ||
import type { ChangeEvent } from 'react'; | ||
import { useCallback, useState } from 'react'; | ||
import { useCallback, useEffect, useState } from 'react'; | ||
|
||
import imageCompression from 'browser-image-compression'; | ||
|
||
import { useImageMutation } from '@hooks/api/useImageMutation'; | ||
import { useToast } from '@hooks/common/useToast'; | ||
|
||
import convertImageNames from '@utils/convertImageNames'; | ||
import { convertToImageNames, convertToImageUrls } from '@utils/convertImage'; | ||
|
||
import { IMAGE_COMPRESSION_OPTIONS } from '@constants/image'; | ||
import { TRIP_ITEM_ADD_MAX_IMAGE_UPLOAD_COUNT } from '@constants/ui'; | ||
|
||
interface UseMultipleImageUploadParams { | ||
initialImageNames: string[]; | ||
maxUploadCount?: number; | ||
handleInitialImage?: (images: string[]) => void; | ||
onSuccess?: CallableFunction; | ||
updateFormImage?: CallableFunction; | ||
onError?: CallableFunction; | ||
} | ||
|
||
export const useMultipleImageUpload = ({ | ||
initialImageNames, | ||
maxUploadCount = TRIP_ITEM_ADD_MAX_IMAGE_UPLOAD_COUNT, | ||
onSuccess, | ||
updateFormImage, | ||
onError, | ||
}: UseMultipleImageUploadParams) => { | ||
const imageMutation = useImageMutation(); | ||
const isImageUploading = imageMutation.isLoading; | ||
|
||
const convertedImageNames = convertImageNames(initialImageNames); | ||
const initialImageUrls = convertToImageUrls([...initialImageNames]); | ||
|
||
const { createToast } = useToast(); | ||
const [uploadedImageNames, setUploadedImageNames] = useState(convertedImageNames); | ||
const [imageUrls, setImageUrls] = useState(initialImageUrls); | ||
const [imageNames, setImageNames] = useState(initialImageNames); | ||
|
||
const handleImageUpload = useCallback( | ||
async (event: ChangeEvent<HTMLInputElement>) => { | ||
const originalImageFiles = event.target.files; | ||
|
||
if (!originalImageFiles) return; | ||
useEffect(() => { | ||
updateFormImage?.(imageNames); | ||
}, [imageNames, updateFormImage]); | ||
|
||
if (originalImageFiles.length + uploadedImageNames.length > maxUploadCount) { | ||
onError?.(); | ||
const compressImages = useCallback(async (originalImageFiles: FileList): Promise<File[]> => { | ||
const imageFiles: File[] = []; | ||
|
||
return; | ||
} | ||
try { | ||
await Promise.all( | ||
[...originalImageFiles].map(async (file) => { | ||
const compressedImageFile = await imageCompression(file, IMAGE_COMPRESSION_OPTIONS); | ||
|
||
const prevImageNames = uploadedImageNames; | ||
const fileName = file.name; | ||
const fileType = compressedImageFile.type; | ||
const convertedFile = new File([compressedImageFile], fileName, { type: fileType }); | ||
|
||
setUploadedImageNames((prevImageNames) => { | ||
const newImageNames = [...originalImageFiles].map((file) => URL.createObjectURL(file)); | ||
|
||
return [...prevImageNames, ...newImageNames]; | ||
}); | ||
|
||
const imageFiles: File[] = []; | ||
|
||
try { | ||
await Promise.all( | ||
[...originalImageFiles].map(async (file) => { | ||
const compressedImageFile = await imageCompression(file, IMAGE_COMPRESSION_OPTIONS); | ||
|
||
const fileName = file.name; | ||
const fileType = compressedImageFile.type; | ||
const convertedFile = new File([compressedImageFile], fileName, { type: fileType }); | ||
imageFiles.push(convertedFile); | ||
}) | ||
); | ||
} catch (e) { | ||
imageFiles.push(...originalImageFiles); | ||
} | ||
|
||
imageFiles.push(convertedFile); | ||
}) | ||
); | ||
} catch (e) { | ||
imageFiles.push(...originalImageFiles); | ||
} | ||
return imageFiles; | ||
}, []); | ||
|
||
const imageUploadFormData = new FormData(); | ||
const convertToImageFormData = useCallback( | ||
async (imageFiles: FileList) => { | ||
const compressedImages = await compressImages(imageFiles); | ||
const imageFormData = new FormData(); | ||
|
||
[...imageFiles].forEach((file) => { | ||
imageUploadFormData.append('images', file); | ||
compressedImages.forEach((file) => { | ||
imageFormData.append('images', file); | ||
}); | ||
|
||
return imageFormData; | ||
}, | ||
[compressImages] | ||
); | ||
|
||
const postImageNames = useCallback( | ||
async (images: FormData) => { | ||
imageMutation.mutate( | ||
{ images: imageUploadFormData }, | ||
{ images }, | ||
{ | ||
onSuccess: ({ imageNames }) => { | ||
if (maxUploadCount === 1) { | ||
onSuccess?.([...imageNames]); | ||
createToast('이미지 업로드에 성공했습니다', 'success'); | ||
setImageNames([...imageNames]); | ||
|
||
return; | ||
} | ||
|
||
onSuccess?.([...convertedImageNames, ...imageNames]); | ||
createToast('이미지 업로드에 성공했습니다', 'success'); | ||
setImageNames((prev) => [...prev, ...imageNames]); | ||
}, | ||
onError: () => { | ||
setUploadedImageNames(prevImageNames); | ||
setImageUrls(initialImageUrls); | ||
}, | ||
} | ||
); | ||
}, | ||
[imageMutation, maxUploadCount, initialImageUrls] | ||
); | ||
|
||
const handleImageUpload = useCallback( | ||
async (event: ChangeEvent<HTMLInputElement>) => { | ||
const originalImageFiles = event.target.files; | ||
|
||
if (!originalImageFiles) return; | ||
|
||
if (originalImageFiles.length + imageUrls.length > maxUploadCount) { | ||
onError?.(); | ||
|
||
return; | ||
} | ||
|
||
// 화면에 보여지는 이미지 url로 변경 + 업데이트 | ||
setImageUrls((prevImageUrls) => { | ||
const newImageUrls = [...originalImageFiles].map((file) => URL.createObjectURL(file)); | ||
|
||
return [...prevImageUrls, ...newImageUrls]; | ||
}); | ||
|
||
const imageFormData = await convertToImageFormData(originalImageFiles); | ||
postImageNames(imageFormData); | ||
|
||
// eslint-disable-next-line no-param-reassign | ||
event.target.value = ''; | ||
}, | ||
[ | ||
createToast, | ||
imageMutation, | ||
convertedImageNames, | ||
maxUploadCount, | ||
onError, | ||
onSuccess, | ||
uploadedImageNames, | ||
] | ||
[imageUrls, maxUploadCount, convertToImageFormData, postImageNames, onError] | ||
); | ||
|
||
const handleImageRemoval = useCallback( | ||
(selectedImageName: string) => () => { | ||
setUploadedImageNames((prevImageNames) => { | ||
const updatedImageNames = prevImageNames.filter( | ||
(imageName) => imageName !== selectedImageName | ||
); | ||
|
||
onSuccess?.(updatedImageNames); | ||
|
||
return updatedImageNames; | ||
(selectedImageUrl: string) => () => { | ||
setImageUrls((prevImageUrls) => { | ||
const updatedImageUrls = prevImageUrls.filter((imageUrl) => imageUrl !== selectedImageUrl); | ||
// form에 들어가는 imageName 변경 | ||
const imageNames = convertToImageNames(updatedImageUrls); | ||
updateFormImage?.(imageNames); | ||
|
||
// 화면에 보여지는 imageUrl 변경 | ||
return updatedImageUrls; | ||
}); | ||
}, | ||
[onSuccess] | ||
[updateFormImage] | ||
); | ||
|
||
return { isImageUploading, uploadedImageNames, handleImageUpload, handleImageRemoval }; | ||
return { isImageUploading, imageUrls, handleImageUpload, handleImageRemoval }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,7 +107,6 @@ export const useAddTripItemForm = ({ | |
|
||
return; | ||
} | ||
|
||
if (!itemId) { | ||
addTripItemMutation.mutate( | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
export const images = [ | ||
'https://upload.wikimedia.org/wikipedia/commons/f/f9/Open_Happiness_Piccadilly_Circus_Blue-Pink_Hour_120917-1126-jikatu.jpg', | ||
'https://e3.365dm.com/17/10/2048x1152/skynews-piccadilly-piccadilly-circus_4131587.jpg', | ||
'https://dynamic-media-cdn.tripadvisor.com/media/photo-o/15/9e/a5/6f/regent-str.jpg?w=1200&h=-1&s=1', | ||
'https://flashbak.com/wp-content/uploads/2017/01/Piccadilly-by-Night-London-1960-by-Elmar-Ludwig.jpg', | ||
'Open_Happiness_Piccadilly_Circus_Blue-Pink_Hour_120917-1126-jikatu.jpg', | ||
'regent-str.jpg', | ||
'Piccadilly-by-Night-London-1960-by-Elmar-Ludwig.jpg', | ||
]; |
Oops, something went wrong.