diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 3810bd7b..da241db1 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -1263,7 +1263,7 @@ export default function Estimate({}) { }} getOptionLabel={(x) => x.clCodeNm} getOptionValue={(x) => x.clCode} - isClearable={false} + isClearable={true} isSearchable={false} value={honorificCodeList.filter(function (option) { return option.clCodeNm === estimateContextState.objectNameOmit diff --git a/src/components/estimate/EstimateFileUploader.jsx b/src/components/estimate/EstimateFileUploader.jsx index c02d4637..b02daef1 100644 --- a/src/components/estimate/EstimateFileUploader.jsx +++ b/src/components/estimate/EstimateFileUploader.jsx @@ -28,6 +28,8 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { 'application/pdf', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // PPTX 형식 + 'application/vnd.ms-powerpoint', // PPT 형식 ] Array.from(e.target.files).forEach((file) => { //엑셀, pdf, 이미지 @@ -61,6 +63,8 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { 'application/pdf', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // PPTX 형식 + 'application/vnd.ms-powerpoint', // PPT 형식 ] Array.from(e.dataTransfer.files).forEach((file) => { diff --git a/src/components/estimate/popup/EstimateCopyPop.jsx b/src/components/estimate/popup/EstimateCopyPop.jsx index 3bc25c74..564a1aae 100644 --- a/src/components/estimate/popup/EstimateCopyPop.jsx +++ b/src/components/estimate/popup/EstimateCopyPop.jsx @@ -106,7 +106,7 @@ export default function EstimateCopyPop({ planNo, setEstimateCopyPopupOpen }) { useEffect(() => { if (estimateContextState?.charger) { - setCopyReceiveUser(estimateContextState.charger) + setCopyReceiveUser(session?.userNm) } }, [estimateContextState?.charger]) diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 63ecdef3..4ce1ec27 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -159,7 +159,7 @@ export default function CanvasMenu(props) { roof.set({ selectable: true }) setSurfaceShapePattern(roof, null, false, roof.roofMaterial) delete roof.moduleCompass - drawDirectionArrow(roof) + drawDirectionArrow(roof, false) }) } @@ -184,13 +184,13 @@ export default function CanvasMenu(props) { break case 'surface': const modules = canvas.getObjects().filter((module) => module.name === POLYGON_TYPE.MODULE) + initRoofs() if (modules.length > 0) { swalFire({ text: getMessage('module.delete.confirm'), type: 'confirm', confirmFn: () => { //해당 메뉴 이동시 배치면 삭제 - initRoofs() const moduleSurfacesArray = canvas .getObjects() @@ -204,6 +204,7 @@ export default function CanvasMenu(props) { moduleSurfacesArray.forEach((moduleSurface) => { canvas.remove(moduleSurface) }) + canvas.renderAll() onClickNav(menu) } diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index 981201ec..e0d32bbc 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -563,8 +563,8 @@ export default function CircuitTrestleSetting({ id }) { goodsNo: model.goodsNo, serQtyList: [ { - serQty: result[index + 1].maxValue, - paralQty: result[index + 1].count, + serQty: result[(index + 1).toString()] ? result[(index + 1).toString()].maxValue : 0, + paralQty: result[(index + 1).toString()] ? result[(index + 1).toString()].count : 0, rmdYn: 'Y', usePossYn: 'Y', roofSurfaceList: canvas diff --git a/src/components/management/StuffSubHeader.jsx b/src/components/management/StuffSubHeader.jsx index f130b729..c22f4cb8 100644 --- a/src/components/management/StuffSubHeader.jsx +++ b/src/components/management/StuffSubHeader.jsx @@ -23,7 +23,7 @@ export default function StuffSubHeader({ type }) { const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) - const { managementState } = useContext(GlobalDataContext) + const { managementState, setManagementState } = useContext(GlobalDataContext) const [buttonStyle, setButtonStyle] = useState('') @@ -31,17 +31,20 @@ export default function StuffSubHeader({ type }) { useEffect(() => { window.scrollTo(0, 0) + setManagementState({}) }, []) useEffect(() => { - if (isObjectNotEmpty(managementState)) { - if (managementState?.createSaleStoreId === 'T01') { - if (session?.storeId !== 'T01') { - setButtonStyle('none') + if (type === 'detail') { + if (isObjectNotEmpty(managementState)) { + if (managementState?.createSaleStoreId === 'T01') { + if (session?.storeId !== 'T01') { + setButtonStyle('none') + } } } } - }, [managementState?.createSaleStoreId]) + }, [type, managementState]) const searchParams = useSearchParams() const objectNo = searchParams.get('objectNo') //url에서 물건번호 꺼내서 바로 set diff --git a/src/hooks/common/useCommonUtils.js b/src/hooks/common/useCommonUtils.js index 85cbc2bd..d5c1bd01 100644 --- a/src/hooks/common/useCommonUtils.js +++ b/src/hooks/common/useCommonUtils.js @@ -11,6 +11,7 @@ import { usePopup } from '@/hooks/usePopup' import Distance from '@/components/floor-plan/modal/distance/Distance' import { usePolygon } from '@/hooks/usePolygon' import { useObjectBatch } from '@/hooks/object/useObjectBatch' +import { BATCH_TYPE } from '@/common/common' export function useCommonUtils() { const canvas = useRecoilValue(canvasState) @@ -18,6 +19,7 @@ export function useCommonUtils() { const { addCanvasMouseEventListener, addDocumentEventListener, initEvent } = useEvent() const dimensionSettings = useRecoilValue(dimensionLineSettingsState) const dimensionLineTextFont = useRecoilValue(fontSelector('dimensionLineText')) + const lengthTextFont = useRecoilValue(fontSelector('lengthText')) const commonTextFont = useRecoilValue(fontSelector('commonText')) const [commonUtils, setCommonUtilsState] = useRecoilState(commonUtilsState) const { addPopup } = usePopup() @@ -559,7 +561,9 @@ export function useCommonUtils() { const commonCopyObject = (obj) => { if (obj) { - if (obj.name.indexOf('triangleDormer') || obj.name.indexOf('pentagonDormer')) { + //도머는 복사하기 보다 새로 호출해서 만드는 방법으로 함 + if (obj.name == BATCH_TYPE.TRIANGLE_DORMER || obj.name == BATCH_TYPE.PENTAGON_DORMER) { + //그룹 객체 0번에 도머 속성을 넣어둠 const dormerAttributes = obj._objects[0].dormerAttributes const dormerName = obj._objects[0].name @@ -572,14 +576,14 @@ export function useCommonUtils() { directionRef: dormerAttributes.directionRef, } - const buttonAct = dormerName == 'triangleDormer' ? 3 : 4 - + const buttonAct = dormerName == BATCH_TYPE.TRIANGLE_DORMER ? 3 : 4 applyDormers(dormerParams, buttonAct) } else { let clonedObj = null obj.clone((cloned) => { clonedObj = cloned + clonedObj.fontSize = lengthTextFont.fontSize.value }) addCanvasMouseEventListener('mouse:move', (e) => { @@ -614,6 +618,7 @@ export function useCommonUtils() { //배치면일 경우 if (obj.name === 'roof') { clonedObj.setCoords() + clonedObj.fire('modified') clonedObj.fire('polygonMoved') clonedObj.set({ direction: obj.direction, directionText: obj.directionText, roofMaterial: obj.roofMaterial }) diff --git a/src/hooks/module/useOrientation.js b/src/hooks/module/useOrientation.js index 9e57c687..649d8f79 100644 --- a/src/hooks/module/useOrientation.js +++ b/src/hooks/module/useOrientation.js @@ -27,6 +27,13 @@ export function useOrientation() { setCompasDeg(0) } const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) + const hasModules = canvas.getObjects().some((obj) => obj.name === 'module') + if (!hasModules) { + roofs.forEach((roof) => { + delete roof.directionText + }) + } + roofs.forEach((roof) => { roof.set({ moduleCompass: isNaN(compasDeg) ? 0 : compasDeg, diff --git a/src/hooks/module/useTrestle.js b/src/hooks/module/useTrestle.js index 73fca74e..b122a19e 100644 --- a/src/hooks/module/useTrestle.js +++ b/src/hooks/module/useTrestle.js @@ -9,6 +9,7 @@ import { basicSettingState, trestleDisplaySelector } from '@/store/settingAtom' import { useSwal } from '@/hooks/useSwal' import { useContext } from 'react' import { QcastContext } from '@/app/QcastProvider' +import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' // 모듈간 같은 행, 열의 마진이 10 이하인 경우는 같은 행, 열로 간주 const MODULE_MARGIN = 10 @@ -22,6 +23,9 @@ export const useTrestle = () => { const isTrestleDisplay = useRecoilValue(trestleDisplaySelector) const { swalFire } = useSwal() const { setIsGlobalLoading } = useContext(QcastContext) + + const { getSelectedPcsItemList } = useCircuitTrestle() + const apply = () => { const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit) if (notAllocationModules.length > 0) { @@ -723,11 +727,7 @@ export const useTrestle = () => { // circuitItemList 중복제거 circuitItemList = circuitItemList.filter((item, index) => circuitItemList.indexOf(item) === index) - circuitItemList = circuitItemList.map((circuitId) => { - return { - itemId: circuitId, - } - }) + circuitItemList = getSelectedPcsItemList() return { itemList, northArrangement, roofSurfaceList, circuitItemList } } diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index ff9bf24d..61a785bc 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -5,7 +5,7 @@ import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { BATCH_TYPE, INPUT_TYPE, POLYGON_TYPE } from '@/common/common' import { useEvent } from '@/hooks/useEvent' -import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon, triangleToPolygon, toFixedWithoutRounding } from '@/util/canvas-util' +import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon, triangleToPolygon, getDegreeByChon } from '@/util/canvas-util' import { useSwal } from '@/hooks/useSwal' import * as turf from '@turf/turf' import { usePolygon } from '@/hooks/usePolygon' @@ -273,6 +273,9 @@ export function useObjectBatch({ isHidden, setIsHidden }) { const dormerName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER : BATCH_TYPE.PENTAGON_DORMER const dormerTempName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER_TEMP : BATCH_TYPE.PENTAGON_DORMER_TEMP + //도머의 각도 + const dormerAngle = getDegreeByChon(pitch) + let dormer, dormerOffset, isDown, selectedSurface, pentagonPoints, pentagonOffsetPoints const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) @@ -284,11 +287,10 @@ export function useObjectBatch({ isHidden, setIsHidden }) { return } + let theta = 0 + //삼각형 도머 if (buttonAct === 3) { - const bottomLength = Math.floor((height / Math.cos(Math.atan(pitch / 10))) * 10) / 10 - const bottomOffsetLength = Math.floor(((height + offsetRef) / Math.cos(Math.atan(pitch / 10))) * 10) / 10 - let groupDormerPoints = [] //나중에 offset을 위한 포인트 저장용 addCanvasMouseEventListener('mouse:move', (e) => { @@ -306,6 +308,13 @@ export function useObjectBatch({ isHidden, setIsHidden }) { console.log('selectedSurface', selectedSurface) + const roofAngle = selectedSurface.roofMaterial.angle + + theta = Math.atan(Math.tan((roofAngle * Math.PI) / 180) / Math.tan((dormerAngle * Math.PI) / 180)) + + const bottomLength = Number((Math.tan(theta) * height).toFixed()) + const bottomOffsetLength = Number((Math.tan(theta) * (height + offsetRef)).toFixed()) + let angle = 0 if (directionRef === 'left') { //서 diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index ed7b2ca1..07532422 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -181,7 +181,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { const batchSurface = new QPolygon(obj.getCurrentPoints(), { fill: 'transparent', stroke: 'red', - strokeWidth: 1, + strokeWidth: 3, strokeDasharray: [10, 4], fontSize: 12, selectable: true, diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 3e706b84..04507c17 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -172,8 +172,9 @@ export const usePolygon = () => { /** * poolygon의 방향에 따라 화살표를 추가한다. * @param polygon + * @param showDirectionText */ - const drawDirectionArrow = (polygon) => { + const drawDirectionArrow = (polygon, showDirectionText = true) => { if (polygon.points.length < 3) { return } @@ -319,17 +320,16 @@ export const usePolygon = () => { pitch: polygon.roofMaterial?.pitch ?? 4, parentId: polygon.id, }) - arrow.setViewLengthText(false) polygon.arrow = arrow polygon.canvas.add(arrow) polygon.canvas.renderAll() - drawDirectionStringToArrow2(polygon) + drawDirectionStringToArrow2(polygon, showDirectionText) // drawDirectionStringToArrow() } //arrow의 compass 값으로 방향 글자 설정 필요 - const drawDirectionStringToArrow2 = (polygon) => { + const drawDirectionStringToArrow2 = (polygon, showDirectionText) => { const { direction, surfaceCompass, moduleCompass, arrow } = polygon if (moduleCompass === null || moduleCompass === undefined) { const textObj = new fabric.Text(`${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText}`, { @@ -510,24 +510,27 @@ export const usePolygon = () => { text = text + (sameDirectionCnt.length + 1) polygon.set('directionText', text) - const textObj = new fabric.Text(`${text} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})`, { - fontFamily: flowFontOptions.fontFamily.value, - fontWeight: flowFontOptions.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', - fontStyle: flowFontOptions.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', - fontSize: flowFontOptions.fontSize.value, - fill: flowFontOptions.fontColor.value, - pitch: arrow.pitch, - originX: 'center', - originY: 'center', - name: 'flowText', - originText: text, - selectable: false, - left: arrow.stickeyPoint.x, - top: arrow.stickeyPoint.y, - parent: arrow, - parentId: arrow.id, - visible: isFlowDisplay, - }) + const textObj = new fabric.Text( + `${showDirectionText && text} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})`, + { + fontFamily: flowFontOptions.fontFamily.value, + fontWeight: flowFontOptions.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', + fontStyle: flowFontOptions.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', + fontSize: flowFontOptions.fontSize.value, + fill: flowFontOptions.fontColor.value, + pitch: arrow.pitch, + originX: 'center', + originY: 'center', + name: 'flowText', + originText: text, + selectable: false, + left: arrow.stickeyPoint.x, + top: arrow.stickeyPoint.y, + parent: arrow, + parentId: arrow.id, + visible: isFlowDisplay, + }, + ) polygon.canvas.add(textObj) } @@ -755,10 +758,7 @@ export const usePolygon = () => { // innerLine이 세팅이 안되어있는경우 찾아서 세팅한다. if (!innerLines || innerLines.length === 0) { - let innerLineTypes = [] - Object.keys(LINE_TYPE.SUBLINE).forEach((key, value) => { - innerLineTypes.push(LINE_TYPE.SUBLINE[key]) - }) + let innerLineTypes = Object.keys(LINE_TYPE.SUBLINE).map((key, value) => LINE_TYPE.SUBLINE[key]) polygon.innerLines = canvas .getObjects() .filter( @@ -1102,6 +1102,8 @@ export const usePolygon = () => { } }) + // blue로 생성된 것들은 대표라인이 될 수 없음. + representLines = representLines.filter((line) => line.stroke !== 'blue') // representLines중 가장 긴 line을 찾는다. representLines.forEach((line) => { if (!representLine) {