917 lines
37 KiB
JavaScript
917 lines
37 KiB
JavaScript
'use client'
|
|
|
|
import { useEffect, useState, useContext } from 'react'
|
|
import { useRecoilValue } from 'recoil'
|
|
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
|
import { useMessage } from '@/hooks/useMessage'
|
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
|
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
|
import EstimateFileUploader from './EstimateFileUploader'
|
|
import { useAxios } from '@/hooks/useAxios'
|
|
import { globalLocaleStore } from '@/store/localeAtom'
|
|
import { isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
|
|
import dayjs from 'dayjs'
|
|
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
|
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
|
import { SessionContext } from '@/app/SessionProvider'
|
|
import Select, { components } from 'react-select'
|
|
import { convertNumberToPriceDecimal } from '@/util/common-utils'
|
|
import ProductFeaturesPop from './popup/ProductFeaturesPop'
|
|
export default function Estimate({ params }) {
|
|
const { session } = useContext(SessionContext)
|
|
const [objectNo, setObjectNo] = useState('') //물건번호
|
|
const [planNo, setPlanNo] = useState('') //플랜번호
|
|
|
|
const [files, setFiles] = useState([]) // 보내는 첨부파일
|
|
const [originFiles, setOriginFiles] = useState([]) //기존 첨부파일
|
|
|
|
const [showContentCode, setShowContentCode] = useState('ATTR001')
|
|
|
|
const [productFeaturesPopupOpen, setProductFeaturesPopupOpen] = useState(false) //견적특이사항 팝업
|
|
const [showProductFeatureData, setShowProductFeatureData] = useState([]) //팝업에 보여줄 견적특이사항 데이터
|
|
|
|
const [selection, setSelection] = useState(new Set())
|
|
//견적특이사항 접고 펼치기
|
|
const [hidden, setHidden] = useState(false)
|
|
|
|
//아이템 자동완성 리스트
|
|
const [displayItemList, setDisplayItemList] = useState([])
|
|
|
|
//공통코드
|
|
const { findCommonCode } = useCommonCode()
|
|
const [honorificCodeList, setHonorificCodeList] = useState([]) //경칭 공통코드
|
|
|
|
const [storePriceList, setStorePriceList] = useState([]) //가격표시 option
|
|
|
|
const [tempPriceCd, setTempPriceCd] = useState('')
|
|
|
|
const [startDate, setStartDate] = useState(new Date())
|
|
const singleDatePickerProps = {
|
|
startDate,
|
|
setStartDate,
|
|
}
|
|
|
|
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
|
|
|
//견적서 상세데이터
|
|
const { state, setState, addItem } = useEstimateController(params.pid)
|
|
|
|
//견적특이사항 List
|
|
const [specialNoteList, setSpecialNoteList] = useState([])
|
|
|
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
|
const { get, promisePost } = useAxios(globalLocaleState)
|
|
|
|
const { getMessage } = useMessage()
|
|
|
|
const { setMenuNumber } = useCanvasMenu()
|
|
|
|
//새로 추가한 첨부파일 props
|
|
const fileUploadProps = {
|
|
uploadFiles: files,
|
|
setUploadFiles: setFiles,
|
|
}
|
|
|
|
useEffect(() => {
|
|
setMenuNumber(5)
|
|
setObjectNo(objectRecoil.floorPlanObjectNo)
|
|
setPlanNo(params.pid)
|
|
|
|
// 공통코드
|
|
const code1 = findCommonCode(200800)
|
|
if (code1 != null) {
|
|
setHonorificCodeList(code1)
|
|
}
|
|
|
|
//아이템 자동완성 목록 가져오기
|
|
const param = {
|
|
saleStoreId: session.storeId,
|
|
}
|
|
const apiUrl = `/api/display-item/item-list?${queryStringFormatter(param)}`
|
|
get({ url: apiUrl }).then((res) => {
|
|
if (res.length > 0) {
|
|
setDisplayItemList(res)
|
|
}
|
|
})
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
//견적특이사항 API호출
|
|
//여러개 선택하면 구분자로 (、)
|
|
let url = `/api/estimate/special-note-list`
|
|
get({ url: url }).then((res) => {
|
|
if (isNotEmptyArray(res)) {
|
|
if (state?.estimateOption) {
|
|
res.map((row) => {
|
|
let estimateOption = state?.estimateOption?.split('、')
|
|
row.text = false
|
|
estimateOption.map((row2) => {
|
|
if (row2 === row.code) {
|
|
row.text = true
|
|
}
|
|
})
|
|
})
|
|
setSpecialNoteList(res)
|
|
}
|
|
}
|
|
})
|
|
}, [state?.estimateOption])
|
|
|
|
//견적일 set
|
|
useEffect(() => {
|
|
let estimateDate = dayjs(startDate).format('YYYY-MM-DD')
|
|
setState({ estimateDate: estimateDate })
|
|
}, [startDate])
|
|
|
|
useEffect(() => {
|
|
//선택된 견적특이사항 setState
|
|
if (isNotEmptyArray(specialNoteList)) {
|
|
const liveCheckedData = specialNoteList.filter((row) => row.text === true)
|
|
|
|
const data = []
|
|
for (let ele of liveCheckedData) {
|
|
data.push(ele.code)
|
|
}
|
|
|
|
const newData = data.join('、')
|
|
setState({ estimateOption: newData })
|
|
}
|
|
}, [specialNoteList])
|
|
|
|
// 견적특이사항 remark 보여주기
|
|
const settingShowContent = (code, event) => {
|
|
setShowContentCode(code)
|
|
event.stopPropagation()
|
|
}
|
|
|
|
// 추가한 첨부파일 state에 넣기
|
|
useEffect(() => {
|
|
if (isNotEmptyArray(files)) {
|
|
files.map((row) => {
|
|
setState({ fileList: row.data })
|
|
})
|
|
} else {
|
|
setState({ fileList: [] })
|
|
}
|
|
}, [files])
|
|
|
|
//상세에서 내려온 첨부파일 set 만들기
|
|
useEffect(() => {
|
|
if (isNotEmptyArray(state.fileList)) {
|
|
setOriginFiles(state.fileList)
|
|
}
|
|
}, [state?.fileList])
|
|
|
|
// 기존첨부파일 삭제
|
|
const deleteOriginFile = async (objectNo, no) => {
|
|
const delParams = {
|
|
userId: session.userId,
|
|
objectNo: objectNo,
|
|
no: no,
|
|
}
|
|
|
|
await promisePost({ url: 'api/file/fileDelete', data: delParams }).then((res) => {
|
|
if (res.status === 204) {
|
|
setOriginFiles(originFiles.filter((file) => file.objectNo === objectNo && file.no !== no))
|
|
setState({
|
|
fileList: originFiles.filter((file) => file.objectNo === objectNo && file.no !== no),
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
//아이템 목록
|
|
// useEffect(() => {
|
|
// if (isNotEmptyArray(state.itemList)) {
|
|
// setItemList(state.itemList)
|
|
// }
|
|
// }, [state?.itemList])
|
|
|
|
//가격표시 option 최초세팅
|
|
useEffect(() => {
|
|
if (state.estimateType !== '') {
|
|
const param = {
|
|
saleStoreId: session.storeId,
|
|
sapSalesStoreCd: session.custCd,
|
|
docTpCd: state?.estimateType,
|
|
}
|
|
|
|
const apiUrl = `/api/estimate/price/store-price-list?${queryStringFormatter(param)}`
|
|
get({ url: apiUrl }).then((res) => {
|
|
if (isNotEmptyArray(res?.data)) {
|
|
setStorePriceList(res.data)
|
|
}
|
|
})
|
|
}
|
|
}, [state?.estimateType])
|
|
|
|
//가격표시 option 변경시
|
|
useEffect(() => {
|
|
if (tempPriceCd !== '') {
|
|
const param = {
|
|
saleStoreId: session.storeId,
|
|
sapSalesStoreCd: session.custCd,
|
|
docTpCd: tempPriceCd,
|
|
}
|
|
|
|
const apiUrl = `/api/estimate/price/store-price-list?${queryStringFormatter(param)}`
|
|
get({ url: apiUrl }).then((res) => {
|
|
if (isNotEmptyArray(res?.data)) {
|
|
setStorePriceList(res.data)
|
|
}
|
|
})
|
|
}
|
|
}, [tempPriceCd])
|
|
|
|
//Pricing 버튼
|
|
const handlePricing = async (priceCd) => {
|
|
const param = {
|
|
saleStoreId: session.storeId,
|
|
sapSalesStoreCd: session.custCd,
|
|
docTpCd: state.estimateType,
|
|
priceCd: session.storeLvl === '1' ? tempPriceCd : priceCd,
|
|
itemIdList: state.itemList, //아이템 최초정보로 호출
|
|
}
|
|
|
|
// console.log('프라이싱파람::', param)
|
|
await promisePost({ url: '/api/estimate/price/item-price-list', data: param }).then((res) => {
|
|
if (res) {
|
|
if (res.status === 200) {
|
|
const data = res.data
|
|
if (data.result.code === 200) {
|
|
if (isNotEmptyArray(data.data2)) {
|
|
//아이템쪽 다 새로고침............
|
|
//성공후..
|
|
//기존itemList랑 프라이싱결과랑 비교해서 단가만 업뎃 서로 갯수가 안맞을 수 있음 없는 itemId면 unitPrice 0으로
|
|
//itemId로 비교해서 단가정보만 업데이트
|
|
setState({
|
|
priceCd: session.storeLvl === '1' ? tempPriceCd : priceCd,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
//row 체크박스 컨트롤
|
|
const onChangeSelect = (dispOrder) => {
|
|
const newSelection = new Set(selection)
|
|
if (newSelection.has(dispOrder)) {
|
|
newSelection.delete(dispOrder)
|
|
} else {
|
|
newSelection.add(dispOrder)
|
|
}
|
|
|
|
setSelection(newSelection)
|
|
}
|
|
|
|
// 아이템 자동완성 검색시
|
|
const onChangeDisplayItem = (itemId, dispOrder) => {
|
|
console.log('아이템 자동완성:::::::', dispOrder)
|
|
const param = {
|
|
itemId: itemId,
|
|
}
|
|
const apiUrl = `/api/display-item/item-detail?${queryStringFormatter(param)}`
|
|
get({ url: apiUrl }).then((res) => {
|
|
console.log('제품상세 결과::::::::', res)
|
|
})
|
|
// setState({
|
|
// itemList: [{ itemNo: '123123123123' }],
|
|
// })
|
|
}
|
|
|
|
//제품 삭제
|
|
const removeItem = () => {
|
|
const array = [...selection]
|
|
let tempList = []
|
|
state.itemList.filter((row) => {
|
|
array.map((row2) => {
|
|
if (row2 === row.dispOrder) {
|
|
tempList.push({ ...row })
|
|
}
|
|
})
|
|
})
|
|
|
|
const result = state.itemList.filter((item) => {
|
|
return !tempList.some((other) => other.dispOrder === item.dispOrder)
|
|
})
|
|
|
|
setState({
|
|
itemList: result,
|
|
})
|
|
|
|
setSelection(new Set())
|
|
}
|
|
|
|
return (
|
|
<div className="sub-content estimate">
|
|
<div className="sub-content-inner">
|
|
{/* 물건번호, 견적서번호, 등록일, 변경일시 시작 */}
|
|
<div className="sub-content-box">
|
|
<div className="sub-table-box">
|
|
<div className="estimate-list-wrap one">
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div>
|
|
<div className="estimate-name">
|
|
{objectNo} (Plan No: {planNo})
|
|
</div>
|
|
</div>
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.docNo')}</div>
|
|
<div className="estimate-name">{state.docNo}</div>
|
|
</div>
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.drawingEstimateCreateDate')}</div>
|
|
<div className="estimate-name">
|
|
{state?.drawingEstimateCreateDate ? `${dayjs(state.drawingEstimateCreateDate).format('YYYY.MM.DD')}` : ''}
|
|
</div>
|
|
</div>
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.lastEditDatetime')}</div>
|
|
<div className="estimate-name">{state?.lastEditDatetime ? `${dayjs(state.lastEditDatetime).format('YYYY.MM.DD HH:mm')}` : ''}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/* 물건번호, 견적서번호, 등록일, 변경일시 끝 */}
|
|
{/* 기본정보 시작 */}
|
|
<div className="sub-content-box">
|
|
<div className="sub-table-box">
|
|
<div className="table-box-title-wrap">
|
|
<div className="title-wrap">
|
|
<h3>{getMessage('estimate.detail.header.title')}</h3>
|
|
</div>
|
|
</div>
|
|
<div className="common-table bt-able">
|
|
<table>
|
|
<colgroup>
|
|
<col style={{ width: '160px' }} />
|
|
<col />
|
|
<col style={{ width: '160px' }} />
|
|
<col />
|
|
</colgroup>
|
|
<tbody>
|
|
<tr>
|
|
{/* 1차 판매점명 */}
|
|
<th>{getMessage('estimate.detail.saleStoreId')}</th>
|
|
<td>{state?.firstSaleStoreName}</td>
|
|
{/* 견적일 */}
|
|
<th>
|
|
{getMessage('estimate.detail.estimateDate')} <span className="important">*</span>
|
|
</th>
|
|
<td>
|
|
<div className="date-picker" style={{ width: '350px' }}>
|
|
<SingleDatePicker {...singleDatePickerProps} />
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
{/* 2차 판매점명 */}
|
|
<th>{getMessage('estimate.detail.otherSaleStoreId')}</th>
|
|
<td>{state?.agencySaleStoreName}</td>
|
|
{/* 담당자 */}
|
|
<th>
|
|
{getMessage('estimate.detail.receiveUser')} <span className="important">*</span>
|
|
</th>
|
|
<td>
|
|
<div className="input-wrap" style={{ width: '350px' }}>
|
|
<input
|
|
type="text"
|
|
className="input-light"
|
|
defaultValue={state?.charger}
|
|
onChange={(e) => {
|
|
//담당자 charger
|
|
setState({ charger: e.target.value })
|
|
}}
|
|
/>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
{/* 안건명 */}
|
|
<th>
|
|
{getMessage('estimate.detail.objectName')} <span className="important">*</span>
|
|
</th>
|
|
<td colSpan={3}>
|
|
<div className="form-flex-wrap">
|
|
<div className="input-wrap mr5" style={{ width: '610px' }}>
|
|
<input
|
|
type="text"
|
|
className="input-light"
|
|
defaultValue={state?.objectName}
|
|
onChange={(e) => {
|
|
//안건명 objectName
|
|
setState({ objectName: e.target.value })
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className="select-wrap" style={{ width: '200px' }}>
|
|
<Select
|
|
id="objectNameOmit"
|
|
instanceId="objectNameOmit"
|
|
className="react-select-custom"
|
|
classNamePrefix="custom"
|
|
placeholder="Select"
|
|
options={honorificCodeList}
|
|
onChange={(e) => {
|
|
if (isObjectNotEmpty(e)) {
|
|
setState({ objectNameOmit: e.clCodeNm })
|
|
} else {
|
|
setState({ objectNameOmit: '' })
|
|
}
|
|
}}
|
|
getOptionLabel={(x) => x.clCodeNm}
|
|
getOptionValue={(x) => x.clCode}
|
|
isClearable={true}
|
|
isSearchable={false}
|
|
value={honorificCodeList.filter(function (option) {
|
|
return option.clCodeNm === state.objectNameOmit
|
|
})}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
{/* 물건정보에서 입력한 메모 */}
|
|
<th>{getMessage('estimate.detail.objectRemarks')}</th>
|
|
<td colSpan={3}>{state?.objectRemarks}</td>
|
|
</tr>
|
|
<tr>
|
|
{/* 주문분류 */}
|
|
<th>
|
|
{getMessage('estimate.detail.estimateType')} <span className="important">*</span>
|
|
</th>
|
|
<td colSpan={3}>
|
|
<div className="radio-wrap">
|
|
<div className="d-check-radio light mr10">
|
|
<input
|
|
type="radio"
|
|
name="estimateType"
|
|
id="YJSS"
|
|
value={'YJSS'}
|
|
checked={state?.estimateType === 'YJSS' ? true : false}
|
|
onChange={(e) => {
|
|
//주문분류
|
|
setState({ estimateType: e.target.value })
|
|
}}
|
|
/>
|
|
<label htmlFor="YJSS">住宅PKG</label>
|
|
</div>
|
|
<div className="d-check-radio light">
|
|
<input
|
|
type="radio"
|
|
name="estimateType"
|
|
id="YJOD"
|
|
value={'YJOD'}
|
|
checked={state?.estimateType === 'YJOD' ? true : false}
|
|
onChange={(e) => {
|
|
setState({ estimateType: e.target.value })
|
|
}}
|
|
/>
|
|
<label htmlFor="YJOD">積上げ( YJOD )</label>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
{/* 지붕재・사양시공 최대4개*/}
|
|
<th>{getMessage('estimate.detail.roofCns')}</th>
|
|
<td colSpan={3}>
|
|
{state?.roofMaterialIdMulti?.split('、').map((row, index) => {
|
|
//지붕재
|
|
let roofList = row
|
|
let roofListLength = state?.roofMaterialIdMulti?.split('、').length
|
|
let style = 'mb5'
|
|
if (roofListLength == index + 1) {
|
|
style = ''
|
|
}
|
|
//사양시공
|
|
let constructSpecificationMulti = state?.constructSpecificationMulti?.split('、')
|
|
|
|
return (
|
|
<>
|
|
<div className={`form-flex-wrap ${style}`}>
|
|
<div className="input-wrap mr5" style={{ width: '610px' }}>
|
|
<input type="text" className="input-light" defaultValue={roofList} readOnly />
|
|
</div>
|
|
<div className="input-wrap" style={{ width: '200px' }}>
|
|
<input type="text" className="input-light" defaultValue={constructSpecificationMulti[index]} readOnly />
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
})}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
{/* 비고 */}
|
|
<th>{getMessage('estimate.detail.remarks')}</th>
|
|
<td colSpan={3}>
|
|
<div className="input-wrap">
|
|
<input
|
|
type="text"
|
|
className="input-light"
|
|
defaultValue={state?.remarks}
|
|
onChange={(e) => {
|
|
//비고
|
|
setState({ remarks: e.target.value })
|
|
}}
|
|
/>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{/* 파일첨부 시작 */}
|
|
<div className="table-box-title-wrap">
|
|
<div className="title-wrap">
|
|
<h3>{getMessage('estimate.detail.header.fileList1')}</h3>
|
|
<div className="d-check-box light mr5">
|
|
<input
|
|
type="checkbox"
|
|
id="next"
|
|
checked={state?.fileFlg === '0' ? false : true}
|
|
onChange={(e) => {
|
|
setState({
|
|
fileFlg: e.target.checked ? '1' : '0',
|
|
})
|
|
}}
|
|
/>
|
|
<label htmlFor="next" style={{ color: '#101010' }}>
|
|
{getMessage('estimate.detail.fileFlg')}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="common-table mb10">
|
|
<table>
|
|
<colgroup>
|
|
<col style={{ width: '160px' }} />
|
|
<col />
|
|
</colgroup>
|
|
<tbody>
|
|
<tr>
|
|
<th>{getMessage('estimate.detail.header.fileList1')}</th>
|
|
<td>
|
|
<EstimateFileUploader {...fileUploadProps} />
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{/* 첨부파일 목록 시작 */}
|
|
<div className="common-table bt-able">
|
|
<table>
|
|
<colgroup>
|
|
<col style={{ width: '160px' }} />
|
|
<col />
|
|
</colgroup>
|
|
<tbody>
|
|
<tr>
|
|
<th>{getMessage('estimate.detail.header.fileList2')}</th>
|
|
<td>
|
|
<div className="drag-file-box">
|
|
<ul className="file-list">
|
|
{originFiles.length > 0 &&
|
|
originFiles.map((originFile) => {
|
|
return (
|
|
<li className="file-item">
|
|
<span>
|
|
{originFile.faileName}
|
|
<button className="delete" onClick={() => deleteOriginFile(originFile.objectNo, originFile.no)}></button>
|
|
</span>
|
|
</li>
|
|
)
|
|
})}
|
|
</ul>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{/* 첨부파일 목록 끝 */}
|
|
{/* 파일첨부 끝 */}
|
|
{/* 견적특이사항 시작 */}
|
|
<div className="table-box-title-wrap">
|
|
<div className="title-wrap">
|
|
<h3 className="product">{getMessage('estimate.detail.header.specialEstimate')}</h3>
|
|
<div className="product_tit">{getMessage('estimate.detail.header.specialEstimateProductInfo')}</div>
|
|
</div>
|
|
<div className="left-unit-box">
|
|
<button className={`estimate-arr-btn down mr5 ${hidden ? '' : 'on'}`} onClick={() => setHidden(false)}></button>
|
|
<button className={`estimate-arr-btn up ${hidden ? 'on' : ''}`} onClick={() => setHidden(true)}></button>
|
|
</div>
|
|
</div>
|
|
{/* 견적 특이사항 코드영역시작 */}
|
|
<div className={`estimate-check-wrap ${hidden ? 'hide' : ''}`}>
|
|
<div className="estimate-check-inner">
|
|
<div className="special-note-check-wrap">
|
|
{/* SpecialNoteList반복문 */}
|
|
{specialNoteList.length > 0 &&
|
|
specialNoteList.map((row) => {
|
|
return (
|
|
<div
|
|
className="special-note-check-item"
|
|
onClick={(event) => {
|
|
settingShowContent(row.code, event)
|
|
}}
|
|
>
|
|
<div className="d-check-box light">
|
|
<input
|
|
type="checkbox"
|
|
id={row.code}
|
|
checked={!!row.text}
|
|
disabled={row.code === 'ATTR001' ? true : false}
|
|
onChange={(event) => {
|
|
setSpecialNoteList((specialNote) =>
|
|
specialNote.map((temp) => (temp.code === row.code ? { ...temp, text: !temp.text } : temp)),
|
|
)
|
|
settingShowContent(row.code, event)
|
|
}}
|
|
/>
|
|
<label htmlFor={row.code}>{row.codeNm}</label>
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
{/* 견적특이사항 선택한 내용 영역시작 */}
|
|
<div className="calculation-estimate">
|
|
{specialNoteList.map((row) => {
|
|
if (row.code === showContentCode) {
|
|
return (
|
|
<dl>
|
|
<dt>{row.codeNm}</dt>
|
|
<dd dangerouslySetInnerHTML={{ __html: row.remarks }}></dd>
|
|
</dl>
|
|
)
|
|
}
|
|
})}
|
|
</div>
|
|
{/* 견적특이사항 선택한 내용 영역끝 */}
|
|
</div>
|
|
</div>
|
|
|
|
{/* 견적 특이사항 코드영역 끝 */}
|
|
|
|
{/* 견적특이사항 영역끝 */}
|
|
{/* 제품정보 시작 */}
|
|
<div className="table-box-title-wrap">
|
|
<div className="title-wrap">
|
|
<h3>{getMessage('estimate.detail.header.specialEstimateProductInfo')}</h3>
|
|
</div>
|
|
</div>
|
|
<div className="esimate-wrap">
|
|
<div className="estimate-list-wrap one">
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totPcs')}</div>
|
|
<div className="estimate-name blue">74</div>
|
|
</div>
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.vol')}</div>
|
|
<div className="estimate-name blue">8300</div>
|
|
</div>
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.netAmt')}</div>
|
|
<div className="estimate-name blue">6,798,900</div>
|
|
</div>
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.vat')}</div>
|
|
<div className="estimate-name blue">679,890</div>
|
|
</div>
|
|
<div className="estimate-box">
|
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totPrice')}</div>
|
|
<div className="estimate-name red">7,478,790</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/* YJOD면 아래영역 숨김 */}
|
|
<div className="common-table bt-able" style={{ display: state?.estimateType === 'YJSS' ? '' : 'none' }}>
|
|
<table>
|
|
<colgroup>
|
|
<col style={{ width: '160px' }} />
|
|
<col />
|
|
<col style={{ width: '160px' }} />
|
|
<col />
|
|
<col style={{ width: '160px' }} />
|
|
<col />
|
|
</colgroup>
|
|
<tbody>
|
|
<tr>
|
|
<th>
|
|
{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice')}
|
|
<span className="important">*</span>
|
|
</th>
|
|
<td>
|
|
<div className="input-wrap">
|
|
<input type="text" className="input-light" />
|
|
</div>
|
|
</td>
|
|
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th>
|
|
<td>{getMessage('estimate.detail.sepcialEstimateProductInfo.calcFormula1')}</td>
|
|
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th>
|
|
<td>{getMessage('estimate.detail.sepcialEstimateProductInfo.calcFormula2')}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{/* 제품정보 끝 */}
|
|
{/* 가격표시영역시작 */}
|
|
<div className="estimate-product-option">
|
|
<div className="product-price-wrap">
|
|
<div className="product-price-tit">{getMessage('estimate.detail.header.showPrice')}</div>
|
|
<div className="select-wrap">
|
|
{session?.storeLvl === '1' ? (
|
|
<select
|
|
className="select-light"
|
|
onChange={(e) => {
|
|
setTempPriceCd(e.target.value)
|
|
}}
|
|
>
|
|
{storePriceList.length > 0 && storePriceList.map((row) => <option value={row.priceCd}>{row.priceNm}</option>)}
|
|
</select>
|
|
) : (
|
|
<select className="select-light">
|
|
<option value="UNIT_PRICE">{getMessage('estimate.detail.header.unitPrice')}</option>
|
|
</select>
|
|
)}
|
|
</div>
|
|
<button
|
|
className="btn-origin grey ml5"
|
|
onClick={() => {
|
|
handlePricing(state.priceCd)
|
|
}}
|
|
>
|
|
{getMessage('estimate.detail.showPrice.pricingBtn')}
|
|
</button>
|
|
</div>
|
|
<div className="product-edit-wrap">
|
|
<ul className="product-edit-explane">
|
|
<li className="explane-item item01">
|
|
<span className="ico"></span>
|
|
{getMessage('estimate.detail.showPrice.description1')}
|
|
</li>
|
|
<li className="explane-item item02">
|
|
<span className="ico"></span>
|
|
{getMessage('estimate.detail.showPrice.description2')}
|
|
</li>
|
|
<li className="explane-item item03">
|
|
<span className="ico"></span>
|
|
{getMessage('estimate.detail.showPrice.description3')}
|
|
</li>
|
|
<li className="explane-item item04">
|
|
<span className="ico"></span>
|
|
{getMessage('estimate.detail.showPrice.description4')}
|
|
</li>
|
|
</ul>
|
|
<div className="product-edit-btn">
|
|
<button className="btn-origin navy mr5" type="button" onClick={addItem}>
|
|
<span className="plus"></span>
|
|
{getMessage('estimate.detail.showPrice.addItem')}
|
|
</button>
|
|
<button className="btn-origin grey" type="button" onClick={removeItem}>
|
|
<span className="minus"></span>
|
|
{getMessage('estimate.detail.showPrice.delItem')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/* 가격표시영역끝 */}
|
|
{/* html테이블시작 */}
|
|
<div className="esimate-table">
|
|
<table>
|
|
<colgroup>
|
|
<col width={50} />
|
|
<col width={100} />
|
|
<col />
|
|
<col width={200} />
|
|
<col width={100} />
|
|
<col width={100} />
|
|
<col width={200} />
|
|
<col width={240} />
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th>
|
|
<div className="d-check-box pop no-text" style={{ display: 'none' }}>
|
|
<input type="checkbox" id="ch97" />
|
|
<label htmlFor="ch97"></label>
|
|
</div>
|
|
</th>
|
|
<th>{getMessage('estimate.detail.itemTableHeader.dispOrder')}</th>
|
|
<th>{getMessage('estimate.detail.itemTableHeader.itemId')}</th>
|
|
<th>{getMessage('estimate.detail.itemTableHeader.itemNo')}</th>
|
|
<th>{getMessage('estimate.detail.itemTableHeader.amount')}</th>
|
|
<th>{getMessage('estimate.detail.itemTableHeader.unit')}</th>
|
|
<th>{getMessage('estimate.detail.itemTableHeader.salePrice')}</th>
|
|
<th>{getMessage('estimate.detail.itemTableHeader.saleTotPrice')}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{state?.itemList.length > 0 &&
|
|
state.itemList.map((item, index) => {
|
|
return (
|
|
<tr key={index}>
|
|
<td className="al-c">
|
|
<div className="d-check-box light no-text">
|
|
<input
|
|
type="checkbox"
|
|
id={item?.dispOrder}
|
|
onChange={() => onChangeSelect(item.dispOrder)}
|
|
checked={selection.has(item.dispOrder) ? true : false}
|
|
/>
|
|
<label htmlFor={item?.dispOrder}></label>
|
|
</div>
|
|
</td>
|
|
<td className="al-r">{item?.dispOrder * 100}</td>
|
|
<td>
|
|
<div className="form-flex-wrap">
|
|
<div className="select-wrap mr5">
|
|
<Select
|
|
id="long-value-select1"
|
|
instanceId="long-value-select1"
|
|
className="react-select-custom"
|
|
classNamePrefix="custom"
|
|
placeholder="Select"
|
|
options={displayItemList}
|
|
onChange={(e) => onChangeDisplayItem(e.itemId, item.dispOrder)}
|
|
getOptionLabel={(x) => x.itemName}
|
|
getOptionValue={(x) => x.itemId}
|
|
isClearable={true}
|
|
isDisabled={false}
|
|
value={displayItemList.filter(function (option) {
|
|
// console.log('옵션값???', option.itemId)
|
|
// console.log('골랐을때 여기오지???', item.itemId)
|
|
return option.itemId === item.itemId
|
|
})}
|
|
/>
|
|
</div>
|
|
{item?.itemChangeFlg === '1' && (
|
|
<div className="btn-area">
|
|
<span className="tb_ico change_check"></span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div className="form-flex-wrap">
|
|
<div className="name">{item?.itemNo}</div>
|
|
<div className="icon-wrap">
|
|
{item?.fileUploadFlg === '1' && <span className="tb_ico file_check"></span>}
|
|
{item?.specialNoteCd && (
|
|
<button
|
|
type="button"
|
|
className="grid-tip"
|
|
onClick={() => {
|
|
setProductFeaturesPopupOpen(true)
|
|
setShowProductFeatureData(item?.specialNoteCd)
|
|
}}
|
|
></button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div className="input-wrap" style={{ width: '100%' }}>
|
|
<input type="text" className="input-light al-r" defaultValue={item?.amount} />
|
|
</div>
|
|
</td>
|
|
<td>{item.unit}</td>
|
|
<td>
|
|
<div className="form-flex-wrap">
|
|
<div className="input-wrap mr5">
|
|
<input type="text" className="input-light al-r" defaultValue={convertNumberToPriceDecimal(item?.salePrice)} />
|
|
</div>
|
|
{/* <div className="btn-area">
|
|
<span className="tb_ico open_check">OPEN아이콘 처리</span>
|
|
</div> */}
|
|
</div>
|
|
</td>
|
|
<td className="al-r">{convertNumberToPriceDecimal(item?.saleTotPrice)}</td>
|
|
</tr>
|
|
)
|
|
})}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{/* html테이블끝 */}
|
|
</div>
|
|
</div>
|
|
{/* 기본정보끝 */}
|
|
</div>
|
|
{productFeaturesPopupOpen && (
|
|
<ProductFeaturesPop
|
|
specialNoteList={specialNoteList}
|
|
showProductFeatureData={showProductFeatureData}
|
|
setProductFeaturesPopupOpen={setProductFeaturesPopupOpen}
|
|
/>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|