견적서 첨부파일 멀티

This commit is contained in:
basssy 2024-12-10 16:27:22 +09:00
parent 694e768043
commit b3d1c2d7d0
5 changed files with 59 additions and 21 deletions

View File

@ -25,7 +25,6 @@ export default function Estimate({ params }) {
const [uniqueData, setUniqueData] = useState([]) const [uniqueData, setUniqueData] = useState([])
const [handlePricingFlag, setHandlePricingFlag] = useState(false) const [handlePricingFlag, setHandlePricingFlag] = useState(false)
const [specialNoteFirstFlg, setSpecialNoteFirstFlg] = useState(false) const [specialNoteFirstFlg, setSpecialNoteFirstFlg] = useState(false)
const fixedKey = 'itemKey'
const [itemChangeYn, setItemChangeYn] = useState(false) const [itemChangeYn, setItemChangeYn] = useState(false)
const { session } = useContext(SessionContext) const { session } = useContext(SessionContext)
const [objectNo, setObjectNo] = useState('') // const [objectNo, setObjectNo] = useState('') //
@ -1193,7 +1192,6 @@ export default function Estimate({ params }) {
{originFiles.map((originFile) => { {originFiles.map((originFile) => {
return ( return (
<li className="file-item" key={originFile.no}> <li className="file-item" key={originFile.no}>
{/* <li className="file-item" key={uuidv4()}> */}
<div className="file-item-wrap"> <div className="file-item-wrap">
<span <span
style={{ display: originFile.delFlg === '0' ? '' : 'none' }} style={{ display: originFile.delFlg === '0' ? '' : 'none' }}
@ -1256,7 +1254,6 @@ export default function Estimate({ params }) {
{specialNoteList.length > 0 && {specialNoteList.length > 0 &&
specialNoteList.map((row) => { specialNoteList.map((row) => {
return ( return (
// <div key={uuidv4()} className="special-note-check-item">
<div key={row.code} className="special-note-check-item"> <div key={row.code} className="special-note-check-item">
<div className="special-note-check-box"> <div className="special-note-check-box">
<div className="d-check-box light"> <div className="d-check-box light">

View File

@ -1,14 +1,12 @@
'use client' 'use client'
import { useContext, useRef } from 'react' import { useRef } from 'react'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { SessionContext } from '@/app/SessionProvider'
export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
const fileInputRef = useRef(null) const fileInputRef = useRef(null)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { session } = useContext(SessionContext)
const handleButtonClick = (e) => { const handleButtonClick = (e) => {
e.preventDefault() e.preventDefault()
@ -20,13 +18,32 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
return return
} }
const { files } = e.target const fileList = []
const file = files[0] let passFlag = true
const fileType = file.type Array.from(e.target.files).forEach((file) => {
if (!fileType.includes('image')) { let fileType = file.type
return alert(getMessage('estimate.detail.fileList.extCheck')) if (!fileType.includes('image')) {
passFlag = false
} else {
fileList.push({ data: file, id: uuidv4() })
}
})
if (!passFlag) {
alert(getMessage('estimate.detail.fileList.extCheck'))
} }
// const { files } = e.target
// const file = files[0]
// const fileType = file.type
// if (!fileType.includes('image')) {
// return alert(getMessage('estimate.detail.fileList.extCheck'))
// }
// setUploadFiles([...uploadFiles, { data: e.target.files[0], id: uuidv4() }])
//
setUploadFiles([...uploadFiles, ...fileList])
e.target.value = ''
// const formData = new FormData() // const formData = new FormData()
// formData.append('file', e.target.files[0]) // formData.append('file', e.target.files[0])
// formData.append('objectNo', objectNo) // // formData.append('objectNo', objectNo) //
@ -37,8 +54,6 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
// await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => { // await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => {
// if (res.data > 0) setUploadFiles([...files, { name: e.target.files[0].name, id: uuidv4() }]) // if (res.data > 0) setUploadFiles([...files, { name: e.target.files[0].name, id: uuidv4() }])
// }) // })
setUploadFiles([...uploadFiles, { data: e.target.files[0], id: uuidv4() }])
e.target.value = ''
} }
const deleteFile = (id) => { const deleteFile = (id) => {
@ -49,9 +64,21 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
const fileList = [] const fileList = []
let passFlag = true
Array.from(e.dataTransfer.files).forEach((file) => { Array.from(e.dataTransfer.files).forEach((file) => {
fileList.push({ data: file, id: uuidv4() }) let fileType = file.type
if (!fileType.includes('image')) {
passFlag = false
} else {
fileList.push({ data: file, id: uuidv4() })
}
}) })
if (!passFlag) {
alert(getMessage('estimate.detail.fileList.extCheck'))
}
setUploadFiles([...uploadFiles, ...fileList]) setUploadFiles([...uploadFiles, ...fileList])
} }
@ -76,7 +103,16 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
<label className="file-upload" htmlFor="img" onClick={handleButtonClick}> <label className="file-upload" htmlFor="img" onClick={handleButtonClick}>
{getMessage('estimate.detail.fileList.btn')} {getMessage('estimate.detail.fileList.btn')}
</label> </label>
<input type="file" name="file" id="img" accept="image/*" ref={fileInputRef} style={{ display: 'none' }} onChange={(e) => onChangeFiles(e)} /> <input
type="file"
multiple
name="file"
id="img"
accept="image/*"
ref={fileInputRef}
style={{ display: 'none' }}
onChange={(e) => onChangeFiles(e)}
/>
</div> </div>
<div <div
className="drag-file-area" className="drag-file-area"

View File

@ -1,13 +1,14 @@
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useContext, useEffect, useReducer, useState } from 'react' import { useContext, useEffect, useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
import { isObjectNotEmpty, isEmptyArray, isNotEmptyArray } from '@/util/common-utils' import { isObjectNotEmpty, isEmptyArray } from '@/util/common-utils'
import { SessionContext } from '@/app/SessionProvider' import { SessionContext } from '@/app/SessionProvider'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
import { QcastContext } from '@/app/QcastProvider'
// Constants // Constants
const ESTIMATE_API_ENDPOINT = '/api/estimate' // API 엔드포인트 정의 const ESTIMATE_API_ENDPOINT = '/api/estimate' // API 엔드포인트 정의
@ -19,7 +20,7 @@ const updateItemInList = (itemList, dispOrder, updates) => {
export const useEstimateController = (planNo) => { export const useEstimateController = (planNo) => {
const [fileList, setFileList] = useState([]) const [fileList, setFileList] = useState([])
const [deleteFileList, setDeleteFileList] = useState([]) const { setIsGlobalLoading } = useContext(QcastContext)
const router = useRouter() const router = useRouter()
const { session } = useContext(SessionContext) const { session } = useContext(SessionContext)
@ -52,6 +53,7 @@ export const useEstimateController = (planNo) => {
const fetchSetting = async (objectNo, planNo) => { const fetchSetting = async (objectNo, planNo) => {
try { try {
await promiseGet({ url: `/api/estimate/${objectNo}/${planNo}/detail` }).then((res) => { await promiseGet({ url: `/api/estimate/${objectNo}/${planNo}/detail` }).then((res) => {
setIsGlobalLoading(true)
if (res.status === 200) { if (res.status === 200) {
if (isObjectNotEmpty(res.data)) { if (isObjectNotEmpty(res.data)) {
if (res.data.itemList.length > 0) { if (res.data.itemList.length > 0) {
@ -72,9 +74,11 @@ export const useEstimateController = (planNo) => {
} }
}) })
setIsLoading(true) setIsLoading(true)
setIsGlobalLoading(false)
} catch (error) { } catch (error) {
console.error('견적서 상세조회 Error: ', error) console.error('견적서 상세조회 Error: ', error)
setIsLoading(true) setIsLoading(true)
setIsGlobalLoading(false)
} }
} }
@ -354,15 +358,16 @@ export const useEstimateController = (planNo) => {
// return // return
try { try {
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => { await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => {
setIsGlobalLoading(true)
if (res.status === 201) { if (res.status === 201) {
estimateData.newFileList = [] estimateData.newFileList = []
// estimateData.originFiles = []
alert(getMessage('estimate.detail.save.alertMsg')) alert(getMessage('estimate.detail.save.alertMsg'))
//어디로 보낼지 //어디로 보낼지
fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo) fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo)
} }
}) })
} catch (e) { } catch (e) {
setIsGlobalLoading(false)
console.log('error::::::::::::', e.response.data.message) console.log('error::::::::::::', e.response.data.message)
} }
} }

View File

@ -840,7 +840,7 @@
"estimate.detail.fileFlg": "後日資料提出", "estimate.detail.fileFlg": "後日資料提出",
"estimate.detail.header.fileList1": "ファイル添付", "estimate.detail.header.fileList1": "ファイル添付",
"estimate.detail.fileList.btn": "ファイル選択", "estimate.detail.fileList.btn": "ファイル選択",
"estimate.detail.fileList.extCheck": "そのファイルはイメージファイルではありません", "estimate.detail.fileList.extCheck": "画像ファイルのみ添付可能.",
"estimate.detail.header.fileList2": "添付ファイル一覧", "estimate.detail.header.fileList2": "添付ファイル一覧",
"estimate.detail.fileList2.btn.return": "復元", "estimate.detail.fileList2.btn.return": "復元",
"estimate.detail.header.specialEstimate": "見積もりの具体的な", "estimate.detail.header.specialEstimate": "見積もりの具体的な",

View File

@ -850,7 +850,7 @@
"estimate.detail.fileFlg": "후일자료제출", "estimate.detail.fileFlg": "후일자료제출",
"estimate.detail.header.fileList1": "파일첨부", "estimate.detail.header.fileList1": "파일첨부",
"estimate.detail.fileList.btn": "파일선택", "estimate.detail.fileList.btn": "파일선택",
"estimate.detail.fileList.extCheck": "해당 파일은 이미지 파일이 아닙니다", "estimate.detail.fileList.extCheck": "이미지 파일만 첨부 가능합니다.",
"estimate.detail.header.fileList2": "첨부파일 목록", "estimate.detail.header.fileList2": "첨부파일 목록",
"estimate.detail.fileList2.btn.return": "복원", "estimate.detail.fileList2.btn.return": "복원",
"estimate.detail.header.specialEstimate": "견적특이사항", "estimate.detail.header.specialEstimate": "견적특이사항",