Merge branch 'dev' into dev-yj
This commit is contained in:
commit
40787942f9
@ -20,6 +20,7 @@ import ProductFeaturesPop from './popup/ProductFeaturesPop'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
export default function Estimate({ params }) {
|
||||
const fixedKey = 'itemKey'
|
||||
const [itemChangeYn, setItemChangeYn] = useState(false)
|
||||
const { session } = useContext(SessionContext)
|
||||
const [objectNo, setObjectNo] = useState('') //물건번호
|
||||
@ -28,6 +29,8 @@ export default function Estimate({ params }) {
|
||||
const [files, setFiles] = useState([]) // 보내는 첨부파일
|
||||
const [originFiles, setOriginFiles] = useState([]) //기존 첨부파일
|
||||
|
||||
const [showPriceCd, setShowPriceCd] = useState('')
|
||||
|
||||
const [showContentCode, setShowContentCode] = useState('ATTR001')
|
||||
|
||||
const [productFeaturesPopupOpen, setProductFeaturesPopupOpen] = useState(false) //견적특이사항 팝업
|
||||
@ -46,8 +49,6 @@ export default function Estimate({ params }) {
|
||||
|
||||
const [storePriceList, setStorePriceList] = useState([]) //가격표시 option
|
||||
|
||||
const [tempPriceCd, setTempPriceCd] = useState('')
|
||||
|
||||
const [startDate, setStartDate] = useState(new Date())
|
||||
const singleDatePickerProps = {
|
||||
startDate,
|
||||
@ -182,7 +183,7 @@ export default function Estimate({ params }) {
|
||||
})
|
||||
}
|
||||
|
||||
//가격표시 option 최초세팅
|
||||
//가격표시 option 목록 최초세팅 && 주문분류 변경시
|
||||
useEffect(() => {
|
||||
if (state.estimateType !== '') {
|
||||
const param = {
|
||||
@ -200,23 +201,35 @@ export default function Estimate({ params }) {
|
||||
}
|
||||
}, [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)
|
||||
}
|
||||
})
|
||||
if (state?.priceCd) {
|
||||
setShowPriceCd(state.priceCd)
|
||||
}
|
||||
}, [tempPriceCd])
|
||||
}, [state?.priceCd])
|
||||
|
||||
//가격 표시 option 변경 이벤트
|
||||
const onChangeStorePriceList = (priceCd) => {
|
||||
const param = {
|
||||
saleStoreId: session.storeId,
|
||||
sapSalesStoreCd: session.custCd,
|
||||
docTpCd: priceCd,
|
||||
}
|
||||
|
||||
//가격표시 바꾸만헀을때는 tempPriceCd에 바꾼값 관리 불필요?
|
||||
//프라이싱 했을때 priceCd setState
|
||||
//화면에 보여지는 값은 showPriceCd로 관리
|
||||
setShowPriceCd(priceCd)
|
||||
//setState({
|
||||
// tempPriceCd: priceCd,
|
||||
//})
|
||||
|
||||
const apiUrl = `/api/estimate/price/store-price-list?${queryStringFormatter(param)}`
|
||||
get({ url: apiUrl }).then((res) => {
|
||||
if (isNotEmptyArray(res?.data)) {
|
||||
setStorePriceList(res.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Pricing 버튼
|
||||
const handlePricing = async (priceCd) => {
|
||||
@ -224,24 +237,55 @@ export default function Estimate({ params }) {
|
||||
saleStoreId: session.storeId,
|
||||
sapSalesStoreCd: session.custCd,
|
||||
docTpCd: state.estimateType,
|
||||
priceCd: session.storeLvl === '1' ? tempPriceCd : priceCd,
|
||||
itemIdList: state.itemList, //아이템 최초정보로 호출
|
||||
priceCd: priceCd,
|
||||
//itemIdList: state.itemList, //아이템 최초정보로 호출 delFlg 0인거만..
|
||||
itemIdList: state.itemList.filter((item) => item.delFlg === '0'),
|
||||
}
|
||||
|
||||
if (param.itemIdList.length > 0) {
|
||||
let pass = true
|
||||
|
||||
param.itemIdList.map((item) => {
|
||||
if (item.itemId === '') {
|
||||
pass = false
|
||||
}
|
||||
})
|
||||
|
||||
if (!pass) {
|
||||
//Pricing이 누락된 아이템이 있습니다. Pricing을 진행해주세요.
|
||||
return alert(getMessage('estimate.detail.showPrice.pricingBtn.noItemId'))
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('프라이싱파람::', param)
|
||||
await promisePost({ url: '/api/estimate/price/item-price-list', data: param }).then((res) => {
|
||||
let updateList = []
|
||||
if (res) {
|
||||
if (res.status === 200) {
|
||||
const data = res.data
|
||||
//기존itemList랑 프라이싱결과랑 비교해서 단가만 업뎃 서로 갯수가 안맞을 수 있음 없는 itemId면 unitPrice 0으로
|
||||
//itemId로 비교해서 단가정보만 업데이트
|
||||
if (data.result.code === 200) {
|
||||
if (isNotEmptyArray(data.data2)) {
|
||||
//아이템쪽 다 새로고침............
|
||||
//성공후..
|
||||
//기존itemList랑 프라이싱결과랑 비교해서 단가만 업뎃 서로 갯수가 안맞을 수 있음 없는 itemId면 unitPrice 0으로
|
||||
//itemId로 비교해서 단가정보만 업데이트
|
||||
setState({
|
||||
priceCd: session.storeLvl === '1' ? tempPriceCd : priceCd,
|
||||
state.itemList.map((item) => {
|
||||
let checkYn = false
|
||||
data.data2.map((item2) => {
|
||||
if (item2.itemId === item.itemId) {
|
||||
updateList.push({ ...item, unitPrice: item2.unitPrice })
|
||||
checkYn = true
|
||||
}
|
||||
})
|
||||
|
||||
if (!checkYn) {
|
||||
updateList.push({ ...item, unitPrice: '0' })
|
||||
}
|
||||
})
|
||||
|
||||
setState({
|
||||
priceCd: priceCd,
|
||||
itemList: updateList,
|
||||
})
|
||||
|
||||
setItemChangeYn(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,8 +305,71 @@ export default function Estimate({ params }) {
|
||||
setSelection(newSelection)
|
||||
}
|
||||
|
||||
// 수량 변경
|
||||
const onChangeAmount = (value, dispOrder, index) => {
|
||||
//itemChangeFlg = 1, partAdd = 0 셋팅
|
||||
let amount = value
|
||||
amount = Number(value.replace(/[^0-9]/g, '').replaceAll(',', ''))
|
||||
if (isNaN(amount)) {
|
||||
amount = 0
|
||||
} else {
|
||||
amount = amount.toLocaleString()
|
||||
}
|
||||
|
||||
let updateList = []
|
||||
let updates = {}
|
||||
updates.amount = amount
|
||||
updates.itemChangeFlg = '1'
|
||||
updates.partAdd = '0'
|
||||
updates.saleTotPrice = (Number(amount.replaceAll(',', '')) * state.itemList[index].salePrice.replaceAll(',', '')).toLocaleString()
|
||||
|
||||
updateList = state.itemList.map((item) => {
|
||||
if (item.dispOrder === dispOrder) {
|
||||
return { ...item, ...updates }
|
||||
} else {
|
||||
return item
|
||||
}
|
||||
})
|
||||
|
||||
setState({
|
||||
itemList: updateList,
|
||||
})
|
||||
|
||||
setItemChangeYn(true)
|
||||
}
|
||||
|
||||
// 단가 변경
|
||||
const onChangeSalePrice = (value, dispOrder, index) => {
|
||||
//itemChangeFlg, partAdd 받아온 그대로
|
||||
let salePrice
|
||||
salePrice = Number(value.replace(/[^0-9]/g, '').replaceAll(',', ''))
|
||||
if (isNaN(salePrice)) {
|
||||
salePrice = 0
|
||||
} else {
|
||||
salePrice = salePrice.toLocaleString()
|
||||
}
|
||||
let updateList = []
|
||||
let updates = {}
|
||||
updates.salePrice = salePrice
|
||||
updates.saleTotPrice = (Number(salePrice.replaceAll(',', '')) * state.itemList[index].amount.replaceAll(',', '')).toLocaleString()
|
||||
|
||||
updateList = state.itemList.map((item) => {
|
||||
if (item.dispOrder === dispOrder) {
|
||||
return { ...item, ...updates }
|
||||
} else {
|
||||
return item
|
||||
}
|
||||
})
|
||||
|
||||
setState({
|
||||
itemList: updateList,
|
||||
})
|
||||
|
||||
setItemChangeYn(true)
|
||||
}
|
||||
|
||||
// 아이템 자동완성 검색시 아이템 변경
|
||||
const onChangeDisplayItem = (itemId, dispOrder) => {
|
||||
const onChangeDisplayItem = (itemId, dispOrder, index) => {
|
||||
const param = {
|
||||
itemId: itemId,
|
||||
}
|
||||
@ -290,17 +397,37 @@ export default function Estimate({ params }) {
|
||||
updates.specialNoteCd = res.spnAttrCds
|
||||
updates.itemGroup = res.itemGroup
|
||||
updates.delFlg = '0' // 삭제플래그 0
|
||||
updates.saleTotPrice = res.salePrice * state.itemList[index].amount
|
||||
//104671
|
||||
let bomList = res.itemBomList
|
||||
|
||||
updateList = state.itemList.map((item) => {
|
||||
if (item.dispOrder === dispOrder) {
|
||||
return { ...item, ...updates }
|
||||
} else if (item.paDispOrder === dispOrder) {
|
||||
return { ...item, delFlg: '1' }
|
||||
} else {
|
||||
return item
|
||||
}
|
||||
})
|
||||
setState({
|
||||
itemList: updateList,
|
||||
})
|
||||
//paDispOrder
|
||||
if (bomList) {
|
||||
bomList.map((bomItem, index) => {
|
||||
let newItemDispOrder = Math.max(...state.itemList.map((item) => item.dispOrder))
|
||||
bomItem.dispOrder = index + 1 + newItemDispOrder
|
||||
bomItem.delFlg = '0'
|
||||
bomItem.objectNo = objectNo
|
||||
bomItem.planNo = planNo
|
||||
})
|
||||
|
||||
setState({
|
||||
itemList: [...updateList, ...bomList],
|
||||
})
|
||||
} else {
|
||||
setState({
|
||||
itemList: updateList,
|
||||
})
|
||||
}
|
||||
|
||||
setItemChangeYn(true)
|
||||
})
|
||||
@ -315,17 +442,31 @@ export default function Estimate({ params }) {
|
||||
if (row2 === row.dispOrder) {
|
||||
delList.push({ ...row })
|
||||
}
|
||||
if (row2 === row.paDispOrder) {
|
||||
delList.push({ ...row })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const updateList = state.itemList.map((item) => {
|
||||
const isDeleted = delList.some((row) => item.dispOrder === row.dispOrder)
|
||||
const isDeleted = delList.some((row) => item.delFlg === '1' || item.dispOrder === row.dispOrder)
|
||||
return {
|
||||
...item,
|
||||
delFlg: isDeleted ? '1' : '0',
|
||||
}
|
||||
})
|
||||
|
||||
let delCnt = 0
|
||||
updateList.map((item) => {
|
||||
if (item.delFlg === '1') {
|
||||
delCnt++
|
||||
}
|
||||
})
|
||||
|
||||
if (delCnt === updateList.length) {
|
||||
return alert(getMessage('estimate.detail.save.requiredItem'))
|
||||
}
|
||||
|
||||
setState({
|
||||
itemList: updateList,
|
||||
})
|
||||
@ -336,12 +477,30 @@ export default function Estimate({ params }) {
|
||||
|
||||
useEffect(() => {
|
||||
if (itemChangeYn) {
|
||||
console.log('아이템에 뭔가 변화가 일어났어', itemChangeYn)
|
||||
console.log('아이템상태가져오기::::::::::', state.itemList)
|
||||
}
|
||||
// console.log('아이템 상태 가져오기::::::::::', state.itemList)
|
||||
// console.log('토탈쪽 셋팅해주기위한 함수::::::', itemList)
|
||||
//delFlg 0인거 중에..
|
||||
//수량(PCS) : totAmount
|
||||
//용량( Kw) : totVolKw
|
||||
//공급가액 : supplyPrice
|
||||
//부가세(10%) : vatPrice
|
||||
//총액 :totPrice
|
||||
|
||||
//다시 false로 돌리기 여기서할지 가격정보 변경하는거 끝나고할지..
|
||||
setItemChangeYn(false)
|
||||
let totAmount = 0
|
||||
let amount = 0
|
||||
state.itemList.map((item) => {
|
||||
if (item.delFlg === '0') {
|
||||
amount = item.amount.replace(/[^0-9]/g, '').replaceAll(',', '')
|
||||
totAmount += Number(amount)
|
||||
}
|
||||
})
|
||||
|
||||
setState({
|
||||
totAmount: totAmount,
|
||||
})
|
||||
|
||||
setItemChangeYn(false)
|
||||
}
|
||||
}, [itemChangeYn])
|
||||
|
||||
return (
|
||||
@ -534,10 +693,10 @@ export default function Estimate({ params }) {
|
||||
<>
|
||||
<div className={`form-flex-wrap ${style}`} key={uuidv4()}>
|
||||
<div className="input-wrap mr5" style={{ width: '610px' }} key={`roof${index}`}>
|
||||
<input type="text" className="input-light" defaultValue={roofList} readOnly />
|
||||
<input type="text" className="input-light" value={roofList} readOnly />
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" className="input-light" defaultValue={constructSpecificationMulti[index]} readOnly />
|
||||
<input type="text" className="input-light" value={constructSpecificationMulti[index]} readOnly />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@ -778,8 +937,9 @@ export default function Estimate({ params }) {
|
||||
key={uuidv4()}
|
||||
className="select-light"
|
||||
onChange={(e) => {
|
||||
setTempPriceCd(e.target.value)
|
||||
onChangeStorePriceList(e.target.value)
|
||||
}}
|
||||
value={showPriceCd}
|
||||
>
|
||||
{storePriceList.length > 0 && storePriceList.map((row) => <option value={row.priceCd}>{row.priceNm}</option>)}
|
||||
</select>
|
||||
@ -790,9 +950,10 @@ export default function Estimate({ params }) {
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey ml5"
|
||||
onClick={() => {
|
||||
handlePricing(state.priceCd)
|
||||
handlePricing(state?.priceCd)
|
||||
}}
|
||||
>
|
||||
{getMessage('estimate.detail.showPrice.pricingBtn')}
|
||||
@ -818,7 +979,15 @@ export default function Estimate({ params }) {
|
||||
</li>
|
||||
</ul>
|
||||
<div className="product-edit-btn">
|
||||
<button className="btn-origin navy mr5" type="button" onClick={addItem}>
|
||||
{/* <button className="btn-origin navy mr5" type="button" onClick={addItem}> */}
|
||||
<button
|
||||
className="btn-origin navy mr5"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
addItem()
|
||||
// setItemChangeYn(true)
|
||||
}}
|
||||
>
|
||||
<span className="plus"></span>
|
||||
{getMessage('estimate.detail.showPrice.addItem')}
|
||||
</button>
|
||||
@ -863,107 +1032,123 @@ export default function Estimate({ params }) {
|
||||
<tbody>
|
||||
{state?.itemList.length > 0 &&
|
||||
state.itemList.map((item, index) => {
|
||||
return (
|
||||
<tr key={uuidv4()}>
|
||||
<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) => {
|
||||
if (isObjectNotEmpty(e)) {
|
||||
onChangeDisplayItem(e.itemId, item.dispOrder)
|
||||
}
|
||||
}}
|
||||
getOptionLabel={(x) => x.itemName}
|
||||
getOptionValue={(x) => x.itemId}
|
||||
isClearable={true}
|
||||
isDisabled={false}
|
||||
value={displayItemList.filter(function (option) {
|
||||
return option.itemId === item.itemId
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
{/* {item?.partAdd === '1' && ( */}
|
||||
{item?.itemChangeFlg === '1' && (
|
||||
<div className="btn-area">
|
||||
<span className="tb_ico change_check"></span>
|
||||
if (item.delFlg === '0') {
|
||||
return (
|
||||
<>
|
||||
<tr key={fixedKey}>
|
||||
<td className="al-c">
|
||||
<div className="d-check-box light no-text">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={item?.dispOrder}
|
||||
disabled={item?.paDispOrder ? true : false}
|
||||
onChange={() => onChangeSelect(item.dispOrder)}
|
||||
checked={selection.has(item.dispOrder) ? true : false}
|
||||
/>
|
||||
<label htmlFor={item?.dispOrder}></label>
|
||||
</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)
|
||||
</td>
|
||||
<td className="al-r">{item?.dispOrder}</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) => {
|
||||
if (isObjectNotEmpty(e)) {
|
||||
onChangeDisplayItem(e.itemId, item.dispOrder, index)
|
||||
}
|
||||
}}
|
||||
getOptionLabel={(x) => x.itemName}
|
||||
getOptionValue={(x) => x.itemId}
|
||||
isClearable={false}
|
||||
isDisabled={item?.paDispOrder ? true : false}
|
||||
value={displayItemList.filter(function (option) {
|
||||
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"
|
||||
value={item?.amount}
|
||||
disabled={item.itemId === '' ? true : item?.paDispOrder ? true : false}
|
||||
onChange={(e) => {
|
||||
onChangeAmount(e.target.value, item.dispOrder, index)
|
||||
}}
|
||||
></button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '100%' }}>
|
||||
<input
|
||||
type="text"
|
||||
className="input-light al-r"
|
||||
defaultValue={convertNumberToPriceDecimal(item?.amount)}
|
||||
onChange={(e) => {
|
||||
//onChangeDisplayItem참고
|
||||
//itemChangeFlg = 1, partAdd = 0 셋팅
|
||||
console.log('수량변경::::::::', e.target.value)
|
||||
}}
|
||||
/>
|
||||
</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"
|
||||
value={convertNumberToPriceDecimal(item?.salePrice)}
|
||||
onChange={(e) => {
|
||||
//onChangeDisplayItem참고
|
||||
//itemChangeFlg, partAdd 받아온 그대로
|
||||
console.log('단가변경:::::::', e.target.value)
|
||||
}}
|
||||
/>
|
||||
</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>
|
||||
)
|
||||
/>
|
||||
</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"
|
||||
value={item?.salePrice}
|
||||
disabled={
|
||||
state?.estimateType === 'YJSS'
|
||||
? item?.paDispOrder
|
||||
? true
|
||||
: item.pkgMaterialFlg === '1'
|
||||
? false
|
||||
: true
|
||||
: item.itemId === ''
|
||||
? true
|
||||
: item?.paDispOrder
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onChange={(e) => {
|
||||
onChangeSalePrice(e.target.value, item.dispOrder, index)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/* <div className="btn-area">
|
||||
<span className="tb_ico open_check">OPEN아이콘 처리</span>
|
||||
</div> */}
|
||||
</div>
|
||||
</td>
|
||||
<td className="al-r">{item?.saleTotPrice}</td>
|
||||
</tr>
|
||||
</>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@ -6,36 +6,74 @@ import { useRecoilValue } from 'recoil'
|
||||
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||
|
||||
export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
|
||||
// console.log('플랜번호::::::::::::', planNo)
|
||||
const { getMessage } = useMessage()
|
||||
const { promiseGet } = useAxios()
|
||||
const { promisePost } = useAxios()
|
||||
|
||||
//EXCEL, PDF 구분
|
||||
const [schDownload, setSchDownload] = useState('EXCEL')
|
||||
//다운로드 파일 EXCEL
|
||||
const [schUnitPriceFlg, setSchUnitPriceFlg] = useState('0')
|
||||
|
||||
//견적제출서 표시명
|
||||
const [schDisplayFlg, setSchSchDisplayFlg] = useState('0')
|
||||
//가대 중량표 포함
|
||||
const [schWeightFlg, setSchWeightFlg] = useState('0')
|
||||
//도면/시뮬레이션 파일 포함
|
||||
const [schDrawingFlg, setSchDrawingFlg] = useState('0')
|
||||
//가대 중량표 포함(포함:1 미포함 : 0)
|
||||
const [schWeightFlg, setSchWeightFlg] = useState('1')
|
||||
//도면/시뮬레이션 파일 포함(포함:1 미포함 : 0)
|
||||
const [schDrawingFlg, setSchDrawingFlg] = useState('1')
|
||||
|
||||
// recoil 물건번호
|
||||
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
||||
|
||||
//문서 다운로드
|
||||
const handleFileDown = async () => {
|
||||
// console.log('물건번호:::', objectRecoil.floorPlanObjectNo)
|
||||
// console.log('planNo::', planNo)
|
||||
// 고른 옵션값들
|
||||
//0 : 견적가 Excel 1 : 정가용Excel 2: 견적가 PDF 3 :정가용PDF
|
||||
// console.log(schUnitPriceFlg)
|
||||
// console.log(schDisplayFlg)
|
||||
// console.log(schWeightFlg)
|
||||
// console.log(schDrawingFlg)
|
||||
const url = '/api/estimate/excel-download'
|
||||
const params = {}
|
||||
let sendUnitPriceFlg
|
||||
if (schUnitPriceFlg === '0') {
|
||||
sendUnitPriceFlg = '0'
|
||||
} else if (schUnitPriceFlg === '1') {
|
||||
sendUnitPriceFlg = '1'
|
||||
} else if (schUnitPriceFlg === '2') {
|
||||
sendUnitPriceFlg = '0'
|
||||
} else {
|
||||
sendUnitPriceFlg = '1'
|
||||
}
|
||||
|
||||
const params = {
|
||||
objectNo: objectRecoil.floorPlanObjectNo,
|
||||
planNo: planNo,
|
||||
schDownload: schDownload,
|
||||
schUnitPriceFlg: sendUnitPriceFlg,
|
||||
schDisplayFlg: schDisplayFlg,
|
||||
schWeightFlg: schWeightFlg,
|
||||
schDrawingFlg: schDrawingFlg,
|
||||
}
|
||||
const options = { responseType: 'blob' }
|
||||
await promisePost({ url: url, data: params, option: options })
|
||||
.then((resultData) => {
|
||||
if (resultData) {
|
||||
let fileName = 'unknow'
|
||||
const blob = new Blob([resultData.data], { type: resultData.headers['content-type'] || 'application/octet-stream' })
|
||||
const fileUrl = window.URL.createObjectURL(blob)
|
||||
|
||||
const link = document.createElement('a')
|
||||
link.href = fileUrl
|
||||
|
||||
//서버에서 내려오는 파일명
|
||||
const contentDisposition = resultData.headers['content-disposition']
|
||||
if (contentDisposition) {
|
||||
fileName = contentDisposition.split('filename=')[1].replace(/['"]/g, '')
|
||||
}
|
||||
|
||||
link.download = fileName
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
link.remove()
|
||||
window.URL.revokeObjectURL(fileUrl)
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('::FileDownLoad Error::', error)
|
||||
alert('File does not exist.')
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
@ -74,28 +112,30 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
|
||||
<div className="d-check-radio light mr10">
|
||||
<input
|
||||
type="radio"
|
||||
id="schUnitPriceFlg0"
|
||||
id="schUnitPriceExcelFlg0"
|
||||
name="schUnitPriceFlg"
|
||||
value={'0'}
|
||||
checked={schUnitPriceFlg === '0'}
|
||||
onChange={(e) => {
|
||||
setSchDownload('EXCEL')
|
||||
setSchUnitPriceFlg(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="schUnitPriceFlg0">{getMessage('estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg0')}</label>
|
||||
<label htmlFor="schUnitPriceExcelFlg0">{getMessage('estimate.detail.docPopup.schUnitPriceFlg.excelFlg0')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light mr10">
|
||||
<input
|
||||
type="radio"
|
||||
id="schUnitPriceFlg1"
|
||||
id="schUnitPriceExcelFlg1"
|
||||
name="schUnitPriceFlg"
|
||||
value={'1'}
|
||||
checked={schUnitPriceFlg === '1'}
|
||||
onChange={(e) => {
|
||||
setSchDownload('EXCEL')
|
||||
setSchUnitPriceFlg(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="schUnitPriceFlg1">{getMessage('estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg1')}</label>
|
||||
<label htmlFor="schUnitPriceExcelFlg1">{getMessage('estimate.detail.docPopup.schUnitPriceFlg.excelFlg1')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light mr10">
|
||||
<input
|
||||
@ -105,10 +145,11 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
|
||||
value={'2'}
|
||||
checked={schUnitPriceFlg === '2'}
|
||||
onChange={(e) => {
|
||||
setSchDownload('PDF')
|
||||
setSchUnitPriceFlg(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="schUnitPricePdfFlg0">{getMessage('estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg2')}</label>
|
||||
<label htmlFor="schUnitPricePdfFlg0">{getMessage('estimate.detail.docPopup.schUnitPriceFlg.pdfFlg0')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light ">
|
||||
<input
|
||||
@ -118,10 +159,11 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
|
||||
value={'3'}
|
||||
checked={schUnitPriceFlg === '3'}
|
||||
onChange={(e) => {
|
||||
setSchDownload('PDF')
|
||||
setSchUnitPriceFlg(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="schUnitPricePdfFlg1">{getMessage('estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg3')}</label>
|
||||
<label htmlFor="schUnitPricePdfFlg1">{getMessage('estimate.detail.docPopup.schUnitPriceFlg.pdfFlg1')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@ -168,19 +210,6 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
|
||||
<td>
|
||||
<div className="form-flex-wrap">
|
||||
<div className="d-check-radio light mr10">
|
||||
<input
|
||||
type="radio"
|
||||
name="schWeightFlg"
|
||||
id="schWeightFlg0"
|
||||
value={'0'}
|
||||
checked={schWeightFlg === '0'}
|
||||
onChange={(e) => {
|
||||
setSchWeightFlg(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="schWeightFlg0">{getMessage('estimate.detail.docPopup.schWeightFlg.schWeightFlg0')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light">
|
||||
<input
|
||||
type="radio"
|
||||
name="schWeightFlg"
|
||||
@ -193,6 +222,19 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
|
||||
/>
|
||||
<label htmlFor="schWeightFlg1">{getMessage('estimate.detail.docPopup.schWeightFlg.schWeightFlg1')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light">
|
||||
<input
|
||||
type="radio"
|
||||
name="schWeightFlg"
|
||||
id="schWeightFlg0"
|
||||
value={'0'}
|
||||
checked={schWeightFlg === '0'}
|
||||
onChange={(e) => {
|
||||
setSchWeightFlg(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="schWeightFlg0">{getMessage('estimate.detail.docPopup.schWeightFlg.schWeightFlg0')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -201,6 +243,19 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
|
||||
<td>
|
||||
<div className="form-flex-wrap">
|
||||
<div className="d-check-radio light mr10">
|
||||
<input
|
||||
type="radio"
|
||||
name="schDrawingFlg"
|
||||
id="schDrawingFlg1"
|
||||
value={'1'}
|
||||
checked={schDrawingFlg === '1'}
|
||||
onChange={(e) => {
|
||||
setSchDrawingFlg(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="schDrawingFlg1">{getMessage('estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light">
|
||||
<input
|
||||
type="radio"
|
||||
name="schDrawingFlg"
|
||||
@ -213,19 +268,6 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) {
|
||||
/>
|
||||
<label htmlFor="schDrawingFlg0">{getMessage('estimate.detail.docPopup.schDrawingFlg.schDrawingFlg0')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio light">
|
||||
<input
|
||||
type="radio"
|
||||
name="schDrawingFlg"
|
||||
id="schDrawingFlg01"
|
||||
value={'1'}
|
||||
checked={schDrawingFlg === '1'}
|
||||
onChange={(e) => {
|
||||
setSchDrawingFlg(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="schDrawingFlg01">{getMessage('estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -184,7 +184,7 @@ export default function CanvasMenu(props) {
|
||||
}, [type, globalLocale])
|
||||
|
||||
useEffect(() => {
|
||||
if (['2', '3'].includes(canvasSetting?.roofSizeSet?.toString())) {
|
||||
if ([2, 3].some((num) => num === canvasSetting?.roofSizeSet)) {
|
||||
setMenuNumber(3)
|
||||
setType('surface')
|
||||
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
||||
@ -195,8 +195,12 @@ export default function CanvasMenu(props) {
|
||||
}
|
||||
}, [canvasSetting])
|
||||
|
||||
const checkMenuState = (menu) => {
|
||||
return ([2, 3].some((num) => num === canvasSetting?.roofSizeSet) && menu.index === 2) || (menuNumber === 4 && menu.index === 2)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||
<div className={`canvas-menu-wrap ${[2, 3, 4].some((num) => num === menuNumber) ? 'active' : ''}`}>
|
||||
<div className="canvas-menu-inner">
|
||||
<ul className="canvas-menu-list">
|
||||
{canvasMenus.map((menu) => {
|
||||
@ -205,11 +209,12 @@ export default function CanvasMenu(props) {
|
||||
key={`canvas-menu-${menu.index}`}
|
||||
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
if (['2', '3'].includes(canvasSetting?.roofSizeSet?.toString()) && menu.index === 2) return
|
||||
if ([2, 3].some((num) => num === canvasSetting?.roofSizeSet) && menu.index === 2) return
|
||||
if (menuNumber === 4 && menu.index === 2) return
|
||||
onClickNav(menu)
|
||||
}}
|
||||
>
|
||||
<button className={['2', '3'].includes(canvasSetting?.roofSizeSet?.toString()) && menu.index === 2 ? 'no-click' : ''}>
|
||||
<button className={checkMenuState(menu) ? 'no-click' : ''}>
|
||||
<span className={`menu-icon ${menu.icon}`}></span>
|
||||
{getMessage(menu.name)}
|
||||
</button>
|
||||
@ -218,7 +223,7 @@ export default function CanvasMenu(props) {
|
||||
})}
|
||||
</ul>
|
||||
<div className="canvas-side-btn-wrap">
|
||||
{menuNumber !== 6 && menuNumber !== 5 && (
|
||||
{![5, 6].some((num) => num === menuNumber) && (
|
||||
<>
|
||||
{
|
||||
<div className={`vertical-horizontal ${verticalHorizontalMode ? 'on' : ''}`}>
|
||||
@ -248,7 +253,7 @@ export default function CanvasMenu(props) {
|
||||
handleZoom(false)
|
||||
}}
|
||||
></button>
|
||||
<span>{canvasZoom}%</span>
|
||||
<span onClick={handleZoomClear}>{canvasZoom}%</span>
|
||||
<button
|
||||
className="control-btn plus"
|
||||
onClick={() => {
|
||||
@ -314,8 +319,8 @@ export default function CanvasMenu(props) {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`canvas-depth2-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||
{(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && <MenuDepth01 />}
|
||||
<div className={`canvas-depth2-wrap ${[2, 3, 4].some((num) => num === menuNumber) ? 'active' : ''}`}>
|
||||
{[2, 3, 4].some((num) => num === menuNumber) && <MenuDepth01 />}
|
||||
</div>
|
||||
{/* 견적서(menuNumber=== 5) 상세화면인경우 문서다운로드 팝업 */}
|
||||
{estimatePopupOpen && <DocDownOptionPop planNo={estimateRecoilState?.planNo} setEstimatePopupOpen={setEstimatePopupOpen} />}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useOrientation } from '@/hooks/popup/useOrientation'
|
||||
import { useOrientation } from '@/hooks/module/useOrientation'
|
||||
import { getDegreeInOrientation } from '@/util/canvas-util'
|
||||
|
||||
export const Orientation = forwardRef(({ tabNum }, ref) => {
|
||||
|
||||
@ -6,7 +6,7 @@ import { contextPopupPositionState } from '@/store/popupAtom'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||
import { FLOW_DIRECTION_TYPE, useFlowDirectionSetting } from '@/hooks/popup/useFlowDirectionSetting'
|
||||
import { FLOW_DIRECTION_TYPE, useFlowDirectionSetting } from '@/hooks/contextpopup/useFlowDirectionSetting'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
export default function FlowDirectionSetting(props) {
|
||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||
import { useState } from 'react'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
|
||||
export default function ImageSizeSetting(props) {
|
||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||
const { id, pos = contextPopupPosition, size, setSize } = props
|
||||
const [sizeValue, setSizeValue] = useState(100)
|
||||
const { getMessage } = useMessage()
|
||||
const { closePopup } = usePopup()
|
||||
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xxxm mount`}>
|
||||
<div className="modal-head">
|
||||
<h1 className="title">{getMessage('modal.image.size.setting')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="range-wrap">
|
||||
<input
|
||||
type="range"
|
||||
id="size"
|
||||
name="volume"
|
||||
min="20"
|
||||
max="200"
|
||||
step={10}
|
||||
value={sizeValue}
|
||||
onChange={(e) => setSizeValue(e.target.value)}
|
||||
/>
|
||||
<label htmlFor="size">{sizeValue}%</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
}
|
||||
@ -12,7 +12,6 @@ import { usePopup } from '@/hooks/usePopup'
|
||||
import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide'
|
||||
import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide'
|
||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
|
||||
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) {
|
||||
const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요
|
||||
|
||||
@ -4,7 +4,7 @@ import { Fragment, useCallback, useEffect, useState } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||
import { dimmedStore, sessionStore } from '@/store/commonAtom'
|
||||
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
@ -16,6 +16,8 @@ import UserInfoModal from '@/components/myInfo/UserInfoModal'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
|
||||
import { stuffSearchState } from '@/store/stuffAtom'
|
||||
|
||||
export const ToggleonMouse = (e, act, target) => {
|
||||
const listWrap = e.target.closest(target)
|
||||
const ListItem = Array.from(listWrap.childNodes)
|
||||
@ -34,6 +36,8 @@ export const ToggleonMouse = (e, act, target) => {
|
||||
export default function Header(props) {
|
||||
const [userInfoModal, setUserInfoModal] = useState(false)
|
||||
|
||||
const resetStuffRecoil = useResetRecoilState(stuffSearchState)
|
||||
|
||||
const { userSession } = props
|
||||
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
||||
const { getMessage } = useMessage()
|
||||
@ -184,7 +188,14 @@ export default function Header(props) {
|
||||
{userInfoModal && <UserInfoModal userId={sessionState.userId} userInfoModal={userInfoModal} setUserInfoModal={setUserInfoModal} />}
|
||||
</div>
|
||||
<div className="sign-out-box">
|
||||
<button className="sign-out" onClick={() => logout()}>
|
||||
<button
|
||||
className="sign-out"
|
||||
onClick={() => {
|
||||
//리코일은 새로고침 하지 않으면 남아있어서 로그아웃해도 남아있음..
|
||||
resetStuffRecoil()
|
||||
logout()
|
||||
}}
|
||||
>
|
||||
{getMessage('header.logout')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -39,9 +39,9 @@ export default function Stuff() {
|
||||
const copyNo = async (value) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(value)
|
||||
alert(getMessage('stuff.detail.header.message2'))
|
||||
alert(getMessage('stuff.detail.header.successCopy'))
|
||||
} catch (error) {
|
||||
alert(getMessage('stuff.detail.header.message3'))
|
||||
alert(getMessage('stuff.detail.header.failCopy'))
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,6 +209,7 @@ export default function Stuff() {
|
||||
endRow: pageNo * pageSize,
|
||||
schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId ? stuffSearchParams.schOtherSelSaleStoreId : stuffSearchParams.schSelSaleStoreId,
|
||||
schSortType: 'R',
|
||||
code: 'S',
|
||||
}
|
||||
setStuffSearch({
|
||||
...params,
|
||||
|
||||
@ -19,10 +19,15 @@ import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import StuffPlanQGrid from './StuffPlanQGrid'
|
||||
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||
import { ManagementContext } from '@/app/management/ManagementProvider'
|
||||
import DocDownOptionPop from '../estimate/popup/DocDownOptionPop'
|
||||
|
||||
export default function StuffDetail() {
|
||||
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) //견적서 화면용 물건번호리코일
|
||||
|
||||
const [estimatePopupOpen, setEstimatePopupOpen] = useState(false)
|
||||
|
||||
const [popPlanNo, setPopPlanNo] = useState('1') //default 1
|
||||
|
||||
//공통코드
|
||||
const { commonCode, findCommonCode } = useCommonCode()
|
||||
const [selOptions, setSelOptions] = useState('') //선택한 1차점
|
||||
@ -266,11 +271,12 @@ export default function StuffDetail() {
|
||||
type="button"
|
||||
className="grid-btn"
|
||||
onClick={() => {
|
||||
console.log('엑셀버튼클릭')
|
||||
setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo })
|
||||
handleEstimatePopup(params.data.planNo)
|
||||
}}
|
||||
>
|
||||
<span className="excel"></span>
|
||||
{getMessage('stuff.detail.planGrid.btn2')}
|
||||
{getMessage('stuff.detail.planGrid.docDownload')}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
@ -280,6 +286,12 @@ export default function StuffDetail() {
|
||||
],
|
||||
})
|
||||
|
||||
// 문서다운로드 팝업 오픈 셋팅
|
||||
const handleEstimatePopup = (planNo) => {
|
||||
setPopPlanNo(planNo)
|
||||
setEstimatePopupOpen(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (objectNo) {
|
||||
setEditMode('EDIT')
|
||||
@ -289,10 +301,12 @@ export default function StuffDetail() {
|
||||
}
|
||||
promiseGet({ url: `/api/object/${objectNo}/detail` }).then((res) => {
|
||||
if (res.status === 200) {
|
||||
if (res.data != null) {
|
||||
if (isObjectNotEmpty(res.data)) {
|
||||
setManagementState(res.data)
|
||||
} else {
|
||||
setManagementState({})
|
||||
alert(getMessage('stuff.detail.header.notExistObjectNo'))
|
||||
router.push('/management/stuff')
|
||||
}
|
||||
if (isNotEmptyArray(res.data.planList)) {
|
||||
setPlanGridProps({ ...planGridProps, planGridData: res.data.planList })
|
||||
@ -302,6 +316,9 @@ export default function StuffDetail() {
|
||||
} else {
|
||||
setManagementState({})
|
||||
setPlanGridProps({ ...planGridProps, planGridData: [] })
|
||||
|
||||
alert(getMessage('stuff.detail.header.notExistObjectNo'))
|
||||
router.push('/management/stuff')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -2433,6 +2450,8 @@ export default function StuffDetail() {
|
||||
{showWindSpeedButtonValid && (
|
||||
<WindSelectPop setShowWindSpeedButtonValid={setShowWindSpeedButtonValid} prefName={form.watch('prefName')} windSpeedInfo={setWindSppedInfo} />
|
||||
)}
|
||||
|
||||
{estimatePopupOpen && <DocDownOptionPop planNo={popPlanNo} setEstimatePopupOpen={setEstimatePopupOpen} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -116,8 +116,10 @@ export default function StuffSearchCondition() {
|
||||
schAddress: address,
|
||||
schObjectName: objectName,
|
||||
schDispCompanyName: dispCompanyName,
|
||||
schSelSaleStoreId: stuffSearch?.schSelSaleStoreId,
|
||||
schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId,
|
||||
// schSelSaleStoreId: stuffSearch?.schSelSaleStoreId,
|
||||
// schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId,
|
||||
schSelSaleStoreId: schSelSaleStoreId,
|
||||
schOtherSelSaleStoreId: otherSaleStoreId,
|
||||
schReceiveUser: receiveUser,
|
||||
schDateType: dateType,
|
||||
schFromDt: dayjs(startDate).format('YYYY-MM-DD'),
|
||||
@ -157,6 +159,7 @@ export default function StuffSearchCondition() {
|
||||
setStuffSearch({
|
||||
schSelSaleStoreId: '',
|
||||
schOtherSelSaleStoreId: '',
|
||||
schDateType: 'U',
|
||||
})
|
||||
} else {
|
||||
if (otherSaleStoreList.length > 1) {
|
||||
@ -312,8 +315,8 @@ export default function StuffSearchCondition() {
|
||||
} else {
|
||||
//X누름
|
||||
//화면에선 지우는데 리코일은 조회누르지 않으면 보존
|
||||
setSchSelSaleStoreId('')
|
||||
// stuffSearch.schSelSaleStoreId = ''
|
||||
// setSchSelSaleStoreId('') //값이 안비워짐..
|
||||
setSchSelSaleStoreId(null)
|
||||
|
||||
//2차점 판매점목록비우기
|
||||
setOtherSaleStoreList([])
|
||||
@ -333,7 +336,6 @@ export default function StuffSearchCondition() {
|
||||
if (session.storeLvl === '1') {
|
||||
if (stuffSearch.schOtherSelSaleStoreId === '') {
|
||||
// 화면에선 지우는데 조회누르기 전이면 리코일은 남김
|
||||
// stuffSearch.schSelSaleStoreId = ''
|
||||
setSchSelSaleStoreId(session.storeId)
|
||||
} else {
|
||||
// 화면에선 지우는데 조회누르기 전이면 리코일은 남김
|
||||
@ -357,6 +359,7 @@ export default function StuffSearchCondition() {
|
||||
setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName)
|
||||
setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
|
||||
setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
|
||||
setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
|
||||
}, [stuffSearch])
|
||||
|
||||
useEffect(() => {
|
||||
@ -638,7 +641,7 @@ export default function StuffSearchCondition() {
|
||||
type="radio"
|
||||
name="radio_ptype"
|
||||
id="radio_u"
|
||||
checked={stuffSearch.schDateType === 'U' ? true : false}
|
||||
checked={dateType === 'U' ? true : false}
|
||||
value={'U'}
|
||||
onChange={(e) => {
|
||||
setDateType(e.target.value)
|
||||
@ -652,7 +655,7 @@ export default function StuffSearchCondition() {
|
||||
type="radio"
|
||||
name="radio_ptype"
|
||||
id="radio_r"
|
||||
checked={stuffSearch.schDateType === 'R' ? true : false}
|
||||
checked={dateType === 'R' ? true : false}
|
||||
value={'R'}
|
||||
onChange={(e) => {
|
||||
setDateType(e.target.value)
|
||||
|
||||
@ -105,8 +105,8 @@ export default function Simulator() {
|
||||
useEffect(() => {
|
||||
if (objectNo) {
|
||||
fetchObjectDetail(objectNo)
|
||||
fetchSimulatorNotice()
|
||||
}
|
||||
fetchSimulatorNotice()
|
||||
}, [objectNo, plan])
|
||||
|
||||
// 물건 상세 정보 조회
|
||||
@ -158,23 +158,25 @@ export default function Simulator() {
|
||||
<div className="estimate-box">
|
||||
<div className="estimate-tit">{getMessage('simulator.title.sub1')}</div>
|
||||
<div className="estimate-name">
|
||||
{objectDetail.objectNo} (Plan No: {objectDetail.planNo})
|
||||
{objectDetail.objectNo} (Plan No: {plan?.id})
|
||||
</div>
|
||||
</div>
|
||||
{/* 작성일 */}
|
||||
<div className="estimate-box">
|
||||
<div className="estimate-tit">{getMessage('simulator.title.sub2')}</div>
|
||||
<div className="estimate-name">{`${dayjs(objectDetail.drawingEstimateCreateDate).format('YYYY.MM.DD')}`}</div>
|
||||
<div className="estimate-name">
|
||||
{objectDetail.drawingEstimateCreateDate ? `${dayjs(objectDetail.drawingEstimateCreateDate).format('YYYY.MM.DD')}` : ''}
|
||||
</div>
|
||||
</div>
|
||||
{/* 시스템용량 */}
|
||||
<div className="estimate-box">
|
||||
<div className="estimate-tit">{getMessage('simulator.title.sub3')}</div>
|
||||
<div className="estimate-name">{convertNumberToPriceDecimal(objectDetail.capacity)}kW</div>
|
||||
<div className="estimate-name">{objectDetail.capacity ? `${convertNumberToPriceDecimal(objectDetail.capacity)}kW` : ''}</div>
|
||||
</div>
|
||||
{/* 연간예측발전량 */}
|
||||
<div className="estimate-box">
|
||||
<div className="estimate-tit">{getMessage('simulator.title.sub4')}</div>
|
||||
<div className="estimate-name">{convertNumberToPriceDecimal(objectDetail.anlFrcsGnrt)}</div>
|
||||
<div className="estimate-name">{objectDetail.anlFrcsGnrt ? convertNumberToPriceDecimal(objectDetail.anlFrcsGnrt) : ''}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="estimate-list-wrap">
|
||||
|
||||
@ -40,19 +40,19 @@ export function useCanvasConfigInitialize() {
|
||||
const flowTexts = canvas.getObjects().filter((obj) => obj.name === 'flowText')
|
||||
if (basicSetting.roofAngleSet === 'slope') {
|
||||
offsetTexts.forEach((obj) => {
|
||||
obj.set({ text: `${obj.originText}-∠${obj.pitch}${angleUnit}` })
|
||||
obj.set({ text: `${!obj.originText ? '' : obj.originText + '-'}∠${obj.pitch}${angleUnit}` })
|
||||
})
|
||||
flowTexts.forEach((obj) => {
|
||||
obj.set({ text: `${obj.originText}-∠${obj.pitch}${pitchText}` })
|
||||
obj.set({ text: `${!obj.originText ? '' : obj.originText + '-'}∠${obj.pitch}${pitchText}` })
|
||||
})
|
||||
}
|
||||
|
||||
if (basicSetting.roofAngleSet === 'flat') {
|
||||
offsetTexts.forEach((obj) => {
|
||||
obj.set({ text: `${obj.originText}-∠${getDegreeByChon(obj.pitch)}${angleUnit}` })
|
||||
obj.set({ text: `${!obj.originText ? '' : obj.originText + '-'}∠${getDegreeByChon(obj.pitch)}${angleUnit}` })
|
||||
})
|
||||
flowTexts.forEach((obj) => {
|
||||
obj.set({ text: `${obj.originText}-∠${getDegreeByChon(obj.pitch)}${pitchText}` })
|
||||
obj.set({ text: `${!obj.originText ? '' : obj.originText + '-'}∠${getDegreeByChon(obj.pitch)}${pitchText}` })
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -59,6 +59,12 @@ export const useEstimateController = (planNo) => {
|
||||
try {
|
||||
await get({ url: `/api/estimate/${objectRecoil.floorPlanObjectNo}/${planNo}/detail` }).then((res) => {
|
||||
if (isObjectNotEmpty(res)) {
|
||||
if (res.itemList.length > 0) {
|
||||
res.itemList.map((item) => {
|
||||
item.delFlg = '0'
|
||||
})
|
||||
}
|
||||
|
||||
setState(res)
|
||||
}
|
||||
})
|
||||
@ -76,7 +82,9 @@ export const useEstimateController = (planNo) => {
|
||||
}
|
||||
|
||||
const addItem = () => {
|
||||
const newItemDispOrder = Math.max(...state.itemList.map((item) => item.dispOrder)) + 1
|
||||
// const newItemDispOrder = (Math.max(...state.itemList.map((item) => item.dispOrder)) / 100 + 1) * 100
|
||||
let newItemDispOrder = Math.max(...state.itemList.map((item) => item.dispOrder))
|
||||
newItemDispOrder = (Math.floor(newItemDispOrder / 100) + 1) * 100
|
||||
setState({
|
||||
itemList: [
|
||||
...state.itemList,
|
||||
@ -90,8 +98,8 @@ export const useEstimateController = (planNo) => {
|
||||
amount: '', //수량
|
||||
unitPrice: '0',
|
||||
unit: '', //단위
|
||||
salePrice: '0', //단가
|
||||
saleTotPrice: '0', //금액(부가세별도)
|
||||
salePrice: '', //단가
|
||||
saleTotPrice: '', //금액(부가세별도)
|
||||
itemChangeFlg: '1', //추가시 체인지플래그 1로
|
||||
partAdd: '1', //NEW 체인지 플래그
|
||||
delFlg: '0', //삭제 플래그 0 삭제하면 1
|
||||
@ -133,7 +141,7 @@ export const useEstimateController = (planNo) => {
|
||||
const handleEstimateSubmit = async () => {
|
||||
//0. 필수체크
|
||||
let flag = true
|
||||
console.log('::담긴 estimateData:::', estimateData)
|
||||
|
||||
// console.log('첨부파일:::::', estimateData.fileList)
|
||||
//첨부파일을 첨부안했는데
|
||||
//아이템 fileUploadFlg가1(첨부파일 필수)이 1개라도 있는데 후일 자료 제출(fileFlg) 체크안했으면(0) alert 저장안돼
|
||||
@ -151,9 +159,8 @@ export const useEstimateController = (planNo) => {
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
//1. 첨부파일 저장
|
||||
//1. 첨부파일 저장시작
|
||||
const formData = new FormData()
|
||||
console.log('첨부파일:!!!', estimateData.fileList)
|
||||
formData.append('file', estimateData.fileList)
|
||||
formData.append('objectNo', estimateData.objectNo)
|
||||
formData.append('planNo', estimateData.planNo)
|
||||
@ -161,26 +168,30 @@ export const useEstimateController = (planNo) => {
|
||||
formData.append('userId', estimateData.userId)
|
||||
|
||||
await post({ url: '/api/file/fileUpload', data: formData })
|
||||
//첨부파일저장끝
|
||||
|
||||
//제품라인 추가했는데 아이템 안고르고 저장하면itemId=''은 날리고 나머지 저장하기
|
||||
estimateData.itemList = estimateData.itemList.filter((item) => item.itemId !== '')
|
||||
|
||||
let delCnt = 0
|
||||
estimateData.itemList.map((item) => {
|
||||
if (item.delFlg === '1') {
|
||||
delCnt++
|
||||
}
|
||||
})
|
||||
if (delCnt === estimateData.itemList.length) {
|
||||
return alert(getMessage('estimate.detail.save.requiredItem'))
|
||||
}
|
||||
|
||||
console.log('최종 정보::;', estimateData)
|
||||
console.log('최종 남은 아이템정보:::', estimateData.itemList)
|
||||
//2. 상세데이터 저장
|
||||
return
|
||||
// return
|
||||
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => {
|
||||
if (res) {
|
||||
alert(getMessage('estimate.detail.save.alertMsg'))
|
||||
}
|
||||
})
|
||||
|
||||
// try {
|
||||
// const result = await promisePost({
|
||||
// url: ESTIMATE_API_ENDPOINT,
|
||||
// data: estimateData,
|
||||
// })
|
||||
// alert(getMessage('estimate.detail.save.alertMsg'))
|
||||
// return result
|
||||
// } catch (error) {
|
||||
// console.error('Failed to submit estimate:', error)
|
||||
// throw error
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ import { canvasState } from '@/store/canvasAtom'
|
||||
import { usePolygon } from '@/hooks/usePolygon'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { compasDegAtom } from '@/store/orientationAtom'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
// 모듈,회로 구성 탭 기본설정 > 방위설정 탭
|
||||
export function useOrientation() {
|
||||
@ -11,6 +12,16 @@ export function useOrientation() {
|
||||
|
||||
const { drawDirectionArrow } = usePolygon()
|
||||
|
||||
useEffect(() => {
|
||||
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||
roofs.forEach((roof) => {
|
||||
roof.set({
|
||||
moduleCompass: null,
|
||||
})
|
||||
drawDirectionArrow(roof)
|
||||
})
|
||||
}, [])
|
||||
|
||||
const nextStep = () => {
|
||||
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||
roofs.forEach((roof) => {
|
||||
@ -277,7 +277,7 @@ export function useCanvasSetting() {
|
||||
optionName = ['outerLine', POLYGON_TYPE.WALL]
|
||||
break
|
||||
case 'gridDisplay': //그리드 표시
|
||||
optionName = ['lindGrid', 'dotGrid']
|
||||
optionName = ['lindGrid', 'dotGrid', 'tempGrid']
|
||||
break
|
||||
case 'lineDisplay': //지붕선 표시
|
||||
optionName = ['roof', POLYGON_TYPE.ROOF]
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { useEffect } from 'react'
|
||||
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
|
||||
export function useFirstOption() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
|
||||
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
|
||||
|
||||
useEffect(() => {
|
||||
const option1 = settingModalFirstOptions.option1
|
||||
|
||||
// 'allocDisplay' 할당 표시
|
||||
// 'outlineDisplay' 외벽선 표시 'outerLine', POLYGON_TYPE.WALL
|
||||
// 'gridDisplay' 그리드 표시 'lindGrid', 'dotGrid'
|
||||
// 'lineDisplay' 지붕선 표시 'roof', POLYGON_TYPE.ROOF
|
||||
// 'wordDisplay' 문자 표시
|
||||
// 'circuitNumDisplay' 회로번호 표시
|
||||
// 'flowDisplay' 흐름방향 표시 'arrow'
|
||||
// 'trestleDisplay' 가대 표시
|
||||
// 'totalDisplay' 집계표 표시
|
||||
|
||||
let optionName //옵션명
|
||||
let optionSelected //옵션상태
|
||||
|
||||
for (let i = 0; i < option1.length; i++) {
|
||||
switch (option1[i].column) {
|
||||
case 'allocDisplay': //할당 표시
|
||||
optionName = ['1']
|
||||
break
|
||||
case 'outlineDisplay': //외벽선 표시
|
||||
optionName = ['outerLine', POLYGON_TYPE.WALL]
|
||||
break
|
||||
case 'gridDisplay': //그리드 표시
|
||||
optionName = ['lineGrid', 'dotGrid', 'adsorptionPoint', 'tempGrid']
|
||||
break
|
||||
case 'lineDisplay': //지붕선 표시
|
||||
optionName = ['roof', POLYGON_TYPE.ROOF]
|
||||
break
|
||||
case 'wordDisplay': //문자 표시
|
||||
optionName = ['commonText']
|
||||
break
|
||||
case 'circuitNumDisplay': //회로번호 표시
|
||||
optionName = ['7']
|
||||
break
|
||||
case 'flowDisplay': //흐름방향 표시
|
||||
optionName = ['arrow', 'flowText']
|
||||
break
|
||||
case 'trestleDisplay': //가대 표시
|
||||
optionName = ['8']
|
||||
break
|
||||
case 'totalDisplay': //집계표 표시
|
||||
optionName = ['9']
|
||||
break
|
||||
}
|
||||
// 표시 선택 상태(true/false)
|
||||
optionSelected = option1[i].selected
|
||||
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => optionName.includes(obj.name))
|
||||
//.filter((obj) => obj.name === optionName)
|
||||
.forEach((obj) => {
|
||||
obj.set({ visible: optionSelected })
|
||||
//obj.set({ visible: !obj.visible })
|
||||
})
|
||||
|
||||
canvas.renderAll()
|
||||
|
||||
// console.log(
|
||||
// 'optionName',
|
||||
// optionName,
|
||||
// canvas.getObjects().filter((obj) => optionName.includes(obj.name)),
|
||||
// )
|
||||
}
|
||||
}, [settingModalFirstOptions])
|
||||
|
||||
return { settingModalFirstOptions, setSettingModalFirstOptions }
|
||||
}
|
||||
@ -455,9 +455,24 @@ export function useAuxiliaryDrawing(id) {
|
||||
name: 'auxiliaryLine',
|
||||
})
|
||||
|
||||
lineHistory.current.push(line)
|
||||
const historyLines = [...lineHistory.current]
|
||||
|
||||
const hasSameLine = historyLines.some((history) => {
|
||||
return (
|
||||
(isSamePoint(history.startPoint, line.startPoint) && isSamePoint(history.endPoint, line.endPoint)) ||
|
||||
(isSamePoint(history.startPoint, line.endPoint) && isSamePoint(history.endPoint, line.startPoint))
|
||||
)
|
||||
})
|
||||
|
||||
mousePointerArr.current = []
|
||||
clear()
|
||||
|
||||
if (hasSameLine) {
|
||||
canvas.remove(line)
|
||||
return
|
||||
}
|
||||
|
||||
lineHistory.current.push(line)
|
||||
}
|
||||
|
||||
const mouseDown = (e) => {
|
||||
|
||||
@ -125,6 +125,12 @@ export function usePropertiesSetting(id) {
|
||||
}
|
||||
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||
|
||||
const notSetAttributes = lines.filter((line) => !line.attributes?.type)
|
||||
if (notSetAttributes.length > 0) {
|
||||
alert('설정되지 않은 외벽선이 있습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
lines.forEach((line) => {
|
||||
line.set({
|
||||
attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL },
|
||||
|
||||
@ -377,20 +377,20 @@ export function useRoofShapeSetting(id) {
|
||||
}
|
||||
|
||||
// 기존 wallLine, roofBase 제거
|
||||
/*canvas
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||
.forEach((line) => {
|
||||
canvas.remove(line)
|
||||
})*/
|
||||
})
|
||||
|
||||
/*canvas
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.ROOF && !obj.isFixed)
|
||||
.forEach((obj) => {
|
||||
canvas.remove(...obj.innerLines)
|
||||
canvas.remove(obj)
|
||||
})*/
|
||||
})
|
||||
|
||||
const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL, direction })
|
||||
polygon.lines = [...outerLines]
|
||||
|
||||
@ -446,19 +446,24 @@ export function useContextMenu() {
|
||||
])
|
||||
break
|
||||
case 'lineGrid':
|
||||
case 'dotGrid':
|
||||
case 'tempGrid':
|
||||
setContextMenu([
|
||||
[
|
||||
{
|
||||
id: 'gridMove',
|
||||
name: getMessage('modal.grid.move'),
|
||||
component: <GridMove id={popupId} />,
|
||||
},
|
||||
{
|
||||
id: 'gridCopy',
|
||||
name: getMessage('modal.grid.copy'),
|
||||
component: <GridCopy id={popupId} />,
|
||||
},
|
||||
{
|
||||
id: 'gridColorEdit',
|
||||
name: getMessage('contextmenu.grid.color.edit'),
|
||||
component: <ColorPickerModal id={popupId} color={gridColor} setColor={setGridColor} />,
|
||||
},
|
||||
{
|
||||
id: 'remove',
|
||||
|
||||
@ -284,7 +284,6 @@
|
||||
"modal.panel.batch.statistic.total": "合計",
|
||||
"modal.flow.direction.setting": "流れ方向の設定",
|
||||
"modal.flow.direction.setting.info": "流れ方向を選択してください。",
|
||||
"modal.image.size.setting": "画像のサイズ変更",
|
||||
"modal.actual.size.setting": "実測値設定",
|
||||
"modal.actual.size.setting.info": "※隅棟・谷・棟の実際の寸法を入力してください。",
|
||||
"modal.actual.size.setting.not.exist.auxiliary.line": "실측치 입력할 보조선을 선택해 주세요(JA)",
|
||||
@ -733,7 +732,7 @@
|
||||
"stuff.detail.planGridHeader.pcTypeNo": "パワーコンディショナー",
|
||||
"stuff.detail.planGridHeader.management": "管理",
|
||||
"stuff.detail.planGrid.btn1": "見積書の照会",
|
||||
"stuff.detail.planGrid.btn2": "Excel",
|
||||
"stuff.detail.planGrid.docDownload": "文書のダウンロード",
|
||||
"stuff.grid.noData": "照会されたデータがありません",
|
||||
"length": "長さ",
|
||||
"height": "高さ",
|
||||
@ -844,6 +843,7 @@
|
||||
"estimate.detail.header.showPrice": "価格表示",
|
||||
"estimate.detail.header.unitPrice": "定価",
|
||||
"estimate.detail.showPrice.pricingBtn": "Pricing",
|
||||
"estimate.detail.showPrice.pricingBtn.noItemId": "Pricingが欠落しているアイテムがあります。 Pricingを進めてください.",
|
||||
"estimate.detail.showPrice.description1": "製品価格 OPEN",
|
||||
"estimate.detail.showPrice.description2": "追加, 変更資材",
|
||||
"estimate.detail.showPrice.description3": "添付必須",
|
||||
@ -860,25 +860,26 @@
|
||||
"estimate.detail.docPopup.title": "ドキュメントダウンロードオプションの設定",
|
||||
"estimate.detail.docPopup.explane": "ダウンロードする文書のオプションを選択したら、 [文書のダウンロード]ボタンをクリックします.",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg": "ダウンロードファイル",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg0": "見積もり Excel",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg1": "定価用 Excel",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg2": "見積もり PDF",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg3": "定価用 PDF",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg0": "見積もり Excel",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg1": "定価用 Excel",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.pdfFlg0": "見積もり PDF",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.pdfFlg1": "定価用 PDF",
|
||||
"estimate.detail.docPopup.schDisplayFlg": "見積提出先表示名",
|
||||
"estimate.detail.docPopup.schDisplayFlg.schDisplayFlg0": "販売店名",
|
||||
"estimate.detail.docPopup.schDisplayFlg.schDisplayFlg1": "案件名",
|
||||
"estimate.detail.docPopup.schWeightFlg": "架台重量表を含む",
|
||||
"estimate.detail.docPopup.schWeightFlg.schWeightFlg0": "含む",
|
||||
"estimate.detail.docPopup.schWeightFlg.schWeightFlg1": "含まない",
|
||||
"estimate.detail.docPopup.schWeightFlg.schWeightFlg1": "含む",
|
||||
"estimate.detail.docPopup.schWeightFlg.schWeightFlg0": "含まない",
|
||||
"estimate.detail.docPopup.schDrawingFlg": "図面/シミュレーションファイルを含む",
|
||||
"estimate.detail.docPopup.schDrawingFlg.schDrawingFlg0": "含む",
|
||||
"estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1": "含まない",
|
||||
"estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1": "含む",
|
||||
"estimate.detail.docPopup.schDrawingFlg.schDrawingFlg0": "含まない",
|
||||
"estimate.detail.docPopup.close": "閉じる",
|
||||
"estimate.detail.docPopup.docDownload": "文書のダウンロード",
|
||||
"estimate.detail.productFeaturesPopup.title": "製品特異事項",
|
||||
"estimate.detail.productFeaturesPopup.close": "閉じる",
|
||||
"estimate.detail.save.alertMsg": "保存されている見積書で製品を変更した場合、図面や回路には反映されません.",
|
||||
"estimate.detail.save.requiredMsg": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください.",
|
||||
"estimate.detail.save.requiredItem": "製品は1つ以上登録する必要があります.",
|
||||
"estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?",
|
||||
"simulator.title.sub1": "物件番号",
|
||||
"simulator.title.sub2": "作成日",
|
||||
|
||||
@ -289,7 +289,6 @@
|
||||
"modal.panel.batch.statistic.total": "합계",
|
||||
"modal.flow.direction.setting": "흐름 방향 설정",
|
||||
"modal.flow.direction.setting.info": "흐름방향을 선택하세요.",
|
||||
"modal.image.size.setting": "이미지 크기 조절",
|
||||
"modal.actual.size.setting": "실측치 설정",
|
||||
"modal.actual.size.setting.info": "※隅棟・谷・棟의 실제 치수를 입력해주세요.",
|
||||
"modal.actual.size.setting.not.exist.auxiliary.line": "실측치 입력할 보조선을 선택해 주세요",
|
||||
@ -743,7 +742,7 @@
|
||||
"stuff.detail.planGridHeader.pcTypeNo": "파워컨디셔너",
|
||||
"stuff.detail.planGridHeader.management": "관리",
|
||||
"stuff.detail.planGrid.btn1": "견적서 조회",
|
||||
"stuff.detail.planGrid.btn2": "Excel",
|
||||
"stuff.detail.planGrid.docDownload": "문서 다운로드",
|
||||
"stuff.grid.noData": "조회된 데이터가 없습니다",
|
||||
"length": "길이",
|
||||
"height": "높이",
|
||||
@ -849,11 +848,12 @@
|
||||
"estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice": "주택PKG단가 (W)",
|
||||
"estimate.detail.sepcialEstimateProductInfo.pkgWeight": "PKG 용량 (Kw)",
|
||||
"estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG 금액",
|
||||
"estimate.detail.sepcialEstimateProductInfo.calcFormula1": "(모듈수량 * 수량)÷100",
|
||||
"estimate.detail.sepcialEstimateProductInfo.calcFormula1": "(모듈용량 * 수량)÷100",
|
||||
"estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG단가(W) * PKG용량(W)",
|
||||
"estimate.detail.header.showPrice": "가격표시",
|
||||
"estimate.detail.header.unitPrice": "정가",
|
||||
"estimate.detail.showPrice.pricingBtn": "Pricing",
|
||||
"estimate.detail.showPrice.pricingBtn.noItemId": "Pricing이 누락된 아이템이 있습니다. Pricing을 진행해주세요.",
|
||||
"estimate.detail.showPrice.description1": "제품 가격 OPEN",
|
||||
"estimate.detail.showPrice.description2": "추가, 변경 자재",
|
||||
"estimate.detail.showPrice.description3": "첨부필수",
|
||||
@ -870,25 +870,26 @@
|
||||
"estimate.detail.docPopup.title": "문서다운로드 옵션설정",
|
||||
"estimate.detail.docPopup.explane": "다운로드할 문서 옵션을 선택한 후 문서 다운로드 버튼을 클릭합니다.",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg": "다운로드 파일",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg0": "견적가 Excel",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg1": "정가용 Excel",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg2": "견적가 PDF",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg3": "정가용 PDF",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg0": "견적가 Excel",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg1": "정가용 Excel",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.pdfFlg0": "견적가 PDF",
|
||||
"estimate.detail.docPopup.schUnitPriceFlg.pdfFlg1": "정가용 PDF",
|
||||
"estimate.detail.docPopup.schDisplayFlg": "견적제출서 표시명",
|
||||
"estimate.detail.docPopup.schDisplayFlg.schDisplayFlg0": "판매점명",
|
||||
"estimate.detail.docPopup.schDisplayFlg.schDisplayFlg1": "안건명",
|
||||
"estimate.detail.docPopup.schWeightFlg": "가대 중량표 포함",
|
||||
"estimate.detail.docPopup.schWeightFlg.schWeightFlg0": "포함",
|
||||
"estimate.detail.docPopup.schWeightFlg.schWeightFlg1": "미포함",
|
||||
"estimate.detail.docPopup.schWeightFlg.schWeightFlg1": "포함",
|
||||
"estimate.detail.docPopup.schWeightFlg.schWeightFlg0": "미포함",
|
||||
"estimate.detail.docPopup.schDrawingFlg": "도면/시뮬레이션 파일 포함",
|
||||
"estimate.detail.docPopup.schDrawingFlg.schDrawingFlg0": "포함",
|
||||
"estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1": "미포함",
|
||||
"estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1": "포함",
|
||||
"estimate.detail.docPopup.schDrawingFlg.schDrawingFlg0": "미포함",
|
||||
"estimate.detail.docPopup.close": "닫기",
|
||||
"estimate.detail.docPopup.docDownload": "문서 다운로드",
|
||||
"estimate.detail.productFeaturesPopup.title": "제품특이사항",
|
||||
"estimate.detail.productFeaturesPopup.close": "닫기",
|
||||
"estimate.detail.save.alertMsg": "저장되었습니다. 견적서에서 제품을 변경할 경우, 도면 및 회로에 반영되지 않습니다.",
|
||||
"estimate.detail.save.requiredMsg": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오.",
|
||||
"estimate.detail.save.requiredItem": "제품은 1개이상 등록해야 됩니다.",
|
||||
"estimate.detail.reset.confirmMsg": "저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까?",
|
||||
"simulator.title.sub1": "물건번호",
|
||||
"simulator.title.sub2": "작성일",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1201,7 +1201,7 @@ export function removeDuplicatePolygons(polygons) {
|
||||
}
|
||||
|
||||
export const isSamePoint = (a, b) => {
|
||||
return Math.abs(Math.round(a.x) - Math.round(b.x)) <= 1 && Math.abs(Math.round(a.y) - Math.round(b.y)) <= 1
|
||||
return Math.abs(Math.round(a.x) - Math.round(b.x)) <= 2 && Math.abs(Math.round(a.y) - Math.round(b.y)) <= 2
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user