diff --git a/fe/src/components/common/menuItemEditor/ImageBox.tsx b/fe/src/components/common/menuItemEditor/ImageBox.tsx index f613f23e..0ab42074 100644 --- a/fe/src/components/common/menuItemEditor/ImageBox.tsx +++ b/fe/src/components/common/menuItemEditor/ImageBox.tsx @@ -8,165 +8,151 @@ import { PlusGhostIcon } from '../icon/icons'; import { Spinner } from '../loading/spinner'; type Props = { - menuId: string; - imageUrl?: string; - onEditMenuImage(id: string, image: ImageType): void; + menuId: string; + imageUrl?: string; + onEditMenuImage(id: string, image: ImageType): void; }; export const ImageBox: React.FC = ({ - menuId, - imageUrl, - onEditMenuImage, + menuId, + imageUrl, + onEditMenuImage, }) => { - const toast = useToast(); - const { mutate: imageMutate, isLoading } = usePostImage('feed'); + const toast = useToast(); + const { mutate: imageMutate, isLoading } = usePostImage('feed'); - const inputRef = useRef(null); - const imageRef = useRef(null); // img 태그 ref 추가 + const inputRef = useRef(null); - const [imageData, setImageData] = useState({ - id: '', - url: imageUrl, - originalUrl: '', // 원본 이미지 URL 저장 - }); + const [imageData, setImageData] = useState({ + id: '', + url: imageUrl, + }); - const handleImageClick = () => { - if (isLoading) return; + const handleImageClick = () => { + if (isLoading) return; + + if (inputRef.current) { + inputRef.current.click(); + } + }; + + const handleUploadImage = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + + if (!file) { + return; + } + + const ALLOWED_TYPES = ['image/png', 'image/jpg', 'image/jpeg']; + const MAX_FILE_SIZE_BYTES = 1024 * 1024 * 2.6; // 2MB + + if (!ALLOWED_TYPES.includes(file.type) || file.size > MAX_FILE_SIZE_BYTES) { + toast.noti( + '이미지는 2.6MB 이하의 png, jpg, jpeg 파일만 업로드 가능합니z다.' + ); + return; + } + + const resizedFile = (await resizeImage({ + file, + maxWidth: 850, + maxHeight: 850, + })) as File; + console.log('resizedFile', resizedFile); + + const formData = new FormData(); + formData.append('file', resizedFile); + // formData.append('file', file); + + imageMutate(formData, { + onSuccess: (res) => { + console.log(res, ' now res'); + setImageData(res); + onEditMenuImage(menuId, res); + }, + }); + + if (inputRef.current) { + inputRef.current.value = ''; + } + }; + + return ( + + + + menu item image + + {isLoading && ( + + + + )} + {!isLoading && } + + ); +}; - if (inputRef.current) { - inputRef.current.click(); +const ImageWrapper = styled.div<{ $isImageUrl: boolean }>` + width: 95px; + height: 95px; + position: relative; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 95px; + height: 95px; + background-color: rgba(0, 0, 0, 0.3); + pointer-events: none; + cursor: pointer; } - }; - const handleUploadImage = async (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - - if (!file) { - return; + input[type='file'] { + display: none; + &::file-selector-button { + display: none; + } } - const ALLOWED_TYPES = ['image/png', 'image/jpg', 'image/jpeg']; - const MAX_FILE_SIZE_BYTES = 1024 * 1024 * 2.6; // 2MB - - if (!ALLOWED_TYPES.includes(file.type) || file.size > MAX_FILE_SIZE_BYTES) { - toast.noti( - '이미지는 2.6MB 이하의 png, jpg, jpeg 파일만 업로드 가능합니다.' - ); - return; + svg { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 10; } +`; - const resizedFile = (await resizeImage({ - file, - maxWidth: 850, - maxHeight: 850, - })) as File; - console.log('resizedFile', resizedFile); - - const formData = new FormData(); - formData.append('file', resizedFile); - // formData.append('file', file); // 원본 이미지 업로드 시 - - imageMutate(formData, { - onSuccess: (res) => { - console.log(res, ' now res'); - // originalUrl 저장 (res에 원본 url이 있다고 가정) - // 만약 원본 이미지를 업로드하는 경우, res.url을 resizedFile의 url로 변경 - setImageData({ ...res, originalUrl: res.url }); - onEditMenuImage(menuId, res); - }, - }); +const ImageContainer = styled.div` + width: 100%; + height: 100%; + transition: transform 0.2s ease-in-out; - if (inputRef.current) { - inputRef.current.value = ''; + &:hover { + transform: scale(1.1); } - }; - - return ( - { - if (imageRef.current && imageData.originalUrl) { - imageRef.current.src = imageData.originalUrl; - imageRef.current.style.transform = 'scale(1.5)'; - } - }} - onMouseLeave={() => { - if (imageRef.current) { - imageRef.current.src = - imageData.url || generateDefaultUserImage(menuId); - imageRef.current.style.transform = 'scale(1)'; - } - }} - > - - menu item image - {isLoading && ( - - - - )} - {!isLoading && } - - ); -}; -const ImageWrapper = styled.div<{ $isImageUrl: boolean }>` - width: 95px; - height: 95px; - position: relative; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - - &::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 95px; - height: 95px; - background-color: rgba(0, 0, 0, 0.3); - pointer-events: none; - cursor: pointer; - } - - input[type='file'] { - display: none; - &::file-selector-button { - display: none; + img { + width: 100%; + height: 100%; + object-fit: cover; } - } - - img { - width: 95px; - height: 95px; - object-fit: cover; - transition: transform 0.3s ease; - z-index: 1; - } - - &:hover img { - z-index: 10; - } - - svg { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 10; - } `; const SpinnerContainer = styled.div`