Files
operationSystem-front/src/components/ServiceManage/ImageUploadBtn.js
bcjang 28094e1c48 배너 detailGrid 적용
배너 수정 및 삭제
2025-07-01 14:40:13 +09:00

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;
}
`;