Browse Source

사용자 qna 문의 파일 등록

pull/2/head
hhjk00 11 months ago
parent
commit
dc66eb40e0
  1. 38
      src/components/cstmrService/inquiry/InquiryWrite.js
  2. 69
      src/containers/cstmrService/inquiry/UserInquiryContainer.js
  3. 14
      src/modules/cstmrService/inquiry/model/index.ts

38
src/components/cstmrService/inquiry/InquiryWrite.js

@ -26,20 +26,11 @@ function InquiryWrite({
handlerSubmitInquiryForm,
memberName,
inquiryForm,
handlerDeleteConfirmInquiry
handlerDeleteConfirmInquiry,
fileInputRef,
handlerFileChange,
handlerFileClear
}) {
const fileInputRef = useRef(null);
const [selectedFile, setSelectedFile] = useState(null);
const handleFileChange = event => {
const file = event.target.files[0];
setSelectedFile(file);
};
const handleFileClear = () => {
setSelectedFile(null);
};
return (
<Modal
isOpen={isInquiryModalOpen}
@ -170,7 +161,7 @@ function InquiryWrite({
</Label>
<div
className={`custom-file ${
selectedFile ? 'file-selected' : ''
inquiryForm.fileInfos.length > 0 ? 'file-selected' : ''
}`}
>
<Input
@ -178,21 +169,22 @@ function InquiryWrite({
id='inputFile'
name=''
className='custom-file-input pal'
onChange={e => handleFileChange(e)}
onChange={e => handlerFileChange(e)}
ref={fileInputRef}
/>
{/* 현재는 text만 바뀌는상태! input 초기화 작업해주세용 */}
{selectedFile && ( // Display the trash icon only if a file is selected
{inquiryForm.fileInfos.length > 0 && ( // Display the trash icon only if a file is selected
<span className='custom-file-control'>
<X // Display a trash icon
className='clear-file-button'
onClick={handleFileClear}
onClick={() => handlerFileClear('edit')}
/>
</span>
)}
<Label for='inputFile' className='custom-file-label'>
{selectedFile
? selectedFile.name
{inquiryForm.fileInfos.length > 0
? inquiryForm.fileInfos[0].fileName ||
inquiryForm.fileInfos[0].name
: '선택된 파일이 없습니다.'}
</Label>
</div>
@ -208,9 +200,11 @@ function InquiryWrite({
</ModalBody>
<ModalFooter>
<div className='pal-form-btn'>
<Button color='danger' onClick={handlerDeleteConfirmInquiry}>
삭제
</Button>
{detail.createDt && (
<Button color='danger' onClick={handlerDeleteConfirmInquiry}>
삭제
</Button>
)}
<Button color='secondary' onClick={() => handlerInquiryModal()}>
취소
</Button>

69
src/containers/cstmrService/inquiry/UserInquiryContainer.js

@ -2,7 +2,7 @@ import { Button, Badge } from 'reactstrap';
import AppCollapse from '@components/app-collapse';
import { useDispatch, useSelector } from 'react-redux';
import * as Actions from '../../../modules/cstmrService/inquiry/action';
import { Fragment, useCallback, useEffect, useState } from 'react';
import { Fragment, useCallback, useEffect, useRef, useState } from 'react';
import moment from 'moment';
import InquiryWrite from '../../../components/cstmrService/inquiry/InquiryWrite';
import { InfoModal } from '../../../components/modal/InfoModal';
@ -15,13 +15,16 @@ export default function UserInquiryContainer({ memberName }) {
state => state.qnaState
);
const fileInputRef = useRef(null);
const [isInquiryModalOpen, setIsInquiryModalOpen] = useState(false);
const [inquiryForm, setInquiryForm] = useState({
category: '칭찬',
contact: '',
title: '',
content: ''
content: '',
fileInfos: []
});
const [validationModal, setValidationModal] = useState({
errorType: {
isOpen: false,
@ -129,7 +132,8 @@ export default function UserInquiryContainer({ memberName }) {
category: '칭찬',
contact: '',
title: '',
content: ''
content: '',
fileInfos: []
});
}
setIsInquiryModalOpen(!isInquiryModalOpen);
@ -148,9 +152,25 @@ export default function UserInquiryContainer({ memberName }) {
[inquiryForm]
);
const handlerFileChange = e => {
const file = e.target.files[0];
setInquiryForm({
...inquiryForm,
fileInfos: [file]
});
};
const handlerFileClear = () => {
setInquiryForm({
...inquiryForm,
fileInfos: []
});
};
// 문의 등록 event handler
const handlerSubmitInquiryForm = type => {
const { category, title, content, contact, qnaSno } = inquiryForm;
const { category, title, content, contact, fileInfos, qnaSno } =
inquiryForm;
if (!contact) {
setValidationModal({
@ -192,6 +212,34 @@ export default function UserInquiryContainer({ memberName }) {
}
});
return;
} else if (fileInfos.length > 0) {
const allowedExtensions = ['jpg', 'png', 'jpeg', 'gif'];
const fileExtension = fileInfos[0].name.split('.').pop().toLowerCase();
const maxFileSize = 3 * 1024 * 1024; // 3MB
if (!allowedExtensions.includes(fileExtension)) {
setValidationModal({
...validationModal,
errorType: {
title: '파일 형식 오류',
isOpen: true,
desc: '파일 형식은 jpg, png, jpeg, gif 형식만 가능합니다.'
}
});
return;
}
if (fileInfos[0].size > maxFileSize) {
setValidationModal({
...validationModal,
errorType: {
title: '파일 크기 오류',
isOpen: true,
desc: '파일 크기는 3MB를 초과할 수 없습니다.'
}
});
return;
}
}
if (type === 'post') {
@ -201,6 +249,10 @@ export default function UserInquiryContainer({ memberName }) {
form.append('title', title);
form.append('content', content);
if (fileInfos.length > 0) {
form.append('files', fileInfos[0]);
}
dispatch(Actions.USER_INQUIRY.request(form));
} else if (type === 'edit') {
dispatch(
@ -249,13 +301,16 @@ export default function UserInquiryContainer({ memberName }) {
<InquiryWrite
isInquiryModalOpen={isInquiryModalOpen}
handlerInquiryModal={handlerInquiryModal}
detail={detail}
inquiryForm={inquiryForm}
memberName={memberName}
fileInputRef={fileInputRef}
handlerChangeInquiryForm={handlerChangeInquiryForm}
handlerSubmitInquiryForm={handlerSubmitInquiryForm}
memberName={memberName}
inquiryForm={inquiryForm}
handlerInquiryModal={handlerInquiryModal}
handlerDeleteConfirmInquiry={handlerDeleteConfirmInquiry}
handlerFileChange={handlerFileChange}
handlerFileClear={handlerFileClear}
/>
<InfoModal

14
src/modules/cstmrService/inquiry/model/index.ts

@ -28,6 +28,7 @@ export interface IQnaAdminSearch {
export interface IQnaFiles {
fileSno: number;
fileGroupNo: number;
downloadUrl: string;
fileName: string;
}
@ -95,6 +96,15 @@ export interface IQnaUserInquiry {
title: string;
contact: string;
content: string;
files: IQnaUserFileUpload[];
}
export interface IQnaUserFileUpload {
lastModified: number;
lastModifiedDate: Date;
name: string;
type: string;
webkitRelativePath: string;
}
export interface IQnaUserDetail {
@ -115,7 +125,7 @@ export interface IQnaUserDetail {
createDt: string;
updateUserId: string;
updateDt: string;
files: IQnaFiles[];
fileInfos: IQnaFiles[];
}
export interface IQnaUserUpdate extends IQnaUserInquiry {
@ -163,6 +173,6 @@ export const initalState = {
createDt: '',
updateUserId: '',
updateDt: '',
files: []
fileInfos: []
}
};

Loading…
Cancel
Save