diff --git a/public/index.html b/public/index.html index 35a5fcbc..70a9baed 100644 --- a/public/index.html +++ b/public/index.html @@ -8,6 +8,7 @@ name="description" content="backoffice for koin's store owner" /> + diff --git a/src/page/AddMenu/components/AddMenuImgModal/index.tsx b/src/page/AddMenu/components/AddMenuImgModal/index.tsx index 31b5bb1c..0de66a5d 100644 --- a/src/page/AddMenu/components/AddMenuImgModal/index.tsx +++ b/src/page/AddMenu/components/AddMenuImgModal/index.tsx @@ -2,9 +2,9 @@ import React, { useEffect } from 'react'; import { createPortal } from 'react-dom'; import { ReactComponent as CancelIcon } from 'assets/svg/addmenu/mobile-cancle-icon.svg'; import useAddMenuStore from 'store/addMenu'; -import useImageUpload from 'utils/hooks/useImageUpload'; import ErrorMessage from 'page/Auth/Signup/component/ErrorMessage'; -import { ERRORMESSAGE } from 'page/ShopRegistration/constant/errorMessage'; import styles from './AddMenuImgModal.module.scss'; +import { ERRORMESSAGE } from 'page/ShopRegistration/constant/errorMessage'; import useImagesUpload from 'utils/hooks/useImagesUpload'; +import styles from './AddMenuImgModal.module.scss'; interface AddMenuImgModalProps { isOpen: boolean; @@ -12,10 +12,11 @@ interface AddMenuImgModalProps { } export default function AddMenuImgModal({ isOpen, closeModal }: AddMenuImgModalProps) { - const { setImageUrl } = useAddMenuStore(); + const { setImageUrls } = useAddMenuStore(); + const { imageFile, imgRef, saveImgFile, uploadError, - } = useImageUpload(); + } = useImagesUpload(); const triggerFileInput = () => { imgRef.current?.click(); @@ -28,10 +29,10 @@ export default function AddMenuImgModal({ isOpen, closeModal }: AddMenuImgModalP }; useEffect(() => { if (imageFile && !uploadError) { - setImageUrl(imageFile); + setImageUrls(imageFile); closeModal(); } - }, [imageFile, uploadError, setImageUrl, closeModal]); + }, [imageFile, uploadError, setImageUrls, closeModal]); if (!isOpen) return null; @@ -44,7 +45,7 @@ export default function AddMenuImgModal({ isOpen, closeModal }: AddMenuImgModalP 이미지 추가 메뉴 사진을 추가할 수 있습니다.
- +
diff --git a/src/page/AddMenu/components/MenuImage/index.tsx b/src/page/AddMenu/components/MenuImage/index.tsx index 91a83cf3..b4129da7 100644 --- a/src/page/AddMenu/components/MenuImage/index.tsx +++ b/src/page/AddMenu/components/MenuImage/index.tsx @@ -5,9 +5,9 @@ import useMediaQuery from 'utils/hooks/useMediaQuery'; import useBooleanState from 'utils/hooks/useBooleanState'; import AddMenuImgModal from 'page/AddMenu/components/AddMenuImgModal'; import useAddMenuStore from 'store/addMenu'; -import useImageUpload from 'utils/hooks/useImageUpload'; import ErrorMessage from 'page/Auth/Signup/component/ErrorMessage'; import { ERRORMESSAGE } from 'page/ShopRegistration/constant/errorMessage'; +import useImagesUpload from 'utils/hooks/useImagesUpload'; import styles from './MenuImage.module.scss'; interface MenuImageProps { @@ -16,15 +16,16 @@ interface MenuImageProps { export default function MenuImage({ isComplete }: MenuImageProps) { const { isMobile } = useMediaQuery(); - const { imageUrl, setImageUrl, removeImageUrl } = useAddMenuStore(); + const { imageUrl, setImageUrls, removeImageUrl } = useAddMenuStore(); const { value: isAddMenuImgModal, setTrue: openAddMenuImgModal, setFalse: closeAddMenuImgModal, } = useBooleanState(false); + const { imageFile, imgRef, saveImgFile, uploadError, - } = useImageUpload(); + } = useImagesUpload(); const handleAddImage = () => { imgRef.current?.click(); }; @@ -36,9 +37,9 @@ export default function MenuImage({ isComplete }: MenuImageProps) { }; useEffect(() => { if (imageFile) { - setImageUrl(imageFile); + setImageUrls(imageFile); } - }, [imageFile, setImageUrl]); + }, [imageFile, setImageUrls]); return (
{isMobile ? ( @@ -52,14 +53,14 @@ export default function MenuImage({ isComplete }: MenuImageProps) {
{`Selected {!isComplete && ( - + )}
))} @@ -88,14 +89,14 @@ export default function MenuImage({ isComplete }: MenuImageProps) {
{`Selected {!isComplete && ( - + )}
))} @@ -114,6 +115,7 @@ export default function MenuImage({ isComplete }: MenuImageProps) { style={{ display: 'none' }} onChange={handleImageChange} ref={imgRef} + multiple />
diff --git a/src/store/addMenu.ts b/src/store/addMenu.ts index eefc8e79..f064a97e 100644 --- a/src/store/addMenu.ts +++ b/src/store/addMenu.ts @@ -19,6 +19,7 @@ interface AddMenuStore { setCategoryIds: (categoryIds: number[]) => void; setDescription: (description: string) => void; setImageUrl: (newImageUrl: string) => void; + setImageUrls: (newImageUrls: string[]) => void, removeImageUrl: (imageUrlToRemove: string) => void; setIsSingle: (isSingle: boolean) => void; setName: (name: string) => void; @@ -45,6 +46,9 @@ const useAddMenuStore = create((set) => ({ setImageUrl: (newImageUrl) => set((state) => ({ imageUrl: [...state.imageUrl, newImageUrl], })), + setImageUrls: (newImageUrl) => set((state) => ({ + imageUrl: [...state.imageUrl, ...newImageUrl], + })), removeImageUrl: (imageUrlToRemove) => set((state) => ({ imageUrl: state.imageUrl.filter((img) => img !== imageUrlToRemove), })), diff --git a/src/utils/hooks/useImagesUpload.ts b/src/utils/hooks/useImagesUpload.ts new file mode 100644 index 00000000..bb332c3b --- /dev/null +++ b/src/utils/hooks/useImagesUpload.ts @@ -0,0 +1,75 @@ +import { uploadFile } from 'api/uploadFile/Uploadfile'; +import { useRef, useState } from 'react'; +import showToast from 'utils/ts/showToast'; + +// 정의할 수 있는 에러 타입 +type UploadError = '413' | '415' | '404' | '422' | 'networkError' | '401' | ''; + +const MAXSIZE = 1024 * 1024 * 10; + +/* eslint-disable */ +export default function useImagesUpload() { + const [imageFile, setImageFile] = useState([]); + const [uploadError, setUploadError] = useState(''); + const imgRef = useRef(null); + + const saveImgFile = async () => { + const files = imgRef.current?.files; + + if (files && (files.length > 3 || imageFile.length >= 3)) { + showToast('error', '파일은 3개까지 등록할 수 있습니다.') + return; + } + + if (files && files.length) { + const uploadedFiles: string[] = []; + const correctForm = new RegExp('(.*?)\\.(jpg|jpeg|gif|bmp|png)$'); + + for (let i = 0; i < files.length; i += 1) { + const file = files[i]; + + if (file.size > MAXSIZE) { + setUploadError('413'); // 파일 사이즈가 너무 큰 경우 + return; + } + + if (!correctForm.test(file.name)) { + setUploadError('415'); // 지원하지 않는 타입 에러 + return; + } + + const formData = new FormData(); + formData.append('multipartFile', file); + + try { + const data = await uploadFile(formData); + if (data?.data?.file_url) { + uploadedFiles.push(data.data.file_url); + } + } catch (error: any) { + setImageFile([]); + const errorMessage = error.toString(); + if (errorMessage.includes('415')) { + setUploadError('415'); + } else if (errorMessage.includes('404')) { + setUploadError('404'); + } else if (errorMessage.includes('422')) { + setUploadError('422'); + } else if (errorMessage.includes('Network Error')) { + setUploadError('networkError'); + } else { + setUploadError('401'); + } + return; + } + } + + setImageFile(uploadedFiles); + setUploadError(''); + } + }; + + return { + imageFile, imgRef, saveImgFile, uploadError, + }; +}