254 lines
5.5 KiB
JavaScript
254 lines
5.5 KiB
JavaScript
import styled, { css } from 'styled-components';
|
|
import { useEffect, useState } from 'react';
|
|
|
|
import { MenuImageDelete, MenuImageUpload } from '../../apis';
|
|
import { IMAGE_MAX_SIZE } from '../../assets/data/adminConstants';
|
|
import { useAlert } from '../../context/AlertProvider';
|
|
import { alertTypes } from '../../assets/data/types';
|
|
import { ImagePreview } from '../../styles/Components';
|
|
|
|
const ImageUploadBtn = ({ disabled,
|
|
onImageUpload,
|
|
downloadData,
|
|
disabledBtn,
|
|
fileName,
|
|
onFileDelete
|
|
}) => {
|
|
const [previewUrl, setPreviewUrl] = useState(null);
|
|
const token = sessionStorage.getItem('token');
|
|
const { showToast } = useAlert();
|
|
|
|
// 컴포넌트 언마운트 시 미리보기 URL 정리
|
|
useEffect(() => {
|
|
return () => {
|
|
if (previewUrl) {
|
|
URL.revokeObjectURL(previewUrl);
|
|
}
|
|
};
|
|
}, [previewUrl]);
|
|
|
|
const handleFile = async e => {
|
|
const file = e.target.files[0];
|
|
|
|
if (!file) return;
|
|
|
|
// 이미지 파일 확장자 체크
|
|
const fileExt = file.name.split('.').pop().toLowerCase();
|
|
if (fileExt !== 'png' && fileExt !== 'jpg' && fileExt !== 'jpeg') {
|
|
showToast('FILE_IMAGE_EXTENSION_WARNING', {
|
|
type: alertTypes.warning
|
|
});
|
|
if (document.querySelector('#fileinput')) {
|
|
document.querySelector('#fileinput').value = '';
|
|
}
|
|
onFileDelete();
|
|
return;
|
|
}
|
|
|
|
if(file.size > IMAGE_MAX_SIZE){
|
|
showToast('FILE_SIZE_OVER_ERROR', {
|
|
type: alertTypes.warning
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (previewUrl) {
|
|
URL.revokeObjectURL(previewUrl);
|
|
}
|
|
setPreviewUrl(URL.createObjectURL(file));
|
|
|
|
await MenuImageUpload(token, file).then(data =>{
|
|
const message = data.data.message;
|
|
|
|
if (message === 'NOT_EXIT_FILE') {
|
|
showToast('FILE_NOT_EXIT_ERROR', {
|
|
type: alertTypes.error
|
|
});
|
|
|
|
} else {
|
|
onImageUpload(file, data.data.file_name);
|
|
}
|
|
}).catch(error =>{
|
|
console.error('이미지 업로드 오류:', error);
|
|
showToast('FILE_IMAGE_UPLOAD_ERROR', {
|
|
type: alertTypes.error
|
|
});
|
|
});
|
|
};
|
|
|
|
// 파일 삭제
|
|
const handleFileDelete = () => {
|
|
MenuImageDelete(token, fileName).then(data => {
|
|
if(data.result === "ERROR"){
|
|
showToast(data.data.message, {
|
|
type: alertTypes.error
|
|
});
|
|
}else{
|
|
// input 필드 초기화
|
|
if (document.querySelector('#fileinput')) {
|
|
document.querySelector('#fileinput').value = '';
|
|
}
|
|
|
|
if (previewUrl) {
|
|
URL.revokeObjectURL(previewUrl);
|
|
setPreviewUrl(null);
|
|
}
|
|
|
|
onFileDelete();
|
|
}
|
|
}).catch(error => {
|
|
console.log(error)
|
|
}).finally(() => {
|
|
|
|
});
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className="form-group custom-form">
|
|
<FileWrapper>
|
|
{!fileName ? (
|
|
<>
|
|
<FileInput
|
|
type="file"
|
|
required
|
|
onChange={handleFile}
|
|
id="fileinput"
|
|
disabled={disabledBtn}
|
|
accept="image/png, image/jpeg, image/jpg"
|
|
style={{ display: downloadData ? 'none' : 'block' }}
|
|
/>
|
|
<FileButton htmlFor="fileinput" disabled={disabled}>
|
|
이미지 업로드
|
|
</FileButton>
|
|
</>
|
|
) : (
|
|
<PreviewContainer>
|
|
{previewUrl && (
|
|
<ImagePreview
|
|
src={previewUrl}
|
|
alt="이미지 미리보기"
|
|
/>
|
|
)}
|
|
<PreviewInfo>
|
|
{/*<FileName>*/}
|
|
{/* {fileName}*/}
|
|
{/*</FileName>*/}
|
|
<DeleteButton onClick={handleFileDelete}>
|
|
파일 삭제
|
|
</DeleteButton>
|
|
</PreviewInfo>
|
|
</PreviewContainer>
|
|
)}
|
|
</FileWrapper>
|
|
{!fileName && <FileNotice>* .png, .jpg 확장자의 이미지만 업로드 가능합니다.(5MB이하)</FileNotice>}
|
|
</div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ImageUploadBtn;
|
|
|
|
const FileWrapper = styled.div`
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: flex-start;
|
|
margin-right: 20px;
|
|
margin-left: 20px;
|
|
gap: 10px;
|
|
width: 50%;
|
|
`;
|
|
|
|
const FileButton = styled.label`
|
|
border-radius: 5px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: fit-content;
|
|
font-size: 14px;
|
|
background: #2c2c2c;
|
|
color: #fff;
|
|
width: 120px;
|
|
height: 35px;
|
|
cursor: pointer;
|
|
|
|
${props =>
|
|
props.disabled &&
|
|
css`
|
|
background: #b8b8b8;
|
|
cursor: not-allowed;
|
|
`}
|
|
`;
|
|
|
|
const FileInput = styled.input`
|
|
height: 35px;
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 5px;
|
|
//width: calc(100% - 120px);
|
|
padding: 0 15px;
|
|
line-height: 35px;
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
|
|
&::file-selector-button {
|
|
display: none;
|
|
}
|
|
|
|
&:disabled {
|
|
color: #cccccc;
|
|
background: #f6f6f6;
|
|
}
|
|
|
|
${props =>
|
|
props.disabled &&
|
|
css`
|
|
color: #cccccc;
|
|
background: #f6f6f6;
|
|
`}
|
|
`;
|
|
|
|
const FileNotice = styled.div`
|
|
margin: 10px 25px 0;
|
|
color: #cccccc;
|
|
font-size: 10px;
|
|
`;
|
|
|
|
// 새로 추가한 스타일 컴포넌트
|
|
const PreviewContainer = styled.div`
|
|
width: 400px;
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 5px;
|
|
overflow: hidden;
|
|
`;
|
|
|
|
const PreviewInfo = styled.div`
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 8px 10px;
|
|
border-top: 1px solid #e0e0e0;
|
|
`;
|
|
|
|
const FileName = styled.div`
|
|
font-size: 14px;
|
|
color: #555;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
max-width: 250px;
|
|
`;
|
|
|
|
const DeleteButton = styled.button`
|
|
background-color: #ff5252;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
padding: 5px 10px;
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s;
|
|
|
|
&:hover {
|
|
background-color: #ff0000;
|
|
}
|
|
`; |