Compare commits

...

12 Commits

11 changed files with 832 additions and 1962 deletions

View File

@ -3,7 +3,7 @@ import { createCalculator } from '@/util/calc-utils'
import '@/styles/calc.scss' import '@/styles/calc.scss'
export const CalculatorInput = forwardRef( export const CalculatorInput = forwardRef(
({ value, onChange, label, options = {}, id, className = 'calculator-input', readOnly = false, placeholder }, ref) => { ({ value, onChange, label, options = {}, id, className = 'calculator-input', readOnly = false, placeholder, name='', disabled = false }, ref) => {
const [showKeypad, setShowKeypad] = useState(false) const [showKeypad, setShowKeypad] = useState(false)
const [displayValue, setDisplayValue] = useState(value || '0') const [displayValue, setDisplayValue] = useState(value || '0')
const [hasOperation, setHasOperation] = useState(false) const [hasOperation, setHasOperation] = useState(false)
@ -353,6 +353,7 @@ export const CalculatorInput = forwardRef(
ref={inputRef} ref={inputRef}
type="text" type="text"
id={id} id={id}
name={name}
value={displayValue} value={displayValue}
readOnly={readOnly} readOnly={readOnly}
className={className} className={className}
@ -363,6 +364,7 @@ export const CalculatorInput = forwardRef(
tabIndex={readOnly ? -1 : 0} tabIndex={readOnly ? -1 : 0}
placeholder={placeholder} placeholder={placeholder}
autoComplete={'off'} autoComplete={'off'}
disabled={disabled}
/> />
{showKeypad && !readOnly && ( {showKeypad && !readOnly && (

View File

@ -25,6 +25,7 @@ export default function QnaDetailModal({ qnaNo, setOpen, qnaType }) {
compCd : 5200, compCd : 5200,
loginId : sessionState.userId, loginId : sessionState.userId,
langCd : 'JA', langCd : 'JA',
siteTpCd : 'QC',
}) })
const apiUrl = `${url}?${params.toString()}` const apiUrl = `${url}?${params.toString()}`

View File

@ -148,6 +148,8 @@ let fileCheck = false;
} else {
setHideSmFlg(true)
} }
} }

View File

@ -138,7 +138,27 @@ export default function Estimate({}) {
updatedRes = [...res] updatedRes = [...res]
} }
setOriginDisplayItemList(res) const groupByItemGroup = (items) => {
const grouped = items.reduce((acc, item) => {
const group = item.itemGroup || '기타';
if (!acc[group]) {
acc[group] = {
label: group,
options: []
};
}
acc[group].options.push({
value: item.itemId,
label: `${item.itemNo} - ${item.itemName}`,
...item
});
return acc;
}, {});
return Object.values(grouped);
};
const groupedItems = groupByItemGroup(res);
setOriginDisplayItemList(groupedItems)
setDisplayItemList(updatedRes) setDisplayItemList(updatedRes)
} }
}) })
@ -153,6 +173,19 @@ export default function Estimate({}) {
}) })
} }
const groupStyles = {
groupHeading: (provided) => ({
...provided,
fontSize: '14px',
fontWeight: 'bold',
color: '#333',
backgroundColor: '#f5f5f5',
padding: '8px 12px',
marginBottom: '4px',
borderBottom: '2px solid #ddd'
})
};
useEffect(() => { useEffect(() => {
// console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan) // console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan)
if (selectedPlan) initEstimate(selectedPlan?.planNo?? currentPid) if (selectedPlan) initEstimate(selectedPlan?.planNo?? currentPid)
@ -1998,6 +2031,7 @@ export default function Estimate({}) {
classNamePrefix="custom" classNamePrefix="custom"
placeholder="Select" placeholder="Select"
options={originDisplayItemList} options={originDisplayItemList}
styles={groupStyles}
onChange={(e) => { onChange={(e) => {
if (isObjectNotEmpty(e)) { if (isObjectNotEmpty(e)) {
onChangeDisplayItem(e.itemId, item.dispOrder, index, false) onChangeDisplayItem(e.itemId, item.dispOrder, index, false)

View File

@ -6,6 +6,7 @@ import { calculateAngle, drawGableRoof, drawRidgeRoof, drawShedRoof, toGeoJSON }
import * as turf from '@turf/turf' import * as turf from '@turf/turf'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
import Big from 'big.js' import Big from 'big.js'
import { drawSkeletonRidgeRoof } from '@/util/skeleton-utils'
export const QPolygon = fabric.util.createClass(fabric.Polygon, { export const QPolygon = fabric.util.createClass(fabric.Polygon, {
type: 'QPolygon', type: 'QPolygon',
@ -335,6 +336,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
// 용마루 -- straight-skeleton // 용마루 -- straight-skeleton
console.log('용마루 지붕') console.log('용마루 지붕')
drawRidgeRoof(this.id, this.canvas, textMode) drawRidgeRoof(this.id, this.canvas, textMode)
//drawSkeletonRidgeRoof(this.id, this.canvas, textMode);
} else if (isGableRoof(types)) { } else if (isGableRoof(types)) {
// A형, B형 박공 지붕 // A형, B형 박공 지붕
console.log('패턴 지붕') console.log('패턴 지붕')

View File

@ -346,6 +346,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
/> */} /> */}
<CalculatorInput <CalculatorInput
id="" id=""
name=""
label="" label=""
className="input-origin block" className="input-origin block"
readOnly={currentRoof?.roofAngleSet !== item.value} readOnly={currentRoof?.roofAngleSet !== item.value}
@ -412,15 +413,33 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
<div className="flex-ment"> <div className="flex-ment">
<span>W</span> <span>W</span>
<div className="input-grid" style={{ width: '84px' }}> <div className="input-grid" style={{ width: '84px' }}>
<input {/*<input*/}
type="text" {/* type="text"*/}
{/* className="input-origin block"*/}
{/* name={`width`}*/}
{/* ref={roofRef.width}*/}
{/* value={parseInt(currentRoof?.width)}*/}
{/* onChange={(e) => changeInput(normalizeDigits(e.target.value), e)}*/}
{/* readOnly={currentRoof?.widAuth === 'R'}*/}
{/* disabled={currentRoof?.roofSizeSet === '3'}*/}
{/*/>*/}
<CalculatorInput
id=""
name={'width'}
label=""
className="input-origin block" className="input-origin block"
name={`width`}
ref={roofRef.width} ref={roofRef.width}
value={parseInt(currentRoof?.width)} value={currentRoof?.width||0}
onChange={(e) => changeInput(normalizeDigits(e.target.value), e)} onChange={(value) => {
setCurrentRoof({ ...currentRoof, value })
}}
readOnly={currentRoof?.widAuth === 'R'} readOnly={currentRoof?.widAuth === 'R'}
disabled={currentRoof?.roofSizeSet === '3'} disabled={currentRoof?.roofSizeSet === '3'}
options={{
allowNegative: false,
allowDecimal: false //(index !== 0),
}}
/> />
</div> </div>
</div> </div>
@ -429,15 +448,33 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
<div className="flex-ment"> <div className="flex-ment">
<span>L</span> <span>L</span>
<div className="input-grid" style={{ width: '84px' }}> <div className="input-grid" style={{ width: '84px' }}>
<input {/*<input*/}
type="text" {/* type="text"*/}
{/* className="input-origin block"*/}
{/* name={`length`}*/}
{/* ref={roofRef.length}*/}
{/* value={parseInt(currentRoof?.length)}*/}
{/* onChange={(e) => changeInput(normalizeDigits(e.target.value), e)}*/}
{/* readOnly={currentRoof?.lenAuth === 'R'}*/}
{/* disabled={currentRoof?.roofSizeSet === '3'}*/}
{/*/>*/}
<CalculatorInput
id=""
name={'length'}
label=""
className="input-origin block" className="input-origin block"
name={`length`}
ref={roofRef.length} ref={roofRef.length}
value={parseInt(currentRoof?.length)} value={currentRoof?.length||0}
onChange={(e) => changeInput(normalizeDigits(e.target.value), e)} onChange={(value) => {
setCurrentRoof({ ...currentRoof, value })
}}
readOnly={currentRoof?.lenAuth === 'R'} readOnly={currentRoof?.lenAuth === 'R'}
disabled={currentRoof?.roofSizeSet === '3'} disabled={currentRoof?.roofSizeSet === '3'}
options={{
allowNegative: false,
allowDecimal: false //(index !== 0),
}}
/> />
</div> </div>
</div> </div>
@ -465,16 +502,34 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
<div className="flex-ment"> <div className="flex-ment">
<span>{getMessage('hajebichi')}</span> <span>{getMessage('hajebichi')}</span>
<div className="input-grid" style={{ width: '84px' }}> <div className="input-grid" style={{ width: '84px' }}>
<input {/*<input*/}
type="text" {/* type="text"*/}
{/* className="input-origin block"*/}
{/* name={`hajebichi`}*/}
{/* ref={roofRef.hajebichi}*/}
{/* value={parseInt(currentRoof?.hajebichi)}*/}
{/* onChange={(e) => changeInput(normalizeDigits(e.target.value), e)}*/}
{/* readOnly={currentRoof?.roofPchAuth === 'R'}*/}
{/* disabled={currentRoof?.roofSizeSet === '3'}*/}
{/*/>*/}
<CalculatorInput
id=""
name={'hajebichi'}
label=""
className="input-origin block" className="input-origin block"
name={`hajebichi`}
ref={roofRef.hajebichi} ref={roofRef.hajebichi}
value={parseInt(currentRoof?.hajebichi)} value={currentRoof?.hajebichi||0}
onChange={(e) => changeInput(normalizeDigits(e.target.value), e)} onChange={(value) => {
setCurrentRoof({ ...currentRoof, value })
}}
readOnly={currentRoof?.roofPchAuth === 'R'} readOnly={currentRoof?.roofPchAuth === 'R'}
disabled={currentRoof?.roofSizeSet === '3'} disabled={currentRoof?.roofSizeSet === '3'}
options={{
allowNegative: false,
allowDecimal: false //(index !== 0),
}}
/> />
</div> </div>
</div> </div>
)} )}

View File

@ -49,34 +49,25 @@ export default function Simulator() {
return isNaN(num) ? 0 : num return isNaN(num) ? 0 : num
}), }),
backgroundColor: [ backgroundColor: (context) => {
'rgba(255, 99, 132, 0.2)', const chart = context.chart
'rgba(54, 162, 235, 0.2)', const { ctx, chartArea } = chart
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)', if (!chartArea) {
'rgba(153, 102, 255, 0.2)', // This case happens on initial chart load
'rgba(255, 159, 64, 0.2)', return null
'rgba(0, 99, 132, 0.2)', }
'rgba(0, 162, 235, 0.2)',
'rgba(0, 206, 86, 0.2)', const gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top)
'rgba(0, 192, 192, 0.2)', gradient.addColorStop(0, '#4FC3F7') // Light blue at bottom
'rgba(0, 102, 255, 0.2)', gradient.addColorStop(0.3, '#2FA8E0') // Original blue
'rgba(0, 159, 64, 0.2)', gradient.addColorStop(0.7, '#1976D2') // Medium blue
], gradient.addColorStop(1, '#0D47A1') // Dark blue at top
borderColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)', return gradient
'rgba(255, 206, 86, 0.2)', },
'rgba(75, 192, 192, 0.2)', borderColor: '#2FA8E0' ,
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(0, 99, 132, 0.2)',
'rgba(0, 162, 235, 0.2)',
'rgba(0, 206, 86, 0.2)',
'rgba(0, 192, 192, 0.2)',
'rgba(0, 102, 255, 0.2)',
'rgba(0, 159, 64, 0.2)',
],
borderWidth: 1, borderWidth: 1,
}, },
], ],

View File

@ -632,9 +632,12 @@ export function useCanvasSetting(executeEffect = true) {
originHorizon: res.originHorizon, originHorizon: res.originHorizon,
originVertical: res.originVertical, originVertical: res.originVertical,
}) })
if (canvas) {
canvas.setWidth(res.originHorizon) canvas.setWidth(res.originHorizon)
canvas.setHeight(res.originVertical) canvas.setHeight(res.originVertical)
canvas.renderAll() canvas.renderAll()
}
/** 데이터 설정 */ /** 데이터 설정 */
setSettingModalFirstOptions({ setSettingModalFirstOptions({

View File

@ -260,7 +260,7 @@ export const getDegreeByChon = (chon) => {
// tan(theta) = height / base // tan(theta) = height / base
const radians = Math.atan(chon / 10) const radians = Math.atan(chon / 10)
// 라디안을 도 단위로 변환 // 라디안을 도 단위로 변환
return Number((radians * (180 / Math.PI)).toFixed(1)) return Number((radians * (180 / Math.PI)).toFixed(2))
} }
/** /**

View File

@ -7579,7 +7579,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
hipBasePoint = { x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 } hipBasePoint = { x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }
point = [mergePoint[0].x, mergePoint[0].y, mergePoint[3].x, mergePoint[3].y] point = [mergePoint[0].x, mergePoint[0].y, mergePoint[3].x, mergePoint[3].y]
const theta = Big(Math.acos(Big(line.line.attributes.planeSize).div(line.line.attributes.actualSize))) const theta = Big(Math.acos(Big(line.line.attributes.planeSize).div(
line.line.attributes.actualSize === 0 ||
line.line.attributes.actualSize === '' ||
line.line.attributes.actualSize === undefined ?
line.line.attributes.planeSize : line.line.attributes.actualSize
)))
.times(180) .times(180)
.div(Math.PI) .div(Math.PI)
.round(1) .round(1)
@ -9223,7 +9228,11 @@ const getSortedPoint = (points, lines) => {
const reCalculateSize = (line) => { const reCalculateSize = (line) => {
const oldPlaneSize = line.attributes.planeSize const oldPlaneSize = line.attributes.planeSize
const oldActualSize = line.attributes.actualSize const oldActualSize = line.attributes.actualSize
const theta = Big(Math.acos(Big(oldPlaneSize).div(oldActualSize))) const theta = Big(Math.acos(Big(oldPlaneSize).div(
oldActualSize === 0 || oldActualSize === '' || oldActualSize === undefined ?
oldPlaneSize :
oldActualSize
)))
.times(180) .times(180)
.div(Math.PI) .div(Math.PI)
const planeSize = calcLinePlaneSize({ const planeSize = calcLinePlaneSize({

File diff suppressed because it is too large Load Diff